Blog
4 min read

The SSH Config File Explained: Stop Typing Long SSH Commands

~/.ssh/config turns ssh -i ~/.ssh/key -p 2222 deploy@203.0.113.10 into ssh prod. Where the file lives on each OS, the options worth knowing, multiple GitHub accounts, jump hosts, keep-alives, and the precedence rule that trips people up.

If you connect to more than one server, you've probably typed something like this:

ssh -i ~/.ssh/work_key -p 2222 deploy@203.0.113.10

The SSH config file lets you give that connection a short name and put the details in one place:

ssh prod

Every tool that uses SSH — git, scp, rsync, VS Code Remote SSH — reads the same file, so the short name works everywhere.

Where it lives

System Path
macOS / Linux ~/.ssh/config
Windows (OpenSSH) C:\Users\you\.ssh\config

It's a plain text file with no extension. If it doesn't exist, create it. It should be readable only by you:

chmod 600 ~/.ssh/config

(Linux file permissions explained.)

The basic shape

Host prod
  HostName 203.0.113.10
  User deploy
  Port 2222
  IdentityFile ~/.ssh/work_key
  IdentitiesOnly yes
  • Host — the nickname you'll type. Can include wildcards.
  • HostName — the real address (IP or domain).
  • User — the username on the server.
  • Port — if not the default 22.
  • IdentityFile — which private key to use. (SSH keys explained.)
  • IdentitiesOnly yes — use only that key, rather than trying every key in your agent (which can trigger "Too many authentication failures").

Indentation is optional but makes the file readable.

Options worth knowing

Host *
  ServerAliveInterval 60
  ServerAliveCountMax 3
  AddKeysToAgent yes
  • ServerAliveInterval 60 — send a keep-alive every 60 seconds, so idle connections don't get dropped by routers and firewalls. Fixes many "my SSH session froze" complaints.

  • AddKeysToAgent yes — add the key to your SSH agent after first use, so you type its passphrase once per session.

  • On macOS, UseKeychain yes stores the passphrase in the keychain.

  • LocalForward — set up a port forward every time you connect:

    Host db-tunnel
      HostName 203.0.113.10
      User deploy
      LocalForward 5433 localhost:5432
    

    (SSH port forwarding explained.)

  • ProxyJump — connect through a bastion/jump host:

    Host internal-db
      HostName 10.0.0.5
      User admin
      ProxyJump bastion
    

    ssh internal-db hops through bastion automatically.

Two GitHub accounts on one machine

A classic use: a personal and a work GitHub account, each with its own key. GitHub only knows which account you are by the key, so define two aliases:

Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_personal
  IdentitiesOnly yes

Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_work
  IdentitiesOnly yes

Then clone using the alias instead of github.com:

git clone git@github-work:company/app.git

For an existing repository, update its remote: git remote set-url origin git@github-work:company/app.git.

The precedence rule that trips people up

SSH reads the file top to bottom, and for each option, the first value it finds wins. So put specific hosts first and a general Host * block last:

Host prod
  User deploy          # this wins for prod

Host *
  User me              # used only where nothing earlier set User

If Host * with User me came first, it would win for prod too, and you'd wonder why your User deploy line is ignored.

Testing and debugging

  • See the final settings SSH will use for a host:

    ssh -G prod
    
  • Verbose connection output to see which key is offered and why it fails:

    ssh -v prod
    

Keep it tidy

  • Use Include to split configs: Include ~/.ssh/config.d/* at the top of the file, with one file per client or project.
  • Add comments (#) explaining unusual entries.
  • Never put passwords in the config file — SSH doesn't support it anyway; use keys.

The summary

  • ~/.ssh/config gives connections short names and stores their details.
  • Core options: HostName, User, Port, IdentityFile, IdentitiesOnly.
  • Add ServerAliveInterval to stop idle disconnects; ProxyJump and LocalForward for hops and tunnels.
  • First match wins — specific hosts at the top, Host * at the bottom.
  • ssh -G host shows the effective settings; ssh -v shows what's going wrong.

EasySpawn servers are reachable over SSH as well as from the browser and your phone — add one config entry and ssh myapp, VS Code Remote SSH and rsync all just work. See how it works or join the waitlist.

Related: SSH Keys Explained · VS Code Remote SSH · A tmux Cheat Sheet for Long-Running Sessions · The Terminal for Complete Beginners

Keep reading