Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

SSH Cheatsheet

Basic Connection

CommandDescription
ssh user@hostConnect to remote host
ssh -p 2222 user@hostConnect on custom port
ssh -i ~/.ssh/key.pem user@hostConnect with specific key
ssh -v user@hostVerbose mode (debug)
ssh -vvv user@hostExtra verbose

Authentication

Key-Based Auth

# Generate key pair
ssh-keygen -t ed25519 -C "comment"
ssh-keygen -t rsa -b 4096 -C "comment"

# Copy public key to server
ssh-copy-id user@host
ssh-copy-id -i ~/.ssh/key.pub user@host

# Manual copy
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Key Permissions

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config

SSH Config File

Location: ~/.ssh/config

Host myserver
    HostName 192.168.1.100
    User admin
    Port 22
    IdentityFile ~/.ssh/myserver_key

Host jumpbox
    HostName jump.example.com
    User deployer
    IdentityFile ~/.ssh/jump_key

Host internal
    HostName 10.0.0.50
    User admin
    ProxyJump jumpbox

Config Options

OptionDescription
HostNameActual hostname/IP
UserDefault username
PortSSH port
IdentityFilePath to private key
ProxyJumpJump host for tunneling
ForwardAgentForward SSH agent (yes/no)
LocalForwardPersistent local tunnel
DynamicForwardPersistent SOCKS proxy

Port Forwarding / Tunneling

Local Port Forwarding (-L)

Forward a local port to a remote destination through the SSH server.

ssh -L [local_addr:]local_port:remote_host:remote_port user@ssh_server

Use case: Access a service on a remote network that’s not directly reachable.

# Forward local port 8080 to remote host's port 80
ssh -L 8080:webserver.internal:80 user@jumphost

# Access via: http://localhost:8080

PostgreSQL Example (Remote DB on localhost)

Scenario: PostgreSQL on dbserver only listens on 127.0.0.1:5432. You need to connect from your workstation.

# Create tunnel
ssh -L 5432:localhost:5432 user@dbserver

# Now connect locally
psql -h localhost -p 5432 -U dbuser -d mydb

Or use a different local port to avoid conflicts:

# Forward local 15432 to remote's localhost:5432
ssh -L 15432:localhost:5432 user@dbserver

# Connect via the tunnel
psql -h localhost -p 15432 -U dbuser -d mydb

# Or with connection string
psql "postgresql://dbuser:password@localhost:15432/mydb"

Background tunnel (no shell):

ssh -fNL 15432:localhost:5432 user@dbserver

# -f: Background after auth
# -N: No remote command (tunnel only)
# -L: Local forward

Multiple Forwards

ssh -L 5432:localhost:5432 -L 6379:localhost:6379 user@server

Remote Port Forwarding (-R)

Expose a local service to the remote network.

ssh -R [remote_addr:]remote_port:local_host:local_port user@ssh_server

Use case: Make your local dev server accessible from the remote server.

# Expose local port 3000 on remote server's port 8080
ssh -R 8080:localhost:3000 user@remote

# On remote: curl localhost:8080 hits your local :3000

Dynamic Port Forwarding (-D) - SOCKS Proxy

Create a SOCKS proxy that routes all traffic through the SSH server.

ssh -D [local_addr:]local_port user@ssh_server

Use case: Browse the web or access multiple services as if you were on the remote network.

# Create SOCKS5 proxy on localhost:1080
ssh -D 1080 user@remote

# Configure browser/apps to use SOCKS5 proxy: localhost:1080

Using the SOCKS Proxy

curl:

curl --socks5 localhost:1080 http://internal.site.local

proxychains:

# /etc/proxychains.conf
socks5 127.0.0.1 1080

# Run commands through proxy
proxychains psql -h db.internal -U admin -d mydb
proxychains nmap -sT 10.0.0.0/24

Browser: Configure SOCKS5 proxy in Firefox/Chrome settings or use FoxyProxy.

PostgreSQL via SOCKS Proxy

# Start SOCKS proxy
ssh -D 1080 user@jumphost

# Use proxychains
proxychains psql -h db.internal.local -p 5432 -U dbuser -d mydb

Tunnel Comparison

TypeFlagDirectionUse Case
Local-LLocal → RemoteAccess remote service locally
Remote-RRemote → LocalExpose local service remotely
Dynamic-DSOCKS ProxyRoute all traffic through SSH

Tunnel Options

FlagDescription
-fBackground after authentication
-NNo remote command (tunnel only)
-TDisable pseudo-terminal allocation
-gAllow remote hosts to connect to forwarded ports

Common Tunnel Command

# Background tunnel, no shell
ssh -fNT -L 5432:localhost:5432 user@server

# Check tunnel is running
ps aux | grep ssh
lsof -i :5432

Jump Hosts / Bastion

ProxyJump (Modern)

ssh -J jumphost user@internal

# Multiple jumps
ssh -J jump1,jump2 user@internal

ProxyCommand (Legacy)

ssh -o ProxyCommand="ssh -W %h:%p jumphost" user@internal

Config File

Host internal
    HostName 10.0.0.50
    User admin
    ProxyJump jumphost

SSH Agent

# Start agent
eval $(ssh-agent)

# Add key
ssh-add ~/.ssh/id_ed25519

# Add with timeout (1 hour)
ssh-add -t 3600 ~/.ssh/id_ed25519

# List keys
ssh-add -l

# Remove all keys
ssh-add -D

Agent Forwarding

ssh -A user@host

Warning: Agent forwarding can be a security risk on untrusted hosts.


File Transfer

SCP

# Upload
scp file.txt user@host:/path/

# Download
scp user@host:/path/file.txt ./

# Recursive
scp -r folder/ user@host:/path/

# With custom port
scp -P 2222 file.txt user@host:/path/

SFTP

sftp user@host
sftp> put localfile
sftp> get remotefile
sftp> ls
sftp> cd /path
sftp> exit

Rsync over SSH

rsync -avz -e ssh source/ user@host:/dest/
rsync -avz -e "ssh -p 2222" source/ user@host:/dest/

Escape Sequences

Press ~ after newline:

SequenceAction
~.Disconnect
~^ZBackground SSH
~#List forwarded connections
~?Help
~COpen command line (add forwards)

Add Forward to Running Session

~C
ssh> -L 8080:localhost:80

Security Options

OptionDescription
-o StrictHostKeyChecking=yesReject unknown hosts
-o UserKnownHostsFile=/dev/nullDon’t save host keys
-o PasswordAuthentication=noForce key auth
-o PubkeyAuthentication=yesEnable key auth

Disable Host Key Checking (Testing Only)

ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@host

Practical Examples

Access Remote PostgreSQL (localhost only)

# Scenario: PostgreSQL on server only binds to 127.0.0.1:5432

# Option 1: Local forward
ssh -L 5432:127.0.0.1:5432 user@dbserver
psql -h localhost -U postgres -d mydb

# Option 2: Different local port
ssh -fNL 15432:127.0.0.1:5432 user@dbserver
psql -h localhost -p 15432 -U postgres -d mydb

# Option 3: Via jump host
ssh -L 5432:dbserver.internal:5432 user@jumphost
psql -h localhost -U postgres -d mydb

Access Remote Redis

ssh -L 6379:localhost:6379 user@server
redis-cli -h localhost

Browse Internal Network

ssh -D 9050 user@internal-host
# Configure browser SOCKS5: localhost:9050

Tunnel to Multiple Services

ssh -L 5432:localhost:5432 \
    -L 6379:localhost:6379 \
    -L 8080:webapp.internal:80 \
    user@jumphost

Troubleshooting

IssueSolution
Connection refusedCheck SSH service, firewall, port
Permission deniedCheck key permissions, user, auth method
Host key changedRemove old key: ssh-keygen -R host
Tunnel not workingCheck if remote port is listening on localhost
Broken pipeAdd ServerAliveInterval 60 to config

Debug Connection

ssh -vvv user@host

Keep Connection Alive

# ~/.ssh/config
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3