Typing ssh -p 2222 -i ~/.ssh/id_work [email protected] every time gets old fast. The SSH client config file stores those settings per host, so you just type ssh web1. The same aliases work for scp, rsync, sftp, Git and tools like Ansible and VS Code Remote.
Where it lives
- Per user:
~/.ssh/config - System-wide:
/etc/ssh/ssh_config
Create it with the right permissions:
touch ~/.ssh/config
chmod 600 ~/.ssh/config
On Windows, it’s C:\Users\<you>\.ssh\config.
A first entry
Host web1
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Now:
ssh web1
scp backup.tar.gz web1:/tmp/
rsync -avz ./site/ web1:/var/www/site/
IdentitiesOnly yes makes SSH offer only the listed key, avoiding “Too many authentication failures” when your agent holds many keys.
Common options
| Option | Purpose |
|---|---|
HostName |
Real hostname or IP |
User |
Login user |
Port |
SSH port |
IdentityFile |
Private key to use |
IdentitiesOnly |
Only use the configured key |
ProxyJump |
Connect through a bastion host |
LocalForward / RemoteForward |
Port forwarding |
ServerAliveInterval |
Keepalive packets |
ForwardAgent |
Agent forwarding (use carefully) |
StrictHostKeyChecking |
Host key verification behaviour |
Compression |
Compress traffic (slow links) |
Wildcards and defaults
The first value found for each option wins, so put specific hosts at the top and general defaults at the bottom:
Host db1
HostName 10.0.0.5
ProxyJump bastion
Host *.prod.example.com
User admin
IdentityFile ~/.ssh/id_prod
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
AddKeysToAgent yes
ServerAliveInterval 30 sends a keepalive every 30 seconds — the fix for sessions that freeze or drop when idle behind NAT routers. See SSH keepalive and timeouts.
Jump hosts (bastions)
Reach private servers through a bastion in one command:
Host bastion
HostName 203.0.113.50
User alice
Host app1 app2
User deploy
ProxyJump bastion
Host app1
HostName 10.0.0.11
Host app2
HostName 10.0.0.12
ssh app1 connects to the bastion, then on to 10.0.0.11 — your private key never leaves your computer. More in ProxyJump.
Port forwarding presets
Always open a tunnel to a remote database when you connect:
Host db-tunnel
HostName 203.0.113.10
User deploy
LocalForward 5433 127.0.0.1:5432
ExitOnForwardFailure yes
ssh -N db-tunnel # -N: no shell, just the tunnel
Then connect your database client to 127.0.0.1:5433. See SSH tunnels and port forwarding.
Faster repeated connections: multiplexing
Reuse one TCP connection for many SSH sessions — later logins are nearly instant, which speeds up Ansible and repeated scp:
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
See SSH multiplexing.
GitHub with multiple accounts
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
git clone git@github-work:company/repo.git
Splitting the config
Recent OpenSSH supports includes — handy for team-shared host lists:
Include ~/.ssh/config.d/*
Put it at the top of ~/.ssh/config.
Agent forwarding: be careful
ForwardAgent yes lets a remote server use your local SSH agent — convenient for git pull on a server, but anyone with root on that server can use your agent while you’re connected. Prefer ProxyJump for hopping between servers, and deploy keys on servers for Git.
Check what SSH will use
ssh -G web1 | grep -E '^(hostname|user|port|identityfile|proxyjump)'
ssh -G prints the final configuration for a host after all rules are applied — the quickest way to debug which settings win.
Troubleshooting
Bad owner or permissions on ~/.ssh/config—chmod 600 ~/.ssh/configand make sure you own it.- Settings ignored — an earlier
Hostblock (orHost *placed at the top) set the option first. Reorder. - Tabs vs spaces — both work; indentation is only for readability.
Related: SSH keys, scp and SSH into your VPS.