If you maintain WordPress sites across more than a couple of servers, you’ve probably typed a command like ssh -i ~/.ssh/xxx_key.pem -p 2222 user@203.0.113.10 more times than you’d like. Remembering the right key path, port number, and username for each server isn’t realistic, and copying a similar-looking command from shell history is exactly how you end up connecting to the wrong box. ~/.ssh/config solves this by letting you collect per-host settings in one file.
Note:
~/.ssh/configis a file read by the OpenSSH client — it’s not a server-side setting. It lives on your local machine (Mac/Linux/Windows SSH client) and teaches it how to reach each server, typically with just a few lines per host.
Basic structure
A minimal block looks like this:
Host myserver
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/myserver_key
IdentitiesOnly yes
Once saved, you can connect with:
ssh myserver
Host here is an alias — an arbitrary string, unrelated to the actual hostname. scp and rsync can use the same alias, so scp file.txt myserver:/tmp/ just works. You no longer need to pass the port or username on the command line every time, and there’s no chance of mistyping the key path.
Why IdentitiesOnly yes matters
Specifying IdentityFile alone isn’t quite enough. Without IdentitiesOnly yes, the OpenSSH client will offer the specified key plus any other keys registered with ssh-agent. If the server enforces a limit on authentication attempts (MaxAuthTries), or runs something like fail2ban that temporarily blocks an IP after repeated failed auth attempts, offering several unintended keys before reaching the correct one can get your connection blocked before it ever succeeds.
IdentitiesOnly yes restricts the client to only the key explicitly listed in that Host block, which avoids the extra authentication attempts. If you keep separate keys for different projects or separate personal and work use, this option is effectively mandatory.
Grouping shared settings across similar servers with wildcards
When you have several servers with similar setups, Host supports wildcard patterns so you can group shared settings:
Host staging-*
User deploy
IdentitiesOnly yes
ServerAliveInterval 30
Host staging-web1
HostName 203.0.113.10
IdentityFile ~/.ssh/staging_key
Host staging-web2
HostName 203.0.113.20
IdentityFile ~/.ssh/staging_key
OpenSSH reads the config file top to bottom and keeps the first value it finds for a given option — later matching blocks don’t override earlier ones. That means specific Host blocks need to come before the wildcard block. If staging-* were placed first, the individual blocks’ HostName values would never be read, and every alias would try to connect to the same server.
ServerAliveInterval 30 sends a keepalive packet every 30 seconds, which matters on networks that drop idle connections (some routers and firewalls do this). It’s particularly useful when running a long backup job over SSH that you don’t want interrupted mid-way.
Splitting the config file with Include
As the number of projects grows, cramming every server into a single ~/.ssh/config gets hard to navigate. OpenSSH 7.3 and later supports an Include directive to split the file up:
# ~/.ssh/config
Include ~/.ssh/config.d/*.conf
Host *
IdentitiesOnly yes
Keeping one file per project or client under ~/.ssh/config.d/ means that when a project ends, you delete one file and the cleanup is done. Include expands exactly where it’s written, so whether you place it before or after a catch-all Host * block changes which settings take precedence — worth keeping in mind.
How this differs from WP-CLI aliases
Using WP-CLI aliases to switch between multiple WordPress environments safely covered wp-cli.yml aliases, which manage “which WordPress site a command runs against” at the application layer — inside WP-CLI itself. ~/.ssh/config operates one layer down, at the OS’s SSH client, managing “how to connect to which server” in the first place.
The two are independent, but combining them compounds the benefit. ~/.ssh/config organizes the connection itself; WP-CLI aliases then organize the sites within each server. Together, both the connection command and the site-targeting command stay short and less error-prone.
A security note
~/.ssh/config stores hostnames, IP addresses, and port numbers in plain text. As a baseline, keep the file’s permissions at 600 (readable/writable only by you) — some OpenSSH client implementations will warn if permissions are looser than that.
chmod 600 ~/.ssh/config
It’s also worth being deliberate about not committing this file to a Git repository by accident, since that would leak internal connection details externally. ~/.ssh/ is typically outside any project repo, but if you version-control your dotfiles, make sure it’s explicitly excluded via .gitignore.
Summary
| Setting | Purpose |
|---|---|
Host |
Alias name (freely chosen) |
HostName |
Actual connection target (IP or domain) |
IdentityFile |
Path to the private key to use |
IdentitiesOnly yes |
Offers only the specified key, avoiding extra auth attempts |
Host pattern* |
Applies shared settings across multiple servers via wildcard |
Include |
Splits the config file by project or client |
For anyone maintaining multiple WordPress environments over SSH, ~/.ssh/config is a setup cost paid once — after that, all you need to remember is an alias name. The real payoff isn’t the shorter commands; it’s that the structural risk of connecting to the wrong server drops significantly. For choosing which key type to generate in the first place, see also SSH key types (RSA / ED25519 / ECDSA) — what actually differs, and which one to pick.