SSH Config Generator
A tidy ~/.ssh/config with hosts, keys and jump hosts.
● Runs 100% in your browser — nothing you type leaves this page.
# Generated by OhSudo — https://ohsudo.com/tools/ssh-config-generator/# ssh uses the first value it finds for each option: specific hosts first, Host * last.Host bastionHostName bastion.example.comUser deployIdentityFile ~/.ssh/id_ed25519Host web01HostName 10.0.1.21User deployIdentityFile ~/.ssh/id_ed25519# Connect through this host first (it must be reachable from here)ProxyJump bastion# Defaults for every hostHost *# Offer only the key set above, not every key in the agent (avoids "Too many authentication failures")IdentitiesOnly yes# Ask for the key passphrase once, then keep the key in the agentAddKeysToAgent yes# Send a keepalive every 60 s; give up after 3 missed answersServerAliveInterval 60ServerAliveCountMax 3
Install it
$ mkdir -p ~/.ssh && chmod 700 ~/.ssh$ nano ~/.ssh/config$ chmod 600 ~/.ssh/config$ ssh -G web01 | grep -E '^(hostname|user|port|identityfile|proxyjump) '$ ssh web01Linux and macOS. On Windows the file is %USERPROFILE%\.ssh\config. ssh -G shows what ssh will really use for a host, without connecting.
The address bar updates as you go, so you can bookmark or share the result.
How to use it
- Add a host for every server you connect to. The alias is what you’ll type:
ssh web01instead ofssh -i ~/.ssh/work_key -p 2222 deploy@203.0.113.21. - Fill in the address, the user and — if it isn’t 22 — the port. Point IdentityFile at the private key (no
.pub). - For servers you can only reach through a bastion, put the bastion’s alias in Jump through.
ssh web01then hops through it on its own. - Save the result as
~/.ssh/config(mode600) and check it withssh -G <alias>.
What you get
- One block per host, in the right order. ssh uses the first value it finds for each option, so specific hosts come first and the defaults (
Host *) last. Put them the other way round and your defaults quietly win. - Jump hosts with
ProxyJump— the modern replacement forProxyCommand ssh -W. Chains work too:bastion,admin@10.0.0.5. IdentitiesOnly yes, so ssh offers only the key you chose instead of every key in your agent. That’s the fix forToo many authentication failures.- Keepalive (
ServerAliveInterval 60), so idle sessions aren’t dropped by firewalls and NAT, and dead ones are noticed. - Checks for duplicate aliases, jump loops, a
.pubpath inIdentityFile, and a warning when you turn on agent forwarding.
Every option the generator writes is checked with a real OpenSSH client (ssh -G) for every combination of settings.
Common commands
ssh -G web01 | grep -E '^(hostname|user|port|identityfile|proxyjump) ' # what ssh will really usessh -v web01 # watch the connection, key by keyssh -J bastion deploy@10.0.1.21 # one-off jump, without a configscp ./app.tar.gz web01:/tmp/ # scp, rsync and git use the same aliasesrsync -avz ./site/ web01:/var/www/site/ssh-copy-id -i ~/.ssh/id_ed25519.pub web01 # install your public key on the serverWarning
Agent forwarding is not needed for jump hosts. With ProxyJump your keys never leave your machine. ForwardAgent yes lets anyone with root on that server use your keys while you’re connected, so turn it on only for servers you trust, and only when you need your keys on the server (for example git pull from a private repo).
FAQ
Why is my setting ignored?
Because an earlier block already set it. For every option, ssh keeps the first value it reads — from the command line, then ~/.ssh/config top to bottom, then /etc/ssh/ssh_config. A Host * block at the top of the file wins over everything below it. ssh -G <alias> shows the values ssh will actually use.
Permission denied (publickey) after adding the config?
Check that IdentityFile points to the private key, that the matching .pub is in ~/.ssh/authorized_keys on the server, and the permissions on both sides. The full checklist is in SSH Permission denied (publickey). If ssh says the host key changed instead, see REMOTE HOST IDENTIFICATION HAS CHANGED.
Does Ansible use this file?
Yes. Ansible connects with OpenSSH by default, so aliases, users, keys and ProxyJump from ~/.ssh/config apply to its connections too — unless the inventory sets them (ansible_user, ansible_port…), which wins. If a host is UNREACHABLE, test it first with plain ssh <alias> — see Ansible UNREACHABLE.
Where is the file on Windows?
The OpenSSH client built into Windows 10 and 11 reads %USERPROFILE%\.ssh\config (for example C:\Users\you\.ssh\config), with the same syntax.
How do I keep work running if SSH drops?
Run it inside tmux: see the tmux Cheat Sheet.
Articles
Learn more
Ansible "Missing sudo password": give it the password safely, or allow the user properly
Fix Ansible "Missing sudo password": use --ask-become-pass, ansible-vault for the become password, or NOPASSWD in sudoers, plus "Incorrect sudo password" and timeouts.
Beginner · 4 min read
SSH "Too many authentication failures": your agent offers too many keys
Fix SSH "Received disconnect … Too many authentication failures": the agent offers every key before the right one. Use IdentitiesOnly and IdentityFile.
Beginner · 4 min read
Ansible "UNREACHABLE! Failed to connect to the host via ssh": find the real SSH error
Fix Ansible UNREACHABLE: read the SSH error in the message, check the inventory, reproduce with -vvv and plain ssh, then fix keys, users or host keys.
Beginner · 4 min read
SSH "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!": check it, then fix known_hosts
Fix the SSH host key warning safely: find out why the key changed, verify the new fingerprint on the server, then remove the old key with ssh-keygen -R.
Beginner · 3 min read
SSH "Permission denied (publickey)": how to find the real cause
Fix SSH "Permission denied (publickey)": read the server log, fix ~/.ssh permissions, check the key and sshd_config, and handle SELinux on RHEL.
Intermediate · 4 min read