The SSH Config File
Chapter 4 — The SSH Config File
By now you know how to connect, use keys, and specify flags. But typing
ssh -p 2222 -i ~/.ssh/id_work philip@work-server.example.com every
time is nobody's idea of fun. The SSH config file — ~/.ssh/config —
lets you store all of that per host, so the full command above becomes simply
ssh work. It also handles jump hosts, keepalives, agent forwarding,
and anything else you'd normally pass as a flag.
~/.ssh/config on Linux and macOS.
On Windows with OpenSSH it's C:\Users\Philip\.ssh\config — same
format, same directives. Create the file if it doesn't exist; SSH reads it
automatically on every connection.
Before and After
Config File Structure
The file is a series of Host blocks. Each block starts with a
Host line giving a nickname, followed by indented directives that
apply to that host. The nickname is what you type in the terminal — it doesn't
have to match the real hostname.
scp, sftp, and rsync too. Once
pi is defined in your config, rsync -av files/ pi:~/files/
just works.
The Global Default Block
A Host * block at the end of the file sets defaults that apply to
every connection unless a more specific block overrides them. Put keepalives,
compression, and agent forwarding defaults here so you don't repeat them in
every host block.
Host * defaults at the bottom — not the
other way around.
All Useful Directives
| Directive | What it does | Example value |
|---|---|---|
| HostName | The real hostname or IP to connect to | 192.168.1.100 |
| User | Login username on the remote machine | philip |
| Port | Port to connect on (default 22) | 2222 |
| IdentityFile | Path to the private key file to use | ~/.ssh/id_work |
| IdentitiesOnly | Only use the key specified — don't try others from the agent | yes |
| ServerAliveInterval | Send a keepalive packet every N seconds | 60 |
| ServerAliveCountMax | Drop connection after N missed keepalive replies | 3 |
| AddKeysToAgent | Automatically add a used key to the SSH agent | yes |
| ForwardAgent | Forward your local SSH agent to the remote machine (use with care) | yes |
| ProxyJump | Connect via a jump host (see section below) | jumphost |
| LocalForward | Forward a local port to a remote address via the tunnel | 8080 localhost:80 |
| Compression | Enable compression — useful on slow connections | yes |
| StrictHostKeyChecking | How to handle unknown or changed host keys | accept-new |
| LogLevel | Verbosity of SSH output (QUIET, ERROR, INFO, VERBOSE, DEBUG) | QUIET |
| ConnectTimeout | Seconds to wait before giving up on connecting | 10 |
| ControlMaster | Reuse an existing connection for new sessions (multiplexing) | auto |
| ControlPath | Socket file for connection multiplexing | ~/.ssh/cm-%r@%h:%p |
Wildcards and Pattern Matching
The Host keyword supports wildcards, which is useful for groups
of similar hosts:
ProxyJump — Connecting Through a Jump Host
A jump host (also called a bastion host) is an intermediate machine you connect through to reach a target that isn't directly accessible — for example, a server on a private network behind a firewall, or a Raspberry Pi on your home network when you're away from home.
public IP
192.168.1.100
Before ProxyJump, you had to SSH into the jump host first, then
SSH again to the target — two hops, two prompts, two sessions to manage.
ProxyJump makes SSH handle both hops transparently in a single
command.
ProxyJump in the config file
ProxyJump inline (without editing config)
ProxyJump,
your private key is only used by your local SSH client — it never touches the
jump host. This is safer than the old approach of copying your key to the jump
host and using agent forwarding. Always prefer ProxyJump over
ProxyCommand ssh -A for this reason.
Connection Multiplexing — One Connection, Many Sessions
Every time you open a new terminal and SSH to the same server, the full handshake runs again. Multiplexing reuses the first connection as a shared channel — subsequent connections to the same host open in milliseconds and don't require re-authentication.
With this in place, the second ssh server you open in a new tab
connects almost instantly — no new handshake, no passphrase prompt, because it
tunnels through the existing session.
A Complete Real-World Config
This is what Philip's ~/.ssh/config might look like after setting
up all the hosts covered in this course:
Creating and Editing the Config File
ssh -G hostname is the config file debugger —
it prints every resolved setting for that host (including defaults inherited
from Host *) without actually connecting. Use it to confirm your
config is being read the way you expect.
StrictHostKeyChecking — Handle with Care
One directive worth a specific mention: StrictHostKeyChecking
controls what happens when SSH sees an unknown or changed host key.
| Value | Behaviour | When to use |
|---|---|---|
| yes | Refuse connection if key is unknown or changed. Never auto-add. | Maximum security — you manually manage known_hosts. |
| accept-new | Auto-add unknown hosts but refuse changed keys. Good balance. | Recommended for most uses — protects against MITM, allows new hosts. |
| ask (default) | Prompt for unknown hosts; refuse changed keys. | The default — fine for interactive use. |
| no | Accept any key silently — never check known_hosts. | Scripting against ephemeral hosts (containers, VMs that change keys constantly). Never use on real servers. |
StrictHostKeyChecking no in your global
Host * block. It's tempting when you're tired of prompts,
but it disables the protection that detects man-in-the-middle attacks.
If you need it for scripting, set it only for the specific host or a specific
IP range in its own Host block.
Quick Reference
| Task | How to do it |
|---|---|
| Create the config file | touch ~/.ssh/config && chmod 600 ~/.ssh/config |
| Edit it | vi ~/.ssh/config |
| Debug / print resolved settings | ssh -G server |
| Connect using an alias | ssh server |
| Override a config setting inline | ssh -o Port=2222 server |
| Jump through a host (inline) | ssh -J jumphost philip@target |
| Use config alias with sftp | sftp server |
| Use config alias with rsync | rsync -av files/ server:~/files/ |