SSH Keys

SSH key generation, management, and certificate-based authentication patterns.

Key Generation

Generate ed25519 key — the modern default, fast and secure
ssh-keygen -t ed25519 -C "evan@domusdigitalis.dev" -f ~/.ssh/id_ed25519
Generate RSA key — when legacy systems require it (ISE, older appliances)
ssh-keygen -t rsa -b 4096 -C "evan@domusdigitalis.dev" -f ~/.ssh/id_rsa_legacy
Generate key with no passphrase — automation only, never for interactive use
ssh-keygen -t ed25519 -C "automation@domusdigitalis.dev" -f ~/.ssh/id_automation -N ""
Unprotected keys are acceptable only for service accounts with restricted authorized_keys options (forced command, IP restriction).

SSH Agent

Start the agent and add your key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
List loaded keys — verify what the agent is offering
ssh-add -l
Remove all keys from agent
ssh-add -D
Add key with lifetime — auto-expires from agent after 4 hours
ssh-add -t 4h ~/.ssh/id_ed25519

Authorized Keys

Copy public key to a remote host
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote-host
Manual copy — when ssh-copy-id is unavailable
cat ~/.ssh/id_ed25519.pub | ssh user@remote-host 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
Restrict a key in authorized_keys — forced command + IP restriction
command="/usr/local/bin/backup-only.sh",from="10.50.1.0/24",no-pty,no-port-forwarding ssh-ed25519 AAAA... automation@domusdigitalis.dev

This is the correct way to handle automation keys: the key can only run one command, from one subnet, with no interactive shell.

Key Fingerprints

Show fingerprint of a public key
ssh-keygen -lf ~/.ssh/id_ed25519.pub
Show fingerprint in visual ASCII art — helps manual comparison
ssh-keygen -lvf ~/.ssh/id_ed25519.pub
Show fingerprint of a remote host — verify before first connect
ssh-keygen -lf <(ssh-keyscan -t ed25519 remote-host 2>/dev/null)

Format Conversion

Convert OpenSSH key to PEM format — needed for some tools (openssl, Vault)
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa_legacy
Extract public key from private key
ssh-keygen -yf ~/.ssh/id_ed25519 > recovered_pub.pub
Convert PEM to OpenSSH format
ssh-keygen -i -m PEM -f key.pem > key_openssh.pub

SSH Certificate Authority

SSH certificates replace the known_hosts trust-on-first-use model with a CA trust model. The CA signs host and user keys; clients trust the CA, not individual keys.

Generate a CA key pair — this is your signing authority
ssh-keygen -t ed25519 -f /etc/ssh/ca/ssh_ca -C "SSH CA for domusdigitalis.dev"

Host Certificates

Sign a host key — the server proves its identity to clients
ssh-keygen -s /etc/ssh/ca/ssh_ca \
    -I "web-server.inside.domusdigitalis.dev" \
    -h \
    -n "web-server.inside.domusdigitalis.dev,web-server,10.50.1.100" \
    -V +52w \
    /etc/ssh/ssh_host_ed25519_key.pub

Flags: -h marks it as a host cert. -n lists valid principals (hostnames/IPs). -V sets validity.

Client trusts the CA — add to ~/.ssh/known_hosts
@cert-authority *.inside.domusdigitalis.dev ssh-ed25519 AAAA...ca-public-key...

User Certificates

Sign a user key — the user proves identity to servers
ssh-keygen -s /etc/ssh/ca/ssh_ca \
    -I "evan@domusdigitalis.dev" \
    -n "evan,root" \
    -V +24h \
    ~/.ssh/id_ed25519.pub

Short validity (+24h) is deliberate: certificates should be short-lived and re-issued, not long-lived like static keys.

Server trusts the CA — add to sshd_config
TrustedUserCAKeys /etc/ssh/ca/ssh_ca.pub
Inspect a certificate — verify principals, validity, extensions
ssh-keygen -Lf ~/.ssh/id_ed25519-cert.pub

Vault-Signed SSH Certificates

Vault as SSH CA eliminates manual key signing. Users authenticate to Vault, get a short-lived cert.

Sign a key via Vault SSH engine
vault write -field=signed_key ssh-client-signer/sign/default \
    public_key=@$HOME/.ssh/id_ed25519.pub > ~/.ssh/id_ed25519-cert.pub
One-liner: sign and verify
vault write -field=signed_key ssh-client-signer/sign/default \
    public_key=@$HOME/.ssh/id_ed25519.pub > ~/.ssh/id_ed25519-cert.pub \
    && ssh-keygen -Lf ~/.ssh/id_ed25519-cert.pub

Troubleshooting

Debug SSH connection — shows key negotiation, auth attempts
ssh -vvv user@remote-host
Check permissions — SSH refuses keys with wrong permissions
ls -la ~/.ssh/
# Expected: directory 700, private keys 600, public keys 644, authorized_keys 600
Fix permissions in one pass
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_* ~/.ssh/authorized_keys 2>/dev/null && chmod 644 ~/.ssh/*.pub 2>/dev/null