Right, let’s talk about your ~/.ssh/config file. If you’re manually typing ssh -i ~/.some/path/key.pem -p 2222 user@some-long-annoying-hostname.com more than once, you’re doing it wrong. You’re not just wasting keystrokes; you’re inviting carpal tunnel and existential dread. This file is your command-line best friend. It’s where you turn that repetitive, error-prone mess into a simple, elegant ssh my_cool_server.

Think of it as a contacts list for your servers. You don’t memorize your friend’s phone number, IP address, and their favorite pizza topping every time you call them. You just tap their name. Your SSH config lets you do the same for machines.

The Absolute Basics: From Pain to Alias

Let’s start with the most common use case: turning a long, complicated command into a short alias. Here’s a before and after that will change your life.

The “Before” (The Barbaric Way):

ssh -i ~/.ssh/special_key_rsa -p 2022 ubuntu@ec2-54-210-137-77.compute-1.amazonaws.com

The “After” (The Civilized Way): You create a ~/.ssh/config file (if it doesn’t exist) and add this:

Host dev-server
    HostName ec2-54-210-137-77.compute-1.amazonaws.com
    User ubuntu
    Port 2022
    IdentityFile ~/.ssh/special_key_rsa

Now, to achieve the same result, you simply type:

ssh dev-server

It’s a small miracle. Notice the indentation? It’s not just for looks. The SSH config parser is annoyingly picky. It wants spaces, not tabs. Don’t ask me why; it’s one of those “design choices” from a bygone era that we’re just stuck with. Use spaces or face its silent, grumpy rejection.

Ditch the -i Flag: Specify Your Private Keys

The most common reason I see people use this file is to stop specifying keys all the time. By default, SSH offers a key to a server based on its own mysterious internal ordering. If you have multiple keys (you should), this can fail in confusing ways. IdentityFile solves this.

Host github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work

Host *.github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work

Host personal-github
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal

Why three entries? The first handles the direct git clone git@github.com:org/repo.git. The second, with the wildcard *, is a catch-all for any potential subdomain (though GitHub doesn’t use them, it’s a good habit). The third creates a separate alias, ssh personal-github, that uses a different key. This is how you manage separate work and personal accounts on the same platform without losing your mind.

Wildcards and Patterns: Your Secret Weapon

You can use * and ? for pattern matching. This is incredibly powerful for managing whole fleets of similarly named servers.

Host *.mynetwork.internal
    User deploy
    IdentityFile ~/.ssh/deploy_key

Host db-?
    User admin

Host 10.0.0.*
    User backend
    Port 2222

Now, ssh web-01.mynetwork.internal will automatically use the deploy user and the correct key. ssh db-1 and ssh db-a will both use the admin user. And any server on my 10.0.0.0/24 subnet will use the backend user and port 2222. The first matching pattern wins, so you can get specific and then fall back to general rules.

Proxies and Jump Hosts: The SSH Houdini Act

This is where you go from novice to wizard. Sometimes you can’t directly reach a server; you have to hop through a bastion host (or “jump box”). You could SSH twice manually. Or, you can teach SSH to do it for you.

Host bastion
    HostName bastion.mycompany.com
    User jsmith
    IdentityFile ~/.ssh/work_key

Host internal-server
    HostName 10.1.2.3
    User ubuntu
    IdentityFile ~/.ssh/internal_key
    ProxyJump bastion

The magic is in ProxyJump. When you type ssh internal-server, your client will first seamlessly connect to the bastion host and then tunnel the connection through to the internal-server. It’s a thing of beauty. On older SSH versions (<7.3), you had to use ProxyCommand ssh -W %h:%p bastion, which was a cryptic incantation if I’ve ever seen one. ProxyJump is a gift; use it.

Best Practices and Pitfalls

  • File Permissions: The SSH client is paranoid, and rightly so. If your ~/.ssh/config or any key file referenced in it has permissions that are too open (like world-readable), it will simply refuse to use them. Run chmod 600 ~/.ssh/config to be safe.
  • Order Matters: The config file is read from top to bottom, and the first matching Host directive is used. Put your most specific rules at the top and your general wildcard rules at the bottom.
  • The Host Directive is a Matcher: It’s not the alias you use to connect. The text after Host is a pattern that is matched against the hostname you type on the command line. Host dev-server matches ssh dev-server. Host *.com matches ssh example.com.
  • Debugging: If something isn’t working, add the -v (verbose) flag to your ssh command. It will spill the beans on exactly which config options it’s loading and from which host block. It’s your best friend for troubleshooting a misbehaving config.

This file is the difference between feeling like a button-pusher and a conductor. A few minutes of setup saves you a lifetime of annoyance. Go forth and configure.