πŸ“‹ Cheat Sheets

SSH Cheat Sheet β€” Keys, Config, Tunnels, and Troubleshooting


Click any command to expand the explanation and examples.

πŸ”‘ Keys

ssh-keygen β€” generate keys keys
# Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "your@email.com"

Generate RSA key (wider compatibility)

ssh-keygen -t rsa -b 4096 -C β€œyour@email.com”

Custom filename

ssh-keygen -t ed25519 -f ~/.ssh/work_key

Files created:

~/.ssh/id_ed25519 (private key β€” NEVER share)

~/.ssh/id_ed25519.pub (public key β€” share this)

Copy public key to server

ssh-copy-id user@server ssh-copy-id -i ~/.ssh/work_key.pub user@server

Or manually

cat ~/.ssh/id_ed25519.pub | ssh user@server β€˜mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys’

ssh-agent β€” manage keys keys
# Start agent
eval "$(ssh-agent -s)"

Add key

ssh-add ~/.ssh/id_ed25519 ssh-add ~/.ssh/work_key

List loaded keys

ssh-add -l

Remove all keys

ssh-add -D

macOS: add to Keychain (persists across reboots)

ssh-add β€”apple-use-keychain ~/.ssh/id_ed25519

πŸ”Œ Connecting

ssh β€” connect to servers connect
# Basic connection
ssh user@hostname
ssh user@192.168.1.100

Custom port

ssh -p 2222 user@hostname

With specific key

ssh -i ~/.ssh/work_key user@hostname

Run a command (don’t open shell)

ssh user@server β€˜ls -la /var/log’ ssh user@server β€˜df -h && free -m’

Verbose (debugging)

ssh -v user@hostname ssh -vvv user@hostname # Extra verbose

πŸ“ SSH Config File

~/.ssh/config β€” stop typing long commands config
# ~/.ssh/config

Now just: ssh prod

Host prod HostName 203.0.113.50 User deploy Port 22 IdentityFile ~/.ssh/deploy_key

Jump through bastion

Host internal HostName 10.0.1.50 User admin ProxyJump bastion

Host bastion HostName 203.0.113.10 User admin

Wildcard for all hosts

Host * AddKeysToAgent yes IdentitiesOnly yes ServerAliveInterval 60 ServerAliveCountMax 3

Work servers

Host work-* User jochen IdentityFile ~/.ssh/work_key

Host work-web HostName web.internal.company.com

Host work-db HostName db.internal.company.com

This is the most underused SSH feature. Set it up once, save yourself thousands of keystrokes.

πŸš‡ Tunnels & Port Forwarding

-L β€” local port forwarding tunnel
Access a remote service through a local port.
# Access remote PostgreSQL (port 5432) on localhost:5432
ssh -L 5432:localhost:5432 user@server

Access remote service on a different host

ssh -L 8080:internal-db:5432 user@bastion

Now connect to localhost:8080 to reach internal-db:5432

Background tunnel (no shell)

ssh -fNL 5432:localhost:5432 user@server

-f = background, -N = no command, -L = local forward

-R β€” remote port forwarding tunnel
Expose a local service to the remote server.
# Make your local port 3000 available on server's port 8080
ssh -R 8080:localhost:3000 user@server
# Now server:8080 reaches your localhost:3000

Useful for: showing a local dev server to someone on the server

-D β€” SOCKS proxy tunnel
# Create a SOCKS proxy through the server
ssh -D 1080 user@server

Then configure your browser to use SOCKS proxy localhost:1080

All traffic goes through the SSH tunnel

πŸ“‹ File Transfer

scp and rsync transfer
# scp β€” copy files
scp file.txt user@server:/path/
scp user@server:/path/file.txt ./
scp -r folder/ user@server:/path/    # Recursive

rsync β€” better for large/repeated transfers

rsync -avz ./dist/ user@server:/var/www/ rsync -avz β€”delete ./dist/ user@server:/var/www/ # Mirror (delete extra files) rsync -avz -e β€œssh -p 2222” ./dist/ user@server:/var/www/ # Custom port

πŸ”’ Permissions

Fix SSH permissions fix
SSH is strict about file permissions. If they're wrong, it silently refuses to work.
# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519          # Private key
chmod 644 ~/.ssh/id_ed25519.pub      # Public key
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/authorized_keys
See also: Git Permission Denied (publickey) fix