On this page
I SSH into servers maybe thirty times a day. Without a proper SSH config, that would mean typing out usernames, hostnames, ports, and key paths every single time. Life is too short for that.
The Basics#
The SSH config lives at ~/.ssh/config. Here is a minimal example:
Host myserver
HostName 203.0.113.50
User root
IdentityFile ~/.ssh/id_ed25519Now ssh myserver is all you need. But it gets better.
Jump Hosts#
If you need to reach a server through a bastion:
Host bastion
HostName bastion.example.com
User admin
Host internal
HostName 10.0.1.50
User deploy
ProxyJump bastionssh internal automatically tunnels through the bastion. No manual port forwarding, no two-step login.
Wildcard Hosts#
This is the one most people miss:
Host *.prod
User deploy
IdentityFile ~/.ssh/prod_key
StrictHostKeyChecking accept-new
Host web.prod
HostName 10.0.1.10
Host api.prod
HostName 10.0.1.11
Host db.prod
HostName 10.0.1.12The wildcard block sets defaults for anything ending in .prod. Individual host blocks just add the hostname. You get consistent configuration without repetition.
Keep Connections Alive#
Add this to your Host * block:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yesServerAliveInterval sends a keepalive every 60 seconds. This stops firewalls and NATs from killing idle connections. AddKeysToAgent automatically loads keys into ssh-agent after first use.
Connection Multiplexing#
This is the real speed trick:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600The first SSH connection to a host creates a socket. Subsequent connections to the same host reuse it. No new TCP handshake, no new key exchange. The second ssh myserver connects instantly.
ControlPersist 600 keeps the socket alive for 10 minutes after you disconnect. So if you SSH in, run a command, disconnect, and SSH back in within 10 minutes, the second connection is instant.
Create the socket directory first:
mkdir -p ~/.ssh/socketsPort Forwarding Shortcuts#
Host db-tunnel
HostName myserver.com
User admin
LocalForward 5432 localhost:5432
RequestTTY no
ExitOnForwardFailure yesNow ssh db-tunnel opens a tunnel to the remote Postgres. No remembering the -L syntax. ExitOnForwardFailure means if the port is already in use, SSH exits instead of connecting without the tunnel.
SSHFP for Host Verification#
Tired of the “Are you sure you want to continue connecting?” messages? If you control the DNS, add SSHFP records:
ssh-keygen -r myserver.comThis outputs DNS records you can add to your zone. Then set:
Host *
VerifyHostKeyDNS yesSSH verifies the host key against DNS automatically. No more blindly accepting fingerprints.
The SSH config file is probably the highest-leverage dotfile you can invest time in. Five minutes of setup saves thousands of keystrokes.