How to use the SSH Config Generator

  1. Add a host for each server: a short alias, its address, the user and the port.
  2. Set the private key path and tick IdentitiesOnly if you keep several keys.
  3. Add a jump host, port forwards or keepalives where a server needs them.
  4. Download the file to ~/.ssh/config, run chmod 600 ~/.ssh/config, then connect with ssh and the alias.

What is the SSH config file?

The SSH config file, ~/.ssh/config, holds per-host settings for the OpenSSH client, so ssh web can stand for ssh -i ~/.ssh/id_ed25519 -p 2222 deploy@203.0.113.10. Each Host block names one or more aliases, and the lines under it (HostName, User, Port, IdentityFile and the rest) apply whenever you connect to a name that matches.

The same aliases work everywhere OpenSSH does: scp, rsync -e ssh, sftp, git over SSH and editors such as VS Code Remote-SSH all read this file. The format is documented in the ssh_config(5) man page.

How ssh reads it: the first value wins

ssh reads the file from top to bottom and, for each option, keeps the first value it finds among the blocks that match the host. Later values for the same option are ignored. That one rule decides the layout:

  • Specific hosts go first, Host * goes last. A Host * block at the top would set User or IdentityFile for every host before their own blocks are read, and their own values would be ignored.
  • Options a host does not set fall through to Host *, which is why it is the place for defaults such as ServerAliveInterval.
  • Options that can repeat, such as IdentityFile and LocalForward, add up instead of being replaced.

Check what ssh will actually use for an alias, without connecting:

ssh -G web | grep -E '^(hostname|user|port|identityfile|proxyjump) '

The options in this generator

OptionWhat it does
HostNameThe real address. The alias after Host is only a name.
User, PortLogin name and SSH port; Port is left out when it is 22.
IdentityFileThe private key to offer.
IdentitiesOnly yesOffer only that key, not every key in your agent.
ProxyJumpReach the host through a bastion: ssh -J in config form.
ForwardAgentLets the server use your agent's keys while you are connected.
ServerAliveIntervalSeconds between keepalives, so idle sessions survive NAT timeouts.
StrictHostKeyCheckingWhat to do with an unknown or changed host key.
LocalForward, RemoteForward, DynamicForwardPort forwards opened with every connection.
AddKeysToAgent, UseKeychainLoad a key into the agent on first use; on macOS, keep its passphrase in the Keychain.

A worked example: a server behind a bastion

Host web
  HostName 10.0.1.20
  User deploy
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes
  ProxyJump bastion

Host bastion
  HostName bastion.example.com
  User deploy
  Port 2222
  IdentityFile ~/.ssh/id_ed25519

Host *
  AddKeysToAgent yes
  ServerAliveInterval 60
  StrictHostKeyChecking accept-new

ssh web now connects to the bastion on port 2222, opens a channel through it to 10.0.1.20 and logs in there with the same key. Nothing is stored on the bastion, and no agent forwarding is needed. Copy files the same way with scp app.tar.gz web:/srv/ or rsync -a dist/ web:/var/www/app/.

Values that would break the file

The file is split on spaces and # starts a comment, so a key path with a space must be quoted: IdentityFile "~/My Keys/id_ed25519". The generator quotes those for you. It refuses line breaks, which would start a new option, and double quotes, which OpenSSH versions before 8.7 cannot escape. In an IdentityFile, %d, %u and %h are expanded (home directory, user, host), so a literal percent sign must be written %%. Backslashes in Windows paths become forward slashes, which OpenSSH for Windows accepts.

Common errors and how to fix them

  • Bad owner or permissions on ~/.ssh/config. The file must not be writable by anyone else: chmod 600 ~/.ssh/config.
  • Bad configuration option: usekeychain. UseKeychain exists only in Apple's ssh. Put IgnoreUnknown UseKeychain above every Host block, as the generator does, and the same file works on Linux and Windows too.
  • Too many authentication failures. ssh offered every key in your agent and the server stopped counting at MaxAuthTries. Set IdentityFile with IdentitiesOnly yes for that host.
  • A host's setting is ignored. An earlier block, usually a Host * near the top, set it first. Move Host * to the end and check with ssh -G.
  • REMOTE HOST IDENTIFICATION HAS CHANGED. The server's key differs from the one in known_hosts. If you rebuilt the server, remove the old key with ssh-keygen -R host; if you did not, treat it as an attack. StrictHostKeyChecking no hides this warning, which is why it is a bad default.

Shipown and your SSH keys

Shipown connects to each server straight from your desktop over SSH, with the key file you point it at, and installs no agent on the server. Its credential settings decide whether a key's passphrase is kept for the session or saved with your operating system's encryption. Your ~/.ssh/config stays yours for the terminal, scp and rsync.

Frequently asked questions

Where is the SSH config file?

Your own settings live in ~/.ssh/config: /home/you/.ssh/config on Linux, /Users/you/.ssh/config on macOS and C:\Users\you\.ssh\config on Windows. System-wide defaults are in /etc/ssh/ssh_config, which your file overrides.

Why should Host * go at the end of the file?

ssh keeps the first value it finds for each option. A Host * block at the top would set the option before a host’s own block is read, so the host’s value would be ignored.

What does IdentitiesOnly yes do?

It makes ssh offer only the keys named with IdentityFile, instead of every key loaded in your agent. That avoids "Too many authentication failures" on servers with a low MaxAuthTries.

How do I use a jump host in ~/.ssh/config?

Add ProxyJump bastion under the host, where bastion is another alias or user@host:port. ssh connects to the bastion first and tunnels through it, with no agent forwarding needed.

Do scp and rsync use ~/.ssh/config?

Yes. scp, sftp, rsync over SSH and git all run ssh underneath, so scp file web:/srv/ uses the alias web with its user, port, key and jump host.

How do I check what ssh will use for a host?

Run ssh -G alias. It prints every option after reading the config files, without connecting.