SSH
Comprehensive SSH cheatsheet covering OpenSSH client usage, authentication methods, port forwarding, key management, X11 forwarding, and configuration options. Includes real-world examples and security best practices.
No commands found
Try adjusting your search term
Getting Started
Basic SSH Connection
Establishing remote connections to servers
Connect to Remote Host with Default Settings
Connects to a remote host using SSH, with interactive password authentication. The host key is verified and stored in ~/.ssh/known_hosts
ssh hostnameThe authenticity of host 'hostname (192.168.1.100)' can't be established.ECDSA key fingerprint is SHA256:abc123xyz...Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added 'hostname' (ECDSA) to the list of known hosts.Last login: Wed Feb 28 10:30:42 2026 from 192.168.1.50user@hostname:~$- First connection will prompt for host key verification
- Uses default SSH port 22
- Requires password authentication if no keys configured
Connect with Specific Username
Connect using a specific username different from local user. Format is [user@]hostname
ssh user@hostnameuser@hostname's password:Last login: Wed Feb 28 10:35:15 2026 from 192.168.1.50user@hostname:~$- If username not specified, uses current local username
- Can also specify as user@domain.com or user@ip.address
Connect to Non-Standard Port
SSH server might run on ports other than 22. Use -p flag to specify alternative port
ssh -p 2222 user@hostnameuser@hostname's password:Last login: Wed Feb 28 09:15:22 2026 from 192.168.1.50user@hostname:~$- Port must be specified before hostname
- Common alternative port is 2222
- Can also configure in ~/.ssh/config
Authentication Methods
Public Key Authentication
Using SSH keys for passwordless authentication
Generate ED25519 SSH Key Pair
Create a new ED25519 key pair. This modern algorithm is preferred over RSA for better security
ssh-keygen -t ed25519 -C "user@example.com"Generating public/private ed25519 key pair.Enter file in which to save the key (/home/user/.ssh/id_ed25519):Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /home/user/.ssh/id_ed25519Your public key has been saved in /home/user/.ssh/id_ed25519.pubThe key fingerprint is: SHA256:xyz123abc... user@example.com- Ed25519 is the recommended key type (fast, secure, compact)
- Use -C to add a comment identifying the key
- Protect private key with strong passphrase
Add Public Key to Remote Host
Copy public key to remote host's authorized_keys. Enables passwordless login
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub"/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s).../usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed - if you want to re-run this setup...Number of key(s) added: 1- Requires initial password authentication
- Appends to ~/.ssh/authorized_keys on remote
Connect Using Specific Key
Explicitly specify private key for authentication. Useful when multiple keys exist
ssh -i ~/.ssh/id_ed25519 user@hostnameLast login: Wed Feb 28 11:45:30 2026 from 192.168.1.50user@hostname:~$- SSH tries default keys if -i not specified
- Default keys: ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519
Password Authentication
Interactive password-based login
Force Password Authentication
Disable public key auth and force password authentication. Useful for testing or shared accounts
ssh -o PubkeyAuthentication=no user@hostnameuser@hostname's password:Last login: Wed Feb 28 10:20:15 2026user@hostname:~$- Password transmitted securely through SSH tunnel
- Server must have PasswordAuthentication enabled
Non-Interactive Password (Using sshpass)
Pass password non-interactively using sshpass utility. Not recommended for security
sshpass -p 'password' ssh user@hostnameLast login: Wed Feb 28 11:25:10 2026user@hostname:~$- sshpass must be installed separately
- Security risk: password visible in process list and history
- Use SSH keys instead for automation
SSH Agent & Key Forwarding
Use ssh-agent to manage keys across multiple hops
Start SSH Agent in Current Shell
Initialize SSH agent in current shell session. Required before adding keys
eval "$(ssh-agent -s)"Agent pid 12345- Agent runs as background process
- PID stored in SSH_AUTH_SOCK environment variable
Add Private Key to Agent
Add private key to SSH agent. Benefits: Enter passphrase once, agent handles auth on multiple connections
ssh-add ~/.ssh/id_ed25519Enter passphrase for /home/user/.ssh/id_ed25519:Identity added: /home/user/.ssh/id_ed25519 (user@example.com)- Prompted for passphrase only once
- Key unlocked in agent memory until timeout or logout
Enable Agent Forwarding to Remote Host
Forward SSH agent connection to remote host. Allows using local keys from remote for further hops (jump hosts)
ssh -A user@hostnameLast login: Wed Feb 28 12:00:00 2026user@hostname:~$ ssh-add -l256 SHA256:xyz... user@example.com (ED25519)- Requires ForwardAgent yes in ssh_config (or use -A flag)
- Security: Only enable for trusted hosts
- Useful for jump host scenarios
Port Forwarding & Tunneling
Local Port Forwarding
Forward local port to remote service
Forward Local Port to Remote Service
Forward localhost:3306 through SSH tunnel to remote database server. Local connections to 3306 proxy through SSH
ssh -L 3306:localhost:3306 user@database-hostLast login: Wed Feb 28 08:30:00 2026user@database-host:~$- Format: -L [bind_address:]local_port:remote_host:remote_port
- Connection stays open for tunnel to function
- Useful for accessing internal services through SSH
Forward with Non-Standard Local Port
Forward local port 13306 to remote database server db.internal:3306. Avoids port conflicts with local services
ssh -L 13306:db.internal:3306 user@bastion-hostuser@bastion-host:~$- Connect to localhost:13306 to access remote database
- Allows multiple forwards on different local ports
Forward Multiple Ports
Forward multiple local ports to different remote services through single SSH connection
ssh -L 3306:db:3306 -L 5432:db:5432 user@bastion-hostuser@bastion-host:~$- Use multiple -L flags for each port forward
- Efficient: only one SSH tunnel to bastion
Remote Port Forwarding
Forward remote port to local service
Expose Local Service to Remote Network
Forward remote port 8080 to local service on 8080. Remote server can access local service. Enables public access to private service
ssh -R 8080:localhost:8080 user@public-serveruser@public-server:~$- Format: -R [bind_address:]remote_port:local_host:local_port
- Requires GatewayPorts yes on remote server for external access
- Useful for exposing localhost dev server to internet
Bind to All Interfaces on Remote
Expose local service to all interfaces on remote host (not just localhost). Requires GatewayPorts enabled
ssh -R '*':3000:localhost:3000 user@public-serveruser@public-server:~$- Use '*' or empty bind_address for all interfaces
- Security: Only do for development, not production
Dynamic Port Forwarding (SOCKS Proxy)
Create SOCKS proxy through SSH tunnel
Create SOCKS5 Proxy
Create SOCKS5 proxy on localhost:1080. All traffic through proxy routes through SSH tunnel to remote network
ssh -D 1080 user@ssh-serverLast login: Wed Feb 28 09:15:00 2026user@ssh-server:~$- Format: -D [bind_address:]local_port
- Browser/application must support SOCKS5
- Useful for accessing services on remote private network
Configure Browser to Use SOCKS Proxy
Route traffic through SOCKS proxy to access internal services as if on remote network
# Firefox: Preferences > General > Network Settings > SOCKS Host# localhost, port 1080, SOCKS v5
# Or use command-line toolcurl --socks5 localhost:1080 https://internal.company.com<!DOCTYPE html><html><head><title>Internal Company Site</title></head><body>Welcome to internal site</body></html>- Many tools support SOCKS: curl, youtube-dl, etc.
Key Management
Creating and Managing Keys
Generate, manage, and secure SSH keys
Generate RSA Key for Legacy Systems
Create RSA key for systems that don't support Ed25519. Use 4096-bit for adequate security
ssh-keygen -t rsa -b 4096 -C "legacy-key"Generating public/private rsa key pair.Enter file in which to save the key (/home/user/.ssh/id_rsa):Enter passphrase (empty for no passphrase):Your identification has been saved in /home/user/.ssh/id_rsaYour public key has been saved in /home/user/.ssh/id_rsa.pub- RSA requires larger key size (4096) compared to Ed25519 (256)
- Slower but widely supported
List Keys Added to Agent
Display all keys currently loaded in SSH agent with their fingerprints
ssh-add -l256 SHA256:xyz... user@example.com (ED25519)4096 SHA256:abc... legacy-key (RSA)- Shows key type, fingerprint, and comment
- Returns exit code 1 if agent not running
Export Public Key from Private Key
Recover/regenerate public key from existing private key
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJxyz... user@example.com- Useful if public key lost
- Only works if you have the private key
Managing Authorized Keys
Control which keys can access your account
View Authorized Keys
Display all public keys that can authenticate as current user. One key per line
cat ~/.ssh/authorized_keysssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO.../key1 user@host1ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO.../key2 user@host2ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA... legacy-key- File location: ~/.ssh/authorized_keys
- Permissions must be 600
- Directory ~/.ssh must be 700
Remove Specific Key
Remove specific key by filtering it out. Revokes access for that key
grep -v "key1" ~/.ssh/authorized_keys > /tmp/authorized_keys.tmpmv /tmp/authorized_keys.tmp ~/.ssh/authorized_keys(file updated)- Use tools like ssh-keyscan for managing multiple hosts
Set Command Restrictions on Key
Restrict key to only execute specific command. Useful for automation/backups with limited permissions
echo 'command="/usr/local/bin/backup.sh" ssh-ed25519 AAAAC3...' >> ~/.ssh/authorized_keys(user logging in with this key will only run backup.sh)- Key can only run the specified command
- Useful for automated backups, deployments
Configuration & Advanced Setup
SSH Config File
Configure hosts, defaults, and connection settings in ~/.ssh/config
Basic Host Configuration
Define host aliases and connection parameters in ~/.ssh/config. Simplifies repeated connections
cat ~/.ssh/configHost myserver HostName server.example.com User admin Port 2222 IdentityFile ~/.ssh/id_ed25519
Host *.internal User intern_user ProxyJump bastion- Format: Host pattern followed by configuration options
- * and ? wildcards supported in Host patterns
- Configuration applied in order, first match wins
Connect Using Host Alias
Use hostname alias instead of full connection details. All config parameters applied automatically
ssh myserverLast login: Wed Feb 28 14:30:00 2026admin@myserver:~$- Reads from ~/.ssh/config automatically
- Command line options override config file
Jump Host / Bastion Configuration
Use ProxyJump to tunnel through bastion host to reach internal servers. Cleaner than -J flag
Host bastion HostName bastion.company.com User bastionuser
Host internal-*.company.com ProxyJump bastion User internaluser
ssh internal-db.company.com(SSH connects through bastion automatically)Last login: Wed Feb 28 15:00:00 2026internaluser@internal-db:~$- ProxyJump added in OpenSSH 7.3
- Can chain multiple jumps: ProxyJump host1,host2
Connection Multiplexing
Reuse SSH connections for faster subsequent logins
Enable Connection Multiplexing
Enable multiplexing globally. Auto reuses master connections for 1 hour
# Add to ~/.ssh/configHost * ControlMaster auto ControlPath ~/.ssh/control-%h-%r-%p ControlPersist 3600(settings saved)- ControlMaster auto: automatically create master on first connection
- ControlPath: location of control socket
- ControlPersist 3600: keep master alive for 1 hour after last client
Multiple Connections Using Master
Second and subsequent connections reuse the master SSH tunnel, bypassing authentication
# First connection (creates master)ssh user@host
# In another terminal: reuses existing connectionssh user@host(second connection opens instantly)- Dramatically faster since TCP/auth already done
- Check control sockets: ls -la ~/.ssh/control-*
Explicitly Check Master Connection
Check if multiplexed connection is active to a host
ssh -O check user@hostMaster running (pid=12345)- exit code 0 if master running
- Useful for scripts
Security Best Practices
Protecting Your Keys
Keep SSH keys secure from unauthorized access
Fix SSH Directory Permissions
SSH requires specific permissions for security. SSH will refuse keys with wrong permissions
chmod 700 ~/.sshchmod 600 ~/.ssh/id_*chmod 600 ~/.ssh/authorized_keyschmod 644 ~/.ssh/*.pub(permissions updated)- ~/.ssh directory: 700 (rwx------)
- Private key files: 600 (rw-------)
- Public key files: 644 (rw-r--r--)
- authorized_keys: 600 (rw-------)
Test Key Permissions
Verify all permissions are correct. Private keys only readable by owner
ls -la ~/.ssh/total 32drwx------ 2 user user 4096 Feb 28 10:30 .-rw------- 1 user user 464 Feb 28 10:30 id_ed25519-rw-r--r-- 1 user user 89 Feb 28 10:30 id_ed25519.pub-rw------- 1 user user 1679 Feb 28 10:30 authorized_keys- First column shows permissions
- Directory should start with 'd'
- Private keys should be 'rw-------'
Rotate Compromised Key
After compromise, remove old key from all authorized_keys and generate new one
# Step 1: Remove old key from authorized_keys on all serversgrep -l "old_key_fingerprint" ~/.ssh/authorized_keys | while read f; do sed -i '/old_key_fingerprint/d' "$f"done
# Step 2: Delete local private keyrm ~/.ssh/id_rsa
# Step 3: Generate new keyssh-keygen -t ed25519 -C "new-key"(key rotated)- Must rotate across all servers
- May need temporary password access to add new key
Host Key Verification
Verify remote host authenticity to prevent MITM attacks
First Connection Host Key Verification
On first connection, SSH shows host key fingerprint for verification. Accept only if verified from trusted source
ssh user@newhostThe authenticity of host 'newhost (192.168.1.100)' can't be established.ED25519 key fingerprint is SHA256:abcxy123...This key is not known by any other namesAre you sure you want to continue connecting (yes/no/[fingerprint])?- Fingerprint should match official host key
- Answer 'yes' to add to ~/.ssh/known_hosts
- Subsequent connections won't show this prompt
Verify Host Key Fingerprint Manually
Verify fingerprint matches what SSH showed during connection attempt
# On the remote hostssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub256 SHA256:abcxy123... root@newhost (ED25519)- Run on remote server admin console
- Compare with fingerprint displayed during SSH connection
Check Existing Host Key
Display all known host keys and their fingerprints from ~/.ssh/known_hosts
ssh-keygen -l -f ~/.ssh/known_hosts256 SHA256:old_key... hostname1 (ED25519)256 SHA256:new_key... hostname2 (ED25519)- Helps identify if host key has changed
- Unexpected changes may indicate compromise or reconfiguration
Advanced Usage
Jump Hosts & Bastion Patterns
Connect through intermediate hosts to reach internal servers
Single Hop Through Jump Host
Use jump host to reach internal server. SSH tunnels through bastion automatically
ssh -J user@bastion:2222 user@internal-serverLast login: Wed Feb 28 16:30:00 2026user@internal-server:~$- Format: -J [user@]host[:port]
- Can specify non-standard port on jump host
- Automatically applies ProxyCommand
Multiple Hops Through Jump Hosts
Chain multiple jump hosts. Connection routes through bastion1 -> bastion2 -> final-host
ssh -J user@bastion1,user@bastion2 user@final-host(connected through chain of hosts)user@final-host:~$- Separate hosts with commas
- Each hop authenticates independently
Persistent Jump Host Configuration
Configure jump host in ~/.ssh/config for permanent setup. All internal-* hosts use bastion
Host bastion HostName bastion.company.com User admin
Host internal-* ProxyJump bastion User devuser
# Usage: ssh internal-server1(automatic jump through bastion)- ProxyJump simpler than older ProxyCommand
- Inherits authentication from config
X11 Forwarding
Run graphical applications on remote servers and display locally
Enable X11 Forwarding
Forward X11 display from remote to local machine. Start GUI apps on remote, see them locally
ssh -X user@remote-hostuser@remote-host:~$ gedit &(gedit window opens on local display)- Requires X11 server on local machine (native on Linux/macOS)
- -X: standard X11 forwarding
- -Y: trusted X11 forwarding (skips security checks)
Trusted X11 Forwarding
Trusted X11 forwarding allows apps to access X11 security extensions. Faster but less secure
ssh -Y user@remote-hostuser@remote-host:~$ firefox &(firefox window opens on local display)- Use for trusted hosts only
- -Y skips X11 SECURITY extension
- Performance improvement over standard -X
Test X11 Forwarding
DISPLAY variable set by SSH indicates X11 tunnel is active
ssh -X user@remote-hostecho $DISPLAYlocalhost:10.0- DISPLAY set to localhost:N where N > 0
- Value 0 would indicate no X11 forwarding
Practical Real-World Examples
Common Use Cases
Real-world examples and practical patterns
Copy Files Using SCP
SCP (secure copy) transfers files through SSH tunnel. Secure alternative to FTP
# Copy file from local to remotescp /local/path/file user@host:/remote/path/
# Copy file from remote to localscp user@host:/remote/path/file /local/path/
# Copy directory recursivelyscp -r user@host:/remote/path/ /local/path/file 100% 1234KB 5.2MB/s 00:00- Uses SSH for encryption
- -r flag for recursive directory copy
- -P for non-standard port (uppercase!)
Sync Directory with rsync Over SSH
rsync over SSH for efficient file synchronization. Only transfers changed files
# Sync local to remotersync -avz -e ssh /local/path/ user@host:/remote/path/
# Sync remote to localrsync -avz -e ssh user@host:/remote/path/ /local/path/
# With non-standard SSH portrsync -avz -e 'ssh -p 2222' /local/path/ user@host:/remote/path/sending incremental file listfile1file2sent 1234 bytes received 567 bytestotal size is 5678 speedup is 3.21- Much faster than scp for large directories
- -a: archive mode (preserves permissions)
- -v: verbose, -z: compress
- Better for backups and deployments
Run Remote Command and Get Output
Execute remote commands and get output without interactive shell. Useful for scripts
# Execute single commandssh user@host "ps aux | grep nodejs"
# Execute multiple commandsssh user@host "cd /app && npm start"
# Run command and capture outputresult=$(ssh user@host "docker ps -a")echo "$result"user 12345 0.5 15.3 234567 89012 ? Sl 14:30 0:05 node /app/server.js- Command in quotes runs on remote, output sent to stdout
- Exit code preserved: useful in bash conditionals
- Great for cronjobs and automation
Automated Backup to Remote Host
Stream compressed backup to remote server. Efficient and no local temporary files
#!/bin/bash# backup.sh - automated backup script
LOCAL_PATH="/home/user/important-data"BACKUP_HOST="backup.example.com"BACKUP_USER="backup"BACKUP_PATH="/backups/$(hostname)"
# Create backuptar czf - "$LOCAL_PATH" | ssh $BACKUP_USER@$BACKUP_HOST \ "cat > $BACKUP_PATH/backup-$(date +%Y%m%d).tar.gz"
echo "Backup completed"Backup completed- tar pipes directly through SSH
- No local disk space needed for backup
- Useful for cron jobs with SSH key auth
Port Forward for Database Connection
Access private database server through SSH tunnel. Database thinks it's local
# Terminal 1: Create tunnelssh -L 3306:internal-db:3306 -N user@bastion
# Terminal 2: Connect to local portmysql -h localhost -u dbuser -pEnter password:Welcome to MariaDB Monitor. Commands...- -N: don't execute remote command
- Keep tunnel running in separate terminal
- Connection is end-to-end encrypted
SSH Agent for Automated Deployments
Use SSH agent in scripts for passwordless authentication. Clean up after
#!/bin/bash# deploy.sh - automated deployment
# Start SSH agent for this scripteval "$(ssh-agent -s)"ssh-add ~/.ssh/deploy-key
# Deploy to multiple serversfor server in web1 web2 web3; do ssh -o StrictHostKeyChecking=accept-new deploy@$server \ "cd /app && git pull && npm start"done
# Kill agent when donessh-agent -kdeployment to web1... donedeployment to web2... donedeployment to web3... done- ssh-agent managed within script
- StrictHostKeyChecking=accept-new for new hosts
- Always kill agent to avoid leaked credentials
Troubleshooting
Debugging SSH Connection Issues
Diagnose and fix common SSH problems
Enable Verbose Output for Debugging
Verbose flags show detailed connection process. Level indicates where connection fails
# Single verbose (-v): shows authentication methodssh -v user@host
# Double verbose (-vv): shows handshake detailsssh -vv user@host
# Triple verbose (-vvv): shows all details including cryptossh -vvv user@hostOpenSSH_8.0p1 Ubuntu 1:8.0p1-6ubuntu1, OpenSSL 1.1.1debug1: Reading configuration data /home/user/.ssh/configdebug1: No more authentication methods to try.Permission denied (publickey,password).- -v: high-level flow
- -vv: detailed authentication
- -vvv: packet-level (very verbose)
Check SSH Key Permissions
SSH refuses to use keys with improper permissions. Directory 700, private keys 600
# Check directory permissionsls -ld ~/.ssh
# Check key file permissionsls -l ~/.ssh/id_*drwx------ 2 user user 4096 Feb 28 10:00 /home/user/.ssh-rw------- 1 user user 1234 Feb 28 10:00 /home/user/.ssh/id_ed25519-rw-r--r-- 1 user user 456 Feb 28 10:00 /home/user/.ssh/id_ed25519.pub- Private keys must be readable only by owner
- Use 'chmod 700 ~/.ssh' and 'chmod 600 ~/.ssh/id_*'
Test Remote SSH Server Configuration
Test which authentication methods server allows. Helpful for debugging auth failures
# List available authentication methodsssh -o PreferredAuthentications=none user@host
# Test specific auth methodssh -o PreferredAuthentications=publickey user@hostssh -o PreferredAuthentications=password user@hostPermission denied (publickey).debug1: Authentications that can continue: publickey,password- Shows which methods server supports
- Can isolate auth method issues