SSH Cheat Sheet

Connections, key management, ~/.ssh/config patterns, tunneling, ProxyJump, file transfer, and the troubleshooting moves you forget

Basic Connection
ssh user@host
Connect with your default identity
ssh user@host -p 2222
Connect on a custom port
ssh -i ~/.ssh/key user@host
Use a specific identity file
ssh user@host "cmd"
Run a single command and exit
ssh -X user@host
Enable X11 forwarding (GUI apps)
ssh -A user@host
Forward your SSH agent (use with care)
ssh -t user@host
Force pseudo-tty (needed for interactive remote programs)
ssh -v user@host
Verbose, useful for debugging connection issues
ssh -vvv user@host
Even more verbose
ssh -o "ConnectTimeout=5" host
Set option inline
Key Generation & Management
ssh-keygen -t ed25519
Generate Ed25519 key (modern default, recommended)
ssh-keygen -t rsa -b 4096
Generate 4096-bit RSA key (compatible with older systems)
ssh-keygen -t ed25519 -C "you@host"
Add a comment (often the email or hostname)
ssh-keygen -p -f ~/.ssh/id_ed25519
Change passphrase on existing key
ssh-keygen -y -f key
Print public key from private key file
ssh-keygen -lf key.pub
Show fingerprint of a key
ssh-keygen -R host
Remove host from known_hosts (after IP/key change)
ssh-copy-id user@host
Install your public key on remote (writes to authorized_keys)
ssh-copy-id -i key.pub user@host
Install a specific key
SSH Agent
eval $(ssh-agent)
Start ssh-agent for current shell
ssh-add ~/.ssh/id_ed25519
Add key to agent (prompts for passphrase once)
ssh-add
Add default keys
ssh-add -l
List loaded keys
ssh-add -L
List loaded public keys (full)
ssh-add -d ~/.ssh/key
Remove a key from agent
ssh-add -D
Remove all keys from agent
ssh-add -t 3600 ~/.ssh/key
Add key with 1-hour timeout
Config File (~/.ssh/config)

Persistent connection settings per host. Stop typing long ssh commands.

Per-host shortcut
After this, ssh prod connects to the full host with the right key and port.
Host prod
    HostName 198.51.100.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/prod_key
Wildcard for an org
All *.example.com hosts share the same key.
Host *.example.com
    User myname
    IdentityFile ~/.ssh/example_key
    ServerAliveInterval 60
Bastion / jump host
Connect to internal via bastion.example.com. ProxyJump is the modern way.
Host bastion
    HostName bastion.example.com
    User jumper

Host internal
    HostName 10.0.0.5
    User app
    ProxyJump bastion
Connection multiplexing
Reuse one TCP connection for multiple ssh sessions to the same host. Big speedup for repeated commands.
Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m
Port Forwarding & Tunneling
ssh -L 8080:localhost:80 host
Local forward: localhost:8080 on YOU = port 80 on host
ssh -L 5432:db:5432 jump
Local forward through jump host to internal db server
ssh -R 9000:localhost:3000 host
Remote forward: host:9000 = your local:3000 (e.g. expose localhost)
ssh -D 1080 host
Dynamic forward: SOCKS proxy on localhost:1080 routed via host
ssh -N -L 8080:localhost:80 host
Forward only, no shell session (-N)
ssh -f -N -L 8080:localhost:80 host
Forward in background (-f)
File Transfer
scp file user@host:/path
Copy local file to remote
scp user@host:/path file
Copy remote file to local
scp -r dir/ user@host:/path
Recursive copy
scp -P 2222 file host:/
Custom port (uppercase P, unlike ssh's lowercase p)
rsync -avz src/ user@host:/dst
Sync directories: archive, verbose, compress (preferred over scp)
rsync -avz --delete src/ host:/dst
Sync and delete files at dst not in src (mirror)
sftp user@host
Interactive file transfer (get, put, ls, cd)
Multi-Hop & ProxyJump
ssh -J jump user@target
Connect to target via jump host (modern syntax)
ssh -J jump1,jump2 user@target
Multiple hops
ssh -o ProxyCommand="ssh jump nc %h %p" target
Old-school ProxyCommand (still useful for nc-only hosts)
Server Side (sshd_config)
/etc/ssh/sshd_config
Server configuration file
PasswordAuthentication no
Disable password login (recommended after key setup)
PermitRootLogin no
Disable root SSH (login as user, then sudo)
Port 2222
Move SSH off port 22 to reduce log noise
AllowUsers alice bob
Whitelist users who can SSH in
MaxAuthTries 3
Disconnect after 3 failed attempts
sudo systemctl reload sshd
Apply config changes (don't restart over an active SSH session)
sshd -t
Test sshd config syntax before applying
Troubleshooting
Permissions matter. ~/.ssh must be 700, ~/.ssh/authorized_keys must be 600, private keys must be 600. SSH refuses to use keys with looser perms.
"REMOTE HOST IDENTIFICATION HAS CHANGED" warning: the server's host key changed (could be legit reinstall, could be MITM). If you trust the change: ssh-keygen -R host to remove the old entry.
"Permission denied (publickey)": server has your public key but ssh isn't offering the right private key. Check ssh -v output to see which keys are offered. IdentityFile in ~/.ssh/config or -i flag forces a specific key.
Hung connection on flaky network: add ServerAliveInterval 60 in your config so ssh sends keepalives. Combine with ServerAliveCountMax 3 to disconnect cleanly after 3 missed.
"Connection refused" vs "Connection timed out": refused = port open but service not responding (check sshd is running, check firewall on server). Timed out = network can't reach the host (check IP, check network firewall, check VPN).