~/.ssh/config lets you define aliases for hosts, simplifying SSH connections and enabling powerful customizations.

Let’s see it in action. Imagine you frequently SSH into a server at 192.168.1.100 with username admin and you always use a specific private key ~/.ssh/id_rsa_server. Without ~/.ssh/config, you’d type:

ssh admin@192.168.1.100 -i ~/.ssh/id_rsa_server

Now, let’s create a ~/.ssh/config file.

# ~/.ssh/config

Host myserver
    Hostname 192.168.1.100
    User admin
    IdentityFile ~/.ssh/id_rsa_server
    Port 2222

With this configuration, you can now connect simply by typing:

ssh myserver

The SSH client reads this file and automatically applies the Hostname, User, IdentityFile, and Port directives for any connection where the Host alias matches myserver.

This file is structured as a series of Host blocks. Each block defines a set of configurations that apply to matching Host aliases. The Host directive itself can take a glob pattern, allowing you to define configurations for multiple hosts at once. For instance, Host *.example.com would apply the settings in that block to any host ending in .example.com.

Here’s a breakdown of the core problem this solves: repetitive and complex SSH commands. Instead of remembering IPs, usernames, and specific key files for each server, you create a memorable alias. Beyond basic connection details, ~/.ssh/config offers a rich set of options to tailor your SSH experience.

You can control:

  • Hostname: The actual IP address or DNS name of the server.
  • User: The username to use for the connection.
  • Port: The SSH port on the remote server (defaults to 22).
  • IdentityFile: The path to the private key to use for authentication.
  • ForwardAgent: Whether to forward your SSH agent connection (yes or no). This is useful for chaining SSH connections without needing to copy your private key everywhere.
  • ProxyJump: A powerful directive for connecting through an intermediate jump host. Instead of manually SSHing into a jump host and then into the target, ProxyJump handles it in one go. For example:
    Host internal-server
        Hostname 10.0.0.5
        User devuser
        ProxyJump jumphost.example.com
    
    This allows you to connect to internal-server as if it were directly accessible, with SSH handling the hop through jumphost.example.com.
  • LocalForward / RemoteForward: For setting up local or remote port forwarding.
  • ServerAliveInterval: Sends a "keep-alive" message to the server at a specified interval (in seconds) to prevent disconnections due to inactivity.
  • ServerAliveCountMax: The number of keep-alive messages that can be sent without receiving a response from the server before the connection is considered dead.

The SSH client processes ~/.ssh/config from top to bottom. When it encounters a Host directive, it checks if the alias you provided on the command line matches. If it does, it applies the directives within that block. If multiple Host blocks match, the directives from the last matching block take precedence. This allows for both general configurations and specific overrides.

The precedence rules are key to understanding how complex configurations work. For example, you might have a general Host * block for common settings like ServerAliveInterval 60, and then a specific Host production block with User produser and IdentityFile ~/.ssh/prod_key. When you ssh production, the production block’s settings will override or add to the general * block’s settings.

You can also use Match directives within ~/.ssh/config to apply configurations based on more complex criteria than just the Host alias. For instance, you can match based on the remote user, the remote hostname after resolution, or even the address family. This offers a more granular control over connection parameters.

One subtlety often missed is how ~/.ssh/config interacts with the command line. Options provided directly on the ssh command line always override any settings in ~/.ssh/config. So, if your config file specifies Port 2222 for myserver, but you run ssh myserver -p 22, the connection will use port 22. This is by design, allowing for quick, one-off overrides without altering your configuration file.

The next logical step is to explore advanced multiplexing with ControlMaster and ControlPath to reuse existing SSH connections, dramatically speeding up subsequent connections to the same host.

Want structured learning?

Take the full Ssh course →