Files
homelab-docs/SSH-ACCESS.md
2026-01-05 12:28:33 -05:00

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:

  1. Generate new key pair:

    ssh-keygen -t ed25519 -f ~/.ssh/homelab-new -C "homelab-new"
    
  2. 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
    
  3. Update ~/.ssh/config to use new key:

    IdentityFile ~/.ssh/homelab-new
    
  4. 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
    
  5. 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


Last Updated: 2025-12-22