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.