Skip to content

SSH Key Orchestration

One keypair per purpose, not per host. Personal keys and automation (Claude) keys stay separate so either can be revoked without touching the other.

Key matrix

Key (in ~/.ssh/) Purpose Authorized on State (2026-07-24)
mdh-2022 / id_ed25519 Personal interactive use pve1, pve2, pve3, LXCs active
claude-code-lan Claude Code → homelab LAN pve1, pve2, pve3, VM 121 (jarvis) active
claude-code-lan Claude Code → Unraid Holly (port 22159) active
claude-code-ops Claude Code → MDHosting ops servers ops fleet (see mdhosting-docs) active

Service keys (not on the workstation)

Key Lives on Authorized on Restriction
wol-pbs orchestrator CT 101 (the wol-pbs container) pve3 (root) Forced-command restricted — may only power the node off or start pbs-offsite-sync; nothing else executes

Added 2026-07-30 with the pve3 wake-on-LAN backup setup (see Proxmox). The same orchestrator talks to PBS with the read-only API token api@pbs!wolpbs — service credentials follow the same one-purpose, least-privilege rule as the keys above.

Rules

  1. Claude never uses personal keys. If a Claude key isn't authorized on a host, the fix is to authorize it — not to borrow id_ed25519.
  2. One purpose, one key. LAN automation and ops automation stay on separate keys so a leak on one side never crosses the boundary.
  3. Authorize via the host's own management channel (Proxmox shell, Unraid UI → Users → root → SSH authorized keys), never by an agent appending to authorized_keys itself.
  4. Rotation: generate replacement → authorize alongside old → flip ~/.ssh/config → remove old key from every host → delete private key. Rotate any key on suspicion, and the LAN key when a device holding it is retired.

Outstanding actions

Done — August 2026

claude-code-lan is authorized on all three pve nodes (pve1 .199, pve2 .151, pve3 .28), VM 121 (jarvis, .252), and Holly (.200:22159), and is in active daily use. The older claude-code key also works on Holly, but claude-code-lan is the documented convention.

~/.ssh/config aliases

Host pve1
    HostName 192.168.1.199
    User root
    IdentityFile ~/.ssh/claude-code-lan
    IdentitiesOnly yes

Host pve2
    HostName 192.168.1.151
    User root
    IdentityFile ~/.ssh/claude-code-lan
    IdentitiesOnly yes

Host pve3
    HostName 192.168.1.28
    User root
    IdentityFile ~/.ssh/claude-code-lan
    IdentitiesOnly yes
    HostKeyAlias pve3

Host jarvis
    HostName 192.168.1.252
    User jarvis
    IdentityFile ~/.ssh/claude-code-lan
    IdentitiesOnly yes

Host holly
    HostName 192.168.1.200
    Port 22159
    User root
    IdentityFile ~/.ssh/claude-code-lan
    IdentitiesOnly yes

(Keep personal-key variants under different aliases, e.g. pve1-me.)

Future: signed certificates

If key sprawl returns, the next step is a small SSH CA (ssh-keygen -s) issuing short-lived certs per principal — hosts then trust one CA key instead of N user keys. Overkill today at 3 LAN hosts; revisit when the NAS rebuild adds more.