unix / ssh

I reach my VMs and Git hosts over SSH.

Keys

I use one Ed25519 key pair:

ssh-keygen -t ed25519 -C "[email protected]"

The public half, ~/.ssh/id_ed25519.pub, goes on the server in ~/.ssh/authorized_keys or the provider's UI. The private half stays on my laptop.

Host aliases

Without config, each command repeats the IP, user, and key:

ssh -i ~/.ssh/id_ed25519 croaky@203.0.113.10

A Host block in ~/.ssh/config shortens that to ssh sockeye-server:

Host sockeye-server
  HostName 203.0.113.10
  User croaky
  IdentityFile ~/.ssh/id_ed25519

scp and rsync accept the alias:

scp ./sockeye sockeye-server:/tmp/sockeye

Jump hosts

Some VMs have no public IPv4 address. I reach them through a VM that has one. ProxyJump makes SSH open the first connection, then run the second through it:

Host app-server
  HostName 10.0.0.12
  User croaky
  ProxyJump front-server

ssh app-server, scp, and rsync all use the jump. Nothing runs on the middle host except sshd. My laptop holds the private key. The key does not need to be on front-server.

Trust the host key from a second source

The first connection to a host asks whether to trust its key. With BatchMode=yes in scripts, SSH refuses an unknown key and prints Host key verification failed. I keep this check enabled.

I obtain the fingerprint directly on the host through a secure out-of-band channel, such as the cloud provider's console:

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

I compare that fingerprint with the string SSH displays. For automated scripts, I add the verified key to ~/.ssh/known_hosts beforehand rather than setting StrictHostKeyChecking=no.

Jump host or VPN

A VPN or a jump host connects to a VM with no public address. I use a VPN on personal machines and a jump host on work machines. The jump host needs only my public key and four configuration lines.

Keep SSH off public IPv6

Cloud firewalls evaluate IPv4 and IPv6 rules independently. Public web servers require ports 80 and 443 open on IPv6, but do not require port 22. I restrict port 22 access to the private network and the jump host.

Splitting config

My dotfiles are public, so ~/.ssh/config holds only safe defaults. Machine-specific hosts live in files it includes:

# ~/.ssh/config
Include ~/.ssh/config.private*

I keep the VM aliases in ~/.ssh/config.private, outside the repo. SSH ignores a config file that is group- or world-readable, so I chmod 600 it.

I automate the rest of my machine setup in cmd / laptop.

← All articles