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.100Custom 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/configThis is the most underused SSH feature. Set it up once, save yourself thousands of keystrokes.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
π Tunnels & Port Forwarding
-L β local port forwarding tunnel
# Access remote PostgreSQL (port 5432) on localhost:5432 ssh -L 5432:localhost:5432 user@serverAccess 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
# Make your local port 3000 available on server's port 8080 ssh -R 8080:localhost:3000 user@server # Now server:8080 reaches your localhost:3000Useful 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@serverThen 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/ # Recursiversync β 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
# 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_keysSee also: Git Permission Denied (publickey) fix