SSH Config File (~/.ssh/config) Complete Guide (2026)
Last updated: March 2026
Typing ssh -i ~/.ssh/my_key -p 2222 [email protected] every time you connect to a server is tedious and error-prone. The SSH client configuration file (~/.ssh/config) lets you define aliases, set per-host options, and store connection details so you type ssh myserver instead. This guide covers file location, permissions, every common directive, practical examples for managing multiple accounts, and the Include directive for organizing large configurations.
File Location and Permissions
The per-user SSH config file lives at:
~/.ssh/config
The system-wide default is /etc/ssh/ssh_config, which applies to all users. Per-user settings take precedence.
Creating the file
# Create the .ssh directory if it does not exist
mkdir -p ~/.ssh
# Create or edit the config file
touch ~/.ssh/config
Setting correct permissions
SSH is strict about file permissions. If permissions are too open, the SSH client will refuse to use the file or the keys it references.
# The .ssh directory must be readable only by you
chmod 700 ~/.ssh
# The config file must not be readable by others
chmod 600 ~/.ssh/config
# Private key files
chmod 600 ~/.ssh/id_ed25519
# Public key files (less strict, but good practice)
chmod 644 ~/.ssh/id_ed25519.pub
Verify permissions:
ls -la ~/.ssh/
Host Block Syntax
The config file is organized into Host blocks. Each block defines settings for one or more hosts.
Host alias
Directive1 value1
Directive2 value2
Hostcan be an alias, a hostname, an IP address, or a wildcard pattern.- Directives are indented by convention (spaces or tabs — both work).
- Lines starting with
#are comments. - Settings from the first matching
Hostblock win. More specific blocks should appear before more general ones.
Wildcard Host blocks
Host *.example.com
User deploy
IdentityFile ~/.ssh/example_key
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
The Host * block at the end sets defaults for all connections.
Common Directives
HostName
The actual hostname or IP address to connect to. Lets you create short aliases:
Host prod
HostName 203.0.113.10
User ubuntu
Now ssh prod connects to 203.0.113.10 as ubuntu.
User
The username to log in as:
Host staging
HostName staging.example.com
User deploy
Without this, SSH uses your local username.
Port
The port to connect to (default is 22):
Host jumpbox
HostName 203.0.113.20
Port 2222
User admin
IdentityFile
The private key file to use for authentication:
Host work-server
HostName work.example.com
User alice
IdentityFile ~/.ssh/work_ed25519
You can specify multiple IdentityFile entries; SSH tries them in order:
Host legacy-server
HostName old.example.com
IdentityFile ~/.ssh/id_rsa
IdentityFile ~/.ssh/id_ed25519
For more on generating and managing keys, see the SSH Key Generation and Management guide.
ServerAliveInterval and ServerAliveCountMax
Prevent SSH connections from dropping due to inactivity:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
ServerAliveInterval 60 sends a keepalive packet every 60 seconds. ServerAliveCountMax 3 disconnects after 3 consecutive unanswered keepalives (3 minutes of silence).
ProxyJump
Connect through a bastion/jump host to reach a private server:
Host bastion
HostName bastion.example.com
User ubuntu
IdentityFile ~/.ssh/bastion_key
Host private-server
HostName 10.0.0.50
User ubuntu
IdentityFile ~/.ssh/private_key
ProxyJump bastion
Running ssh private-server automatically connects through bastion first. Before OpenSSH 7.3, the equivalent was ProxyCommand ssh bastion -W %h:%p.
For multi-hop scenarios:
Host deep-server
HostName 10.0.1.100
User ubuntu
ProxyJump bastion,private-server
ForwardAgent
Forward your local SSH agent to the remote server, allowing the remote to authenticate to further servers using your local keys without copying private keys to the intermediate server:
Host bastion
HostName bastion.example.com
ForwardAgent yes
Use with caution: anyone with root on the remote host can use your forwarded agent. Only enable it for trusted hosts.
StrictHostKeyChecking
Controls whether SSH checks the server's host key against ~/.ssh/known_hosts:
Host internal-ci
HostName 10.0.0.5
StrictHostKeyChecking accept-new
| Value | Behavior |
|---|---|
yes (default) |
Refuse connections to unknown hosts; fail on changed keys |
accept-new |
Automatically add new host keys; reject changed keys |
no |
Accept all host keys (insecure — avoid in production) |
IdentitiesOnly
Force SSH to use only the key specified in IdentityFile, ignoring any keys loaded in the agent:
Host github.com
IdentitiesOnly yes
IdentityFile ~/.ssh/github_personal
Without IdentitiesOnly yes, SSH may try agent keys in addition to the configured key, causing authentication to use the wrong identity.
AddKeysToAgent
Automatically add loaded keys to the SSH agent:
Host *
AddKeysToAgent yes
Compression
Enable compression for slow links (useful over high-latency connections):
Host remote-office
Compression yes
Server Aliases — Practical Examples
Example: Multiple servers with short names
# ~/.ssh/config
Host web1
HostName 203.0.113.10
User ubuntu
IdentityFile ~/.ssh/prod_key
Host web2
HostName 203.0.113.11
User ubuntu
IdentityFile ~/.ssh/prod_key
Host db1
HostName 203.0.113.20
User postgres
IdentityFile ~/.ssh/prod_key
Port 2222
Host staging
HostName staging.example.com
User deploy
IdentityFile ~/.ssh/staging_key
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
Now:
ssh web1 # connects to 203.0.113.10 as ubuntu
ssh db1 # connects to 203.0.113.20:2222 as postgres
ssh staging # connects to staging.example.com as deploy
Multiple GitHub and GitLab Accounts
A common use case is using separate SSH keys for a personal and a work account on GitHub or GitLab.
Generate separate keys
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/github_personal
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/github_work
Add the public keys to the respective GitHub accounts in Settings > SSH and GPG keys.
Configure ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
IdentitiesOnly yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
IdentitiesOnly yes
Host gitlab-personal
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_personal
IdentitiesOnly yes
Clone using the alias
# Personal GitHub repo
git clone git@github-personal:username/my-repo.git
# Work GitHub repo
git clone git@github-work:company/project.git
Update existing remotes
# If you already cloned with github.com, update the remote
git remote set-url origin git@github-personal:username/my-repo.git
Test the connection
ssh -T git@github-personal
# Hi username! You've successfully authenticated...
ssh -T git@github-work
# Hi workuser! You've successfully authenticated...
The Include Directive
For large configurations, split settings into separate files using Include:
# ~/.ssh/config
Include ~/.ssh/config.d/*.conf
Host *
ServerAliveInterval 60
The Include line must appear before any Host blocks that should be overridden by the included files. Create the directory and individual files:
mkdir -p ~/.ssh/config.d
chmod 700 ~/.ssh/config.d
# Personal servers
touch ~/.ssh/config.d/personal.conf
chmod 600 ~/.ssh/config.d/personal.conf
# Work servers
touch ~/.ssh/config.d/work.conf
chmod 600 ~/.ssh/config.d/work.conf
Each .conf file uses normal Host block syntax. Include was added in OpenSSH 7.3 (2016), so it is available on any modern system.
Debugging SSH Config Issues
Test without the config file
ssh -F /dev/null user@host
Verbose output shows which config file and keys are being used
ssh -v user@host 2>&1 | grep -E "config|identity|offer"
Print the effective config for a host
ssh -G myserver
This prints all the settings SSH would use for myserver after evaluating the config file — extremely useful for debugging.
Common mistakes
- Forgetting
chmod 600 ~/.ssh/config— SSH silently ignores config files with wrong permissions on some versions. - Putting specific
Hostblocks after theHost *block — the first match wins, so specifics must come first. - Missing
IdentitiesOnly yeswhen using multiple accounts on the same service — SSH may authenticate with the wrong key from the agent.