All articles

The SSH Config File on Mac: Aliases, Keys, Keychain and Per-Host Settings

2026-10-12

~/.ssh/config is the file that turns ssh -p 2222 -i ~/.ssh/work_ed25519 [email protected] into ssh prod. It is read by ssh, scp, sftp, rsync -e ssh and Git over SSH, so one entry works everywhere.

Create the file with the right permissions

mkdir -p ~/.ssh && chmod 700 ~/.ssh
touch ~/.ssh/config && chmod 600 ~/.ssh/config

OpenSSH refuses to use a config file that other users can write to.

An alias for each server

Host prod
    HostName 203.0.113.7
    User deploy
    Port 2222
    IdentityFile ~/.ssh/work_ed25519

Now ssh prod is enough. Host is the name you type; HostName is the real address.

Make a key and keep it in the Keychain

ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/work_ed25519
ssh-add --apple-use-keychain ~/.ssh/work_ed25519

Then tell ssh to load keys from the Keychain on demand. Put this at the end of the file:

Host *
    AddKeysToAgent yes
    UseKeychain yes
    IdentityFile ~/.ssh/work_ed25519

UseKeychain is an Apple addition. If you share the file with Linux machines or run a non-Apple OpenSSH, add IgnoreUnknown UseKeychain above it or ssh will stop with "Bad configuration option".

The first match wins

ssh reads the file top to bottom and, for each setting, keeps the first value it finds. That is why specific hosts go first and the Host * block goes last. Check the result for any name with:

ssh -G prod | grep -i -E "^(hostname|user|port|identityfile) "

Settings worth having in Host *

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m

ServerAliveInterval stops idle sessions from being dropped by NATs. ControlMaster reuses one connection for later ssh, scp and git calls, so they open instantly.

Split a big file with Include

Include ~/.ssh/config.d/*

Put Include at the top (it must come before the first Host block) and keep one file per project or client in ~/.ssh/config.d/.

One name for several machines

Host web1 web2 web3 shares the settings between them. Note that these names are just patterns: ssh web2 uses the block and, unless you set HostName, tries to resolve web2 as a DNS name.

FAQ

Why does ssh ask for my passphrase every time? The key is not in the agent. Run the ssh-add --apple-use-keychain command above and keep AddKeysToAgent yes in the config.

Where is the file on Windows or Linux? The same place: ~/.ssh/config (%USERPROFILE%\.ssh\config on Windows).

Does Git use it? Yes. A Host github.com block with IdentityFile is the standard way to pick a key per account.

Shortcut

Disclosure: we make Harbor. Harbor is an SSH terminal for Mac that uses your own ssh and ~/.ssh/config, keeps jump hosts apart as gateways, shows live server stats and, with Pro, a post-mortem that reads the server's own history. The terminal, stats and a read-only database client are free. See Harbor.