}

SSH Config File (~/.ssh/config) Complete Guide (2026)

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
  • Host can 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 Host block 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 Host blocks after the Host * block — the first match wins, so specifics must come first.
  • Missing IdentitiesOnly yes when using multiple accounts on the same service — SSH may authenticate with the wrong key from the agent.

Related Articles