12 KiB
SSH Access
Documentation for SSH access to all homelab systems, including key authentication, password authentication for special cases, and QEMU guest agent usage.
Overview
Most systems use SSH key authentication with the ~/.ssh/homelab key. A few special cases require password authentication (router, Windows PC) due to platform limitations.
SSH Password: GrilledCh33s3# (for systems without key auth)
SSH Key Authentication (Primary Method)
SSH Key Configuration
SSH keys are configured in ~/.ssh/config on both Mac Mini and MacBook.
Key file: ~/.ssh/homelab (Ed25519 key)
Key deployed to: All Proxmox hosts, VMs, and LXCs (13 total hosts)
Host Aliases
Use these convenient aliases instead of IP addresses:
| Host Alias | IP | User | Type | Notes |
|---|---|---|---|---|
ucg-fiber / gateway |
10.10.10.1 | root | UniFi Gateway | Router/firewall |
pve |
10.10.10.120 | root | Proxmox | Primary server |
pve2 |
10.10.10.102 | root | Proxmox | Secondary server |
truenas |
10.10.10.200 | root | VM | NAS/storage |
saltbox |
10.10.10.100 | hutson | VM | Media automation |
lmdev1 |
10.10.10.111 | hutson | VM | AI/LLM development |
docker-host |
10.10.10.206 | hutson | VM | Docker services (PVE) |
docker-host2 |
10.10.10.207 | hutson | VM | Docker services (PVE2) - MetaMCP, n8n |
fs-dev |
10.10.10.5 | hutson | VM | Development |
copyparty |
10.10.10.201 | hutson | VM | File sharing |
gitea-vm |
10.10.10.220 | hutson | VM | Git server |
trading-vm |
10.10.10.221 | hutson | VM | AI trading platform |
pihole |
10.10.10.10 | root | LXC | DNS/Ad blocking |
traefik |
10.10.10.250 | root | LXC | Reverse proxy |
findshyt |
10.10.10.8 | root | LXC | Custom app |
Usage Examples
# List VMs on PVE
ssh pve 'qm list'
# Check ZFS pool on TrueNAS
ssh truenas 'zpool status vault'
# List Docker containers on Saltbox
ssh saltbox 'docker ps'
# Check Pi-hole status
ssh pihole 'pihole status'
# View Traefik config
ssh pve 'pct exec 202 -- cat /etc/traefik/traefik.yaml'
SSH Config File
Location: ~/.ssh/config
Example entries:
# Proxmox Servers
Host pve
HostName 10.10.10.120
User root
IdentityFile ~/.ssh/homelab
Host pve2
HostName 10.10.10.102
User root
IdentityFile ~/.ssh/homelab
# Post-quantum KEX causes MTU issues - use classic
KexAlgorithms curve25519-sha256
# VMs
Host truenas
HostName 10.10.10.200
User root
IdentityFile ~/.ssh/homelab
Host saltbox
HostName 10.10.10.100
User hutson
IdentityFile ~/.ssh/homelab
Host lmdev1
HostName 10.10.10.111
User hutson
IdentityFile ~/.ssh/homelab
Host docker-host
HostName 10.10.10.206
User hutson
IdentityFile ~/.ssh/homelab
Host docker-host2
HostName 10.10.10.207
User hutson
IdentityFile ~/.ssh/homelab
Host fs-dev
HostName 10.10.10.5
User hutson
IdentityFile ~/.ssh/homelab
Host copyparty
HostName 10.10.10.201
User hutson
IdentityFile ~/.ssh/homelab
Host gitea-vm
HostName 10.10.10.220
User hutson
IdentityFile ~/.ssh/homelab
Host trading-vm
HostName 10.10.10.221
User hutson
IdentityFile ~/.ssh/homelab
# LXC Containers
Host pihole
HostName 10.10.10.10
User root
IdentityFile ~/.ssh/homelab
Host traefik
HostName 10.10.10.250
User root
IdentityFile ~/.ssh/homelab
Host findshyt
HostName 10.10.10.8
User root
IdentityFile ~/.ssh/homelab
Password Authentication (Special Cases)
Some systems don't support SSH key auth or have other limitations.
UniFi Router (10.10.10.1) - NOW USES KEY AUTH
Host alias: ucg-fiber or gateway
Status: SSH key authentication now works (as of 2026-01-02)
Commands:
# Run command on router (using SSH key)
ssh ucg-fiber 'hostname'
# Get ARP table (all device IPs)
ssh ucg-fiber 'cat /proc/net/arp'
# Check Tailscale status
ssh ucg-fiber 'tailscale status'
# Check memory usage
ssh ucg-fiber 'free -m'
Note: Key may need to be re-deployed after firmware updates if UniFi clears authorized_keys.
Windows PC (10.10.10.150)
OS: Windows with OpenSSH server
User: claude
Password: GrilledCh33s3#
Shell: PowerShell (not bash)
Commands:
# Run PowerShell command
sshpass -p 'GrilledCh33s3#' ssh claude@10.10.10.150 'Get-Process | Select -First 5'
# Check Syncthing status
sshpass -p 'GrilledCh33s3#' ssh claude@10.10.10.150 'Get-Process -Name syncthing -ErrorAction SilentlyContinue'
# Restart Syncthing
sshpass -p 'GrilledCh33s3#' ssh claude@10.10.10.150 'Stop-Process -Name syncthing -Force; Start-ScheduledTask -TaskName "Syncthing"'
⚠️ Important: Use ; (semicolon) to chain PowerShell commands, NOT && (bash syntax).
Why not key auth?: Could be configured, but password auth works and is simpler for Windows.
QEMU Guest Agent
Most VMs have the QEMU guest agent installed, allowing command execution without SSH.
VMs with QEMU Agent
| VMID | VM Name | Use Case |
|---|---|---|
| 100 | truenas | Execute commands, check ZFS |
| 101 | saltbox | Execute commands, Docker mgmt |
| 105 | fs-dev | Execute commands |
| 111 | lmdev1 | Execute commands |
| 201 | copyparty | Execute commands |
| 206 | docker-host | Execute commands |
| 300 | gitea-vm | Execute commands |
| 301 | trading-vm | Execute commands |
VM WITHOUT QEMU Agent
VMID 110 (homeassistant): No QEMU agent installed
- Access via web UI only
- Or install SSH server manually if needed
Usage Examples
Basic syntax:
ssh pve 'qm guest exec VMID -- bash -c "COMMAND"'
Examples:
# Check ZFS pool on TrueNAS (without SSH)
ssh pve 'qm guest exec 100 -- bash -c "zpool status vault"'
# Get VM IP addresses
ssh pve 'qm guest exec 100 -- bash -c "ip addr"'
# Check Docker containers on Saltbox
ssh pve 'qm guest exec 101 -- bash -c "docker ps"'
# Run multi-line command
ssh pve 'qm guest exec 100 -- bash -c "df -h; free -h; uptime"'
When to use QEMU agent vs SSH:
- ✅ Use SSH for interactive sessions, file editing, complex tasks
- ✅ Use QEMU agent for one-off commands, when SSH is down, or VM has no network
- ⚠️ QEMU agent is slower for multiple commands (use SSH instead)
Troubleshooting SSH Issues
Connection Refused
# Check if SSH service is running
ssh pve 'systemctl status sshd'
# Check if port 22 is open
nc -zv 10.10.10.XXX 22
# Check firewall
ssh pve 'iptables -L -n | grep 22'
Permission Denied (Public Key)
# Verify key file exists
ls -la ~/.ssh/homelab
# Check key permissions (should be 600)
chmod 600 ~/.ssh/homelab
# Test SSH key auth verbosely
ssh -vvv -i ~/.ssh/homelab root@10.10.10.120
# Check authorized_keys on remote (via QEMU agent if SSH broken)
ssh pve 'qm guest exec VMID -- bash -c "cat ~/.ssh/authorized_keys"'
Slow SSH Connection (PVE2 Issue)
Problem: SSH to PVE2 hangs for 30+ seconds before connecting Cause: MTU mismatch (vmbr0=9000, nic1=1500) causing post-quantum KEX packet fragmentation Fix: Use classic KEX algorithm instead
In ~/.ssh/config:
Host pve2
HostName 10.10.10.102
User root
IdentityFile ~/.ssh/homelab
KexAlgorithms curve25519-sha256 # Avoid mlkem768x25519-sha256
Permanent fix: Set nic1 MTU to 9000 in /etc/network/interfaces on PVE2
Adding SSH Keys to New Systems
Linux (VMs/LXCs)
# Copy public key to new host
ssh-copy-id -i ~/.ssh/homelab user@hostname
# Or manually:
ssh user@hostname 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys' < ~/.ssh/homelab.pub
ssh user@hostname 'chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys'
LXC Containers (Root User)
# Via pct exec from Proxmox host
ssh pve 'pct exec CTID -- bash -c "mkdir -p /root/.ssh"'
ssh pve 'pct exec CTID -- bash -c "echo \"$(cat ~/.ssh/homelab.pub)\" >> /root/.ssh/authorized_keys"'
ssh pve 'pct exec CTID -- bash -c "chmod 700 /root/.ssh && chmod 600 /root/.ssh/authorized_keys"'
# Also enable PermitRootLogin in sshd_config
ssh pve 'pct exec CTID -- bash -c "sed -i \"s/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/\" /etc/ssh/sshd_config"'
ssh pve 'pct exec CTID -- bash -c "systemctl restart sshd"'
VMs (via QEMU Agent)
# Add key via QEMU agent (if SSH not working)
ssh pve 'qm guest exec VMID -- bash -c "mkdir -p ~/.ssh"'
ssh pve 'qm guest exec VMID -- bash -c "echo \"$(cat ~/.ssh/homelab.pub)\" >> ~/.ssh/authorized_keys"'
ssh pve 'qm guest exec VMID -- bash -c "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"'
SSH Key Management
Rotate SSH Keys (Future)
When rotating SSH keys:
-
Generate new key pair:
ssh-keygen -t ed25519 -f ~/.ssh/homelab-new -C "homelab-new" -
Deploy new key to all hosts (keep old key for now):
for host in pve pve2 truenas saltbox lmdev1 docker-host fs-dev copyparty gitea-vm trading-vm pihole traefik findshyt; do ssh-copy-id -i ~/.ssh/homelab-new $host done -
Update
~/.ssh/configto use new key:IdentityFile ~/.ssh/homelab-new -
Test all connections:
for host in pve pve2 truenas saltbox lmdev1 docker-host fs-dev copyparty gitea-vm trading-vm pihole traefik findshyt; do echo "Testing $host..." ssh $host 'hostname' done -
Remove old key from all hosts once confirmed working
Quick Reference
Common SSH Operations
# Execute command on remote host
ssh host 'command'
# Execute multiple commands
ssh host 'command1 && command2'
# Copy file to remote
scp file host:/path/
# Copy file from remote
scp host:/path/file ./
# Execute command on Proxmox VM (via QEMU agent)
ssh pve 'qm guest exec VMID -- bash -c "command"'
# Execute command on LXC
ssh pve 'pct exec CTID -- command'
# Interactive shell
ssh host
# SSH with X11 forwarding
ssh -X host
Troubleshooting Commands
# Test SSH with verbose output
ssh -vvv host
# Check SSH service status (remote)
ssh host 'systemctl status sshd'
# Check SSH config (local)
ssh -G host
# Test port connectivity
nc -zv hostname 22
Security Best Practices
Current Security Posture
✅ Good:
- SSH keys used instead of passwords (where possible)
- Keys use Ed25519 (modern, secure algorithm)
- Root login disabled on VMs (use sudo instead)
- SSH keys have proper permissions (600)
⚠️ Could Improve:
- Disable password authentication on all hosts (force key-only)
- Use SSH certificate authority instead of individual keys
- Set up SSH bastion host (jump server)
- Enable 2FA for SSH (via PAM + Google Authenticator)
- Implement SSH key rotation policy (annually)
Hardening SSH (Future)
For additional security, consider:
# /etc/ssh/sshd_config (on remote hosts)
PermitRootLogin prohibit-password # No root password login
PasswordAuthentication no # Disable password auth entirely
PubkeyAuthentication yes # Only allow key auth
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3 # Limit auth attempts
MaxSessions 10 # Limit concurrent sessions
ClientAliveInterval 300 # Timeout idle sessions
ClientAliveCountMax 2 # Drop after 2 keepalives
Apply after editing:
systemctl restart sshd
Related Documentation
- VMS.md - Complete VM/CT inventory
- NETWORK.md - Network configuration
- IP-ASSIGNMENTS.md - IP addresses for all hosts
- SECURITY.md - Security policies (coming soon)
Last Updated: 2025-12-22