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

See Git SSH keys for GitHub.

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/config and make sure you own it.
  • Settings ignored — an earlier Host block (or Host * 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.

  • SSH
  • Productivity
  • Linux