# Connect to remote host
ssh user@hostname
ssh user@192.168.1.100
# Connect on specific port
ssh -p 2222 user@hostname
# Connect with specific identity file
ssh -i ~/.ssh/my_key user@hostname
# Connect with verbose output (debugging)
ssh -v user@hostname
ssh -vv user@hostname # More verbose
ssh -vvv user@hostname # Maximum verbosity
# Generate SSH key pair (Ed25519 - recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"
# Generate RSA key (4096 bits)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# Generate key with specific filename
ssh-keygen -t ed25519 -f ~/.ssh/my_custom_key
# Copy public key to remote server
ssh-copy-id user@hostname
ssh-copy-id -i ~/.ssh/my_key.pub user@hostname
# Copy key manually
cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# Change passphrase on existing key
ssh-keygen -p -f ~/.ssh/id_ed25519
# View key fingerprint
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# Remove host from known_hosts
ssh-keygen -R hostname
# Start SSH agent
eval "$(ssh-agent -s)"
# Add key to agent
ssh-add ~/.ssh/id_ed25519
# Add key with specific lifetime (seconds)
ssh-add -t 3600 ~/.ssh/id_ed25519
# List keys in agent
ssh-add -l
# Remove all keys from agent
ssh-add -D
# Remove specific key
ssh-add -d ~/.ssh/id_ed25519
# Copy file to remote
scp file.txt user@hostname:/path/to/destination/
# Copy file from remote
scp user@hostname:/path/to/file.txt ./local/
# Copy directory recursively
scp -r ./local_dir user@hostname:/remote/path/
# Copy with specific port
scp -P 2222 file.txt user@hostname:/path/
# Copy with specific key
scp -i ~/.ssh/my_key file.txt user@hostname:/path/
# Preserve file attributes
scp -p file.txt user@hostname:/path/
# Start SFTP session
sftp user@hostname
# SFTP with specific port
sftp -P 2222 user@hostname
# Common SFTP commands
# ls - List remote directory
# lls - List local directory
# cd path - Change remote directory
# lcd path - Change local directory
# get file - Download file
# put file - Upload file
# mget *.txt - Download multiple files
# mput *.txt - Upload multiple files
# mkdir dir - Create remote directory
# rm file - Delete remote file
# exit - Close session
# Local port forwarding (access remote service locally)
# Forward local:8080 to remote:80
ssh -L 8080:localhost:80 user@hostname
# Forward to a third host through SSH server
ssh -L 8080:internal.server:80 user@gateway
# Remote port forwarding (expose local service remotely)
# Forward remote:8080 to local:3000
ssh -R 8080:localhost:3000 user@hostname
# Dynamic port forwarding (SOCKS proxy)
ssh -D 9090 user@hostname
# Keep tunnel open without shell
ssh -N -L 8080:localhost:80 user@hostname
# Run in background
ssh -f -N -L 8080:localhost:80 user@hostname
# Connect through jump host
ssh -J jumpuser@jumphost user@destination
# Multiple jump hosts
ssh -J user1@host1,user2@host2 user@destination
# Using ProxyJump in config (preferred)
# See SSH Config section below
# Legacy ProxyCommand method
ssh -o ProxyCommand="ssh -W %h:%p jumpuser@jumphost" user@destination
# Execute single command
ssh user@hostname "ls -la"
# Execute multiple commands
ssh user@hostname "cd /var/log && tail -100 syslog"
# Run command with sudo
ssh user@hostname "sudo systemctl restart nginx"
# Run local script on remote
ssh user@hostname 'bash -s' < local_script.sh
# Run command in background
ssh user@hostname "nohup ./long_running.sh &"
# Location: ~/.ssh/config
# Basic host configuration
Host myserver
HostName 192.168.1.100
User admin
Port 22
IdentityFile ~/.ssh/my_key
# Jump host configuration
Host internal
HostName 10.0.0.5
User developer
ProxyJump bastion
Host bastion
HostName bastion.example.com
User jumpuser
IdentityFile ~/.ssh/bastion_key
# Wildcard configuration
Host *.example.com
User deploy
IdentityFile ~/.ssh/deploy_key
# Keep connections alive
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
# Multiplexing (reuse connections)
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
# Access remote MySQL locally
ssh -L 3306:localhost:3306 user@dbserver
# Access remote web app
ssh -L 8080:localhost:80 user@webserver
# Access internal service through bastion
ssh -L 5432:internal-db:5432 user@bastion
# Create SOCKS proxy for browsing
ssh -D 8080 -f -C -q -N user@hostname
# Reverse tunnel (expose local dev server)
ssh -R 80:localhost:3000 user@public-server
# Disable password authentication (in /etc/ssh/sshd_config)
# PasswordAuthentication no
# Disable root login
# PermitRootLogin no
# Use specific allowed users
# AllowUsers admin deploy
# Change default port
# Port 2222
# Set proper permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/authorized_keys
# Test SSH config syntax
sshd -t
# Debug connection issues
ssh -vvv user@hostname
# Check SSH service status
systemctl status sshd
# View SSH logs
sudo tail -f /var/log/auth.log # Debian/Ubuntu
sudo tail -f /var/log/secure # RHEL/CentOS
# Test connection without logging in
ssh -o BatchMode=yes -o ConnectTimeout=5 user@hostname echo ok
# Check open SSH connections
ss -tnp | grep ssh
netstat -tnp | grep ssh
# Kill stuck SSH session
# Press: ~. (tilde, then period)
| Option | Description |
|---|
-p | Specify port number |
-i | Identity file (private key) |
-l | Login name |
-v | Verbose mode (use -vv or -vvv for more) |
-q | Quiet mode |
-N | No remote command (for tunnels) |
-f | Go to background |
-L | Local port forwarding |
-R | Remote port forwarding |
-D | Dynamic port forwarding (SOCKS) |
-J | Jump host |
-X | Enable X11 forwarding |
-Y | Trusted X11 forwarding |
-C | Enable compression |
-A | Agent forwarding |
-t | Force pseudo-terminal allocation |
-o | Specify config option |