SSH Command Cheatsheet
SSH (Secure Shell) is the foundation of remote server management and secure communication. This cheatsheet covers the most commonly used SSH commands — from basic connections to advanced tunneling — each with practical examples. Whether you're new to server management or need a quick SSH reference, this guide has you covered.
Quick Reference
| Task | Command |
| Connect to a remote server | ssh user@host |
| Generate a key pair | ssh-keygen -t ed25519 |
| Copy public key to server | ssh-copy-id user@host |
| Upload a file | scp file user@host:/path/ |
| Sync a directory | rsync -avz dir/ user@host:/path/ |
| Local port forwarding | ssh -L 8080:localhost:80 user@host |
| SOCKS proxy | ssh -D 1080 user@host |
| Debug connection issues | ssh -vvv user@host |
Remote Connection
``bash
# Basic connection
ssh user@example.com # Default port 22
ssh -p 2222 user@host # Custom port
ssh -i ~/.ssh/key.pem user@host # Specific identity file
# Jump host / Bastion ssh -J user@bastion user@internal # Single jump host ssh -J user@jump1,user@jump2 user@target # Multi-hop jump
# Remote command execution ssh user@host 'df -h' # Execute a single command ssh -t user@host 'top' # Force TTY for interactive commands ssh user@host 'bash -s' < script.sh # Run a local script remotely
# Other connection options
ssh -N -L 8080:localhost:80 user@host # Tunnel only (no shell)
ssh -4 user@host # Force IPv4 only
ssh -6 user@host # Force IPv6 only
`
Key Management
`bash
# Generate key pairs
ssh-keygen -t ed25519 -C "you@email.com" # Ed25519 (recommended)
ssh-keygen -t rsa -b 4096 # RSA (legacy compatible)
ssh-keygen -t ed25519 -f ~/.ssh/custom_key # Custom filename
# Copy public key to server ssh-copy-id user@host # Append to ~/.ssh/authorized_keys ssh-copy-id -i ~/.ssh/custom_key.pub user@host # Copy a specific key
# SSH Agent ssh-agent -s # Start the agent ssh-add ~/.ssh/id_ed25519 # Add a key to the agent ssh-add -l # List keys in the agent ssh-add -D # Remove all keys from agent
# Retrieve host keys ssh-keyscan github.com # Retrieve a remote host's public key ssh-keyscan -t ed25519 example.com # Specify key type
# Manage known_hosts ssh-keygen -R example.com # Remove a host key ssh-keygen -F example.com # Look up a host key
# Inspect / modify keys
ssh-keygen -p -f ~/.ssh/id_ed25519 # Change passphrase
ssh-keygen -lf ~/.ssh/id_ed25519.pub # View public key fingerprint
ssh-keygen -y -f ~/.ssh/id_ed25519 # Export public key from private
`
Client Configuration
Config file location: ~/.ssh/config (permissions: chmod 600 ~/.ssh/config)
Single host configuration:
`
Host myserver
HostName example.com
User myuser
Port 2222
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
`
Wildcard configuration:
`
Host *.internal.example.com
User admin
IdentityFile ~/.ssh/internal-key
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github-key
`
After configuring, connect simply with ssh myserver. You can also use ssh -F ~/.ssh/config-custom myserver to specify an alternative config file.
File Transfer
`bash
# SCP
scp file.txt user@host:/path/ # Upload file to remote
scp user@host:/path/file.txt . # Download file from remote
scp -r ./dist/ user@host:/var/www/ # Recursively upload directory
scp -P 2222 file user@host:/path/ # Custom port
# RSYNC (recommended for large files / directory sync) rsync -avz ./src/ user@host:/path/ # Incremental sync to remote rsync -avz --delete ./src/ user@host:/path/ # Mirror sync (includes deletion) rsync -avz user@host:/path/ ./backup/ # Sync from remote to local rsync -avz -e "ssh -p 2222" ./ user@host:/ # Via custom SSH port
# SFTP
sftp user@host # Interactive file transfer
sftp -oPort=2222 user@host # Custom port
# Inside SFTP: ls, cd, get, put, rm, mkdir
`
Port Forwarding & Tunneling
`bash
# Local port forwarding (map remote port to local)
ssh -L 8080:localhost:80 user@host # Remote 80 → local 8080
ssh -L 3306:db-internal:3306 bastion # Access internal DB via bastion
ssh -L 8080:localhost:80 -L 9090:localhost:90 # Multiple port forwards
# Remote port forwarding (expose local port on remote) ssh -R 8080:localhost:3000 user@host # Local 3000 → remote 8080 ssh -R 0.0.0.0:8080:localhost:3000 user@host # Allow external access to remote port
# SOCKS5 dynamic proxy ssh -D 1080 user@proxy # Local port 1080 as SOCKS proxy # Configure your browser to use SOCKS proxy at localhost:1080
# Persistent tunnel with autossh (production-grade)
autossh -M 0 -o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
-L 3306:localhost:3306 user@host # Auto-reconnecting tunnel
`
Troubleshooting
`bash
# Debug output
ssh -v user@host # Verbose (good for connection issues)
ssh -vvv user@host # Very verbose (full debug output)
ssh -T git@github.com # Test SSH connection without shell
# Connection option debugging ssh -o StrictHostKeyChecking=no user@host # ⚠️ Skip host key check (test only) ssh -o UserKnownHostsFile=/dev/null user@host # Skip known_hosts ssh -o LogLevel=DEBUG user@host # Adjust log level
# Network & capability tests ssh -Q cipher # List supported ciphers ssh -Q mac # List supported MAC algorithms ssh -Q kex # List supported key exchange algorithms
# Server config check (requires root) sshd -T # Test sshd config validity netstat -tlnp | grep :22 # Check SSH listening status
`
SSH Hardening Best Practices
`bash
# Server-side security (/etc/ssh/sshd_config)
# Disable root login PermitRootLogin no
# Key-only authentication PasswordAuthentication no PubkeyAuthentication yes
# Enforce SSH protocol 2 Protocol 2
# Restrict allowed users AllowUsers alice bob
# Change default port (reduces scan attacks) Port 2222
# Restart after changes sudo systemctl restart sshd ``
Connection(7)
| Command | Level | ||
|---|---|---|---|
ssh user@hostConnect to a remote server via SSH | Basic | ssh deploy@192.168.1.100 | |
ssh -p <port>Connect on a custom port (default: 22) | Basic | ssh -p 2222 user@host | |
ssh -i <keyfile>Connect using a specific private key | Basic | ssh -i ~/.ssh/aws-key.pem ec2-user@aws-host | |
ssh -J <jumphost> <target>Connect via a jump host / bastion | Intermediate | ssh -J user@bastion.example.com user@internal-host | |
ssh -t <host> '<cmd>'Force TTY allocation and run a remote command | Intermediate | ssh -t user@host 'top' | |
ssh -N -L <local>:<target>:<remote>Create a port forward without executing a remote command | Intermediate | ssh -N -L 8080:localhost:80 user@host | |
ssh -4 / ssh -6Force IPv4 / IPv6 connection | Basic | ssh -4 user@host |
Key Management(8)
| Command | Level | ||
|---|---|---|---|
ssh-keygen -t ed25519Generate an Ed25519 key pair (recommended) | Basic | ssh-keygen -t ed25519 -C "my@email.com" | |
ssh-keygen -t rsa -b 4096Generate an RSA 4096-bit key pair (legacy compatibility) | Basic | ssh-keygen -t rsa -b 4096 | |
ssh-copy-id user@hostCopy your public key to a remote server | Basic | ssh-copy-id user@server.example.com | |
ssh-add ~/.ssh/id_ed25519Add a private key to the SSH agent | Basic | ssh-add ~/.ssh/id_ed25519 | |
ssh-keygen -pChange the passphrase of an SSH private key | Intermediate | ssh-keygen -p -f ~/.ssh/id_ed25519 | |
ssh-keygen -R <hostname>Remove a host key from known_hosts | Basic | ssh-keygen -R example.com | |
ssh-add -lList keys currently loaded in the SSH agent | Basic | ssh-add -l | |
ssh-keyscan <host>Retrieve a remote host's public key (for CI/CD setup) | Intermediate | ssh-keyscan github.com >> ~/.ssh/known_hosts |
Config(2)
| Command | Level | ||
|---|---|---|---|
~/.ssh/configSSH client configuration file | Intermediate | Host myserver
HostName example.com
User myuser
Port 2222
IdentityFile ~/.ssh/id_ed25519
| |
ssh -F <config>Use an alternative SSH config file | Intermediate | ssh -F ~/.ssh/config-custom myserver |
File Transfer(6)
| Command | Level | ||
|---|---|---|---|
scp <file> user@host:<path>Copy a file to a remote server | Basic | scp app.tar.gz deploy@server:/var/www/ | |
scp user@host:<path> <local-dir>Copy a file from a remote server to local | Basic | scp admin@backup:/data/dump.sql ./ | |
scp -r <dir> user@host:<path>Recursively copy a directory to remote | Basic | scp -r ./build/ user@server:/var/www/html/ | |
rsync -avz <src> user@host:<dest>Incrementally sync a local directory to remote (recommended for backup/deploy) | Intermediate | rsync -avz --delete ./dist/ user@server:/var/www/ | |
rsync -avz user@host:<src> <local-dest>Incrementally sync from remote server to local | Intermediate | rsync -avz user@server:/backups/ ./backups/ | |
sftp user@hostInteractive file transfer via SFTP | Basic | sftp deploy@staging.example.com |
Tunneling(4)
| Command | Level | ||
|---|---|---|---|
ssh -L <local-port>:<target>:<target-port> <host>Local port forwarding (map a remote port to your local machine) | Intermediate | ssh -L 3306:database.internal:3306 bastion | |
ssh -R <remote-port>:<local>:<local-port> <host>Remote port forwarding (expose a local port to a remote machine) | Intermediate | ssh -R 8080:localhost:3000 user@public-host | |
ssh -D <local-port> <host>SOCKS5 dynamic proxy (use local port as a proxy) | Intermediate | ssh -D 1080 user@proxy-server | |
autossh -M 0 -L ...Auto-reconnecting persistent SSH tunnel | Expert | autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -L 3306:localhost:3306 user@host |
Troubleshooting(10)
| Command | Level | ||
|---|---|---|---|
ssh -v <host>Verbose mode (see connection details) | Basic | ssh -v user@host | |
ssh -vvv <host>Extremely verbose (full debug info) | Intermediate | ssh -vvv user@host | |
ssh -o ServerAliveInterval=<seconds>Set keepalive interval to prevent timeout disconnects | Intermediate | ssh -o ServerAliveInterval=60 user@host | |
ssh -o StrictHostKeyChecking=noSkip host key checking (⚠️ test environments only) Disabling host key checking reduces security and risks MITM attacks. Use only for temporary test environments. | Intermediate | ssh -o StrictHostKeyChecking=no user@host | |
ssh -Q cipherList supported ciphers for the SSH client | Expert | ssh -Q cipher | |
ssh -Q macList supported MAC algorithms | Expert | ssh -Q mac | |
ssh -Q kexList supported key exchange algorithms | Expert | ssh -Q kex | |
ssh -T <host>Test SSH connection without allocating a TTY | Intermediate | ssh -T git@github.com | |
ssh -o UserKnownHostsFile=/dev/nullSkip known_hosts file (⚠️ test environments only) Skipping known_hosts verification reduces security — test environments only. | Intermediate | ssh -o UserKnownHostsFile=/dev/null user@host | |
sshd -TTest sshd server configuration for validity | Expert | sshd -T |