SSH Config Host Aliases, IdentitiesOnly, Jumps
Stop repeating long ssh flags. Build a ~/.ssh/config with Host aliases, IdentitiesOnly, and jump hosts so private VPS nodes stay one command away.
Netbay Engineering
Netbay Engineering
On this page
The SSH command line grows a tail of flags the moment you have more than one box. You type ssh -i ~/.ssh/id_ed25519_prod -p 22 -J bastion deploy@10.0.0.4, then you type it again from a second terminal and miss a flag. OpenSSH already ships a client configuration file that turns that mess into ssh prod. It is the client-side map: Host aliases, IdentitiesOnly so the agent does not spray every key at a MaxAuthTries-limited daemon, and a jump host that stays public while the rest of the fleet stays private.
Why a config file beats a shell alias
A shell alias hides flags, but it does not compose. scp, sftp, rsync -e ssh, git, and ansible all speak the OpenSSH client, and they all read ~/.ssh/config. They do not read your .bashrc. Put HostName, User, Port, IdentityFile, and ProxyJump in the config and every tool that shells out to ssh inherits the same map. That is the whole point of doing this work once.
The file is line-oriented. A Host line starts a stanza. Keywords under it apply until the next Host or Match. First match wins for each keyword, which is why you put specific aliases above wildcards. A trailing Host * stanza is the right place for shared defaults such as HashKnownHosts, ServerAliveInterval, and IdentitiesOnly. Do not put a specific IdentityFile on Host * unless you enjoy debugging which key just got offered.
Permissions matter as much as syntax. The directory ~/.ssh must be 700 and the config file 600, owned by you. OpenSSH will ignore a group-writable config. That is not a suggestion; it is how the client refuses to trust a file someone else could have edited.
Host aliases and pattern matching
Give every machine a short name you can type in the dark. The alias is the Host value. The real address is HostName, which can be a public IP, a private RFC1918 address, or a DNS name. User and Port belong in the stanza so you never pass them on the command line again.
Host bastion
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_bastion
IdentitiesOnly yes
Host prod
HostName 10.0.0.4
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
IdentitiesOnly yes
ProxyJump bastion
Host *
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
HashKnownHosts yesPatterns are useful when a fleet shares a suffix. Host db-*.internal matches db-1.internal. Host !bastion * applies a default to everything except the jump box. Keep the pattern language boring. Clever negative matches that nobody else can read will lock a colleague out at 2 a.m. Document the alias list next to your inventory, or generate the config from that inventory so the two cannot drift.
IdentitiesOnly stops the agent from burning tries
This is the setting people skip, then blame MaxAuthTries. ssh-agent holds every key you have loaded: laptop, personal Git host, old project, the break-glass key you added last quarter. By default the client offers them in order until the server accepts one or hangs up. A hardened sshd with MaxAuthTries 3 will disconnect after three publickey failures. Your correct key never gets a turn.
IdentitiesOnly yes tells the client to offer only the IdentityFile listed in the matching stanza, plus any -i flags you passed. Combined with a per-host IdentityFile, the agent still decrypts the key (so you keep a passphrase), but it no longer sprays the rest of the keyring at the daemon. That is the difference between a working login and Too many authentication failures.
Confirm what the client will actually do before you depend on it. ssh -G prints the expanded configuration after alias and pattern matching. Pipe it through grep and you will see hostname, user, identityfile, proxyjump, and identitiesonly without opening a network connection.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
ssh -G prod | grep -Ei "hostname|user|port|identityfile|proxyjump|identitiesonly"
ssh -v prod trueThe verbose trace shows each key offered. If you still see files you did not list, a wildcard stanza or an extra IdentityFile is winning. Put the specific Host prod block above Host *. Extra IdentityFile lines in the same stanza add keys to the offer list.
Jump hosts as first-class Host entries
A jump host, or bastion, is the only machine with a public address. Application nodes listen on a private network. The client reaches them with ProxyJump, which is the modern replacement for a hand-rolled ProxyCommand. Name the bastion as its own Host alias, then point application aliases at it. Nested hops work: ProxyJump bastion,mid is two hops, evaluated left to right.
Keep the bastion thin. It exists to accept your key, forward a tunnel, and not run application code. Give it a dedicated IdentityFile so a compromise of an application key does not equal a compromise of the front door. Put AllowUsers on the bastion sshd so random local accounts cannot authenticate. The application nodes can then restrict source addresses to the bastion private IP, which you will wire in a later sshd Match block.
Do not copy private keys onto the jump host. ProxyJump opens a second SSH connection from your laptop through the already-authenticated hop. The private key never leaves the client. That is a different, safer model than agent forwarding, which we will refuse to treat as the default later in this series.
If a hop fails, ssh -J bastion prod is the one-off equivalent of the config. Use it to test, then put the same values back in the file. Ubuntu 24.04 on a Lucknow VPS needs no extra TCP forwarding limits on a jump box that only you use.
Include files and a config you can review
Once the file passes a page, split it. Include ~/.ssh/config.d/* keeps work.conf, lab.conf, and personal.conf apart. The main file holds Host * defaults. Directory order is lexical, so name files 10-work.conf if you care which alias wins. Never commit private keys. HostName values and usernames are inventory: useful, slightly sensitive, not a public gist.
A short takeaway: aliases give you names, IdentitiesOnly gives you a single key per name, and ProxyJump gives you a private fleet behind one public box. That is the whole client map. You can spin up an Ubuntu 24.04 jump host on Netbay in under 60 seconds and follow along — netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance