Quick Answer: Connect:
ssh user@host. Copy file to server:scp file.txt user@host:/path/. Generate key:ssh-keygen -t ed25519. SOCKS proxy:ssh -D 1080 user@host. Port forward:ssh -L 8080:localhost:80 user@host.
Need a VPS? Vultr (free credit), DigitalOcean ($200 free credit), or RackNerd (cheap annual deals).
Basic Connection
# Connect to server
ssh user@hostname
# Connect on a different port
ssh -p 2222 user@hostname
# Connect with a specific key
ssh -i ~/.ssh/mykey user@hostname
# Connect with verbose output (for debugging)
ssh -v user@hostname
ssh -vv user@hostname # More verbose
ssh -vvv user@hostname # Maximum verbosity
# Run a single command on the remote server
ssh user@hostname "uptime"
ssh user@hostname "df -h && free -m"
# Connect and allocate a pseudo-terminal (for interactive commands)
ssh -t user@hostname "top"
SSH Keys
Generate a Key Pair
# Ed25519 (recommended — fastest, most secure)
ssh-keygen -t ed25519
# Ed25519 with a comment (label)
ssh-keygen -t ed25519 -C "sam@workstation"
# RSA 4096-bit (for older systems that don't support Ed25519)
ssh-keygen -t rsa -b 4096
# Generate key with a specific filename
ssh-keygen -t ed25519 -f ~/.ssh/myserver_key
Copy Key to Server
# Automatic method (recommended)
ssh-copy-id user@hostname
# Copy a specific key
ssh-copy-id -i ~/.ssh/mykey.pub user@hostname
# Copy to a server on a different port
ssh-copy-id -p 2222 user@hostname
# Manual method (if ssh-copy-id is not available)
cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Key Management
# List fingerprints of your keys
ssh-keygen -l -f ~/.ssh/id_ed25519
# Change passphrase on existing key
ssh-keygen -p -f ~/.ssh/id_ed25519
# Show public key
cat ~/.ssh/id_ed25519.pub
# Remove a host from known_hosts (after server reinstall)
ssh-keygen -R hostname
SSH Agent
# Start the agent
eval "$(ssh-agent -s)"
# Add default key
ssh-add
# Add a specific key
ssh-add ~/.ssh/mykey
# List loaded keys
ssh-add -l
# Remove all keys from agent
ssh-add -D
# Add key with expiration (seconds)
ssh-add -t 3600 ~/.ssh/mykey # 1 hour
Agent Forwarding
# Forward your SSH agent to the remote server
# (lets you SSH from server A to server B using your local keys)
ssh -A user@hostname
File Transfer
SCP (Secure Copy)
# Copy file to server
scp file.txt user@host:/remote/path/
# Copy file from server
scp user@host:/remote/file.txt ./local/path/
# Copy directory recursively
scp -r ./local_dir user@host:/remote/path/
# Copy with a specific port
scp -P 2222 file.txt user@host:/path/
# Copy with a specific key
scp -i ~/.ssh/mykey file.txt user@host:/path/
# Copy between two remote servers
scp user@host1:/file.txt user@host2:/path/
# Preserve file attributes (timestamps, permissions)
scp -p file.txt user@host:/path/
SFTP (Interactive)
# Start SFTP session
sftp user@hostname
# SFTP commands:
ls # List remote files
lls # List local files
cd /remote/path # Change remote directory
lcd /local/path # Change local directory
get remote_file # Download file
put local_file # Upload file
get -r remote_dir # Download directory
put -r local_dir # Upload directory
rm file # Delete remote file
mkdir dirname # Create remote directory
exit # Quit
Rsync over SSH
# Sync directory to server
rsync -avz ./local/ user@host:/remote/
# Sync from server to local
rsync -avz user@host:/remote/ ./local/
# Sync with custom SSH port
rsync -avz -e "ssh -p 2222" ./local/ user@host:/remote/
# Dry run (see what would change)
rsync -avzn ./local/ user@host:/remote/
# Delete files on destination that don't exist on source
rsync -avz --delete ./local/ user@host:/remote/
# Exclude files
rsync -avz --exclude="*.log" --exclude=".git" ./local/ user@host:/remote/
Port Forwarding (Tunneling)
Local Port Forwarding
# Forward local port 8080 to remote server's port 80
ssh -L 8080:localhost:80 user@host
# Now visit http://localhost:8080 to access the remote server's port 80
# Forward to a service behind the remote server
ssh -L 5432:db-server:5432 user@jump-host
# Connects local port 5432 to db-server:5432 through jump-host
# Run in background (no shell)
ssh -L 8080:localhost:80 -N -f user@host
Remote Port Forwarding
# Expose your local port 3000 on the remote server's port 9000
ssh -R 9000:localhost:3000 user@host
# Anyone accessing host:9000 reaches your local port 3000
Dynamic Port Forwarding (SOCKS Proxy)
# Create a SOCKS5 proxy on local port 1080
ssh -D 1080 user@host
# Run in background
ssh -D 1080 -N -f user@host
# Then configure your browser to use SOCKS5 proxy: localhost:1080
Guide: SOCKS5 Proxy Setup
SSH Config File
Create ~/.ssh/config to save connection settings:
# Default settings for all hosts
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
# Named server
Host myserver
HostName 203.0.113.50
User sam
Port 2222
IdentityFile ~/.ssh/myserver_key
# Jump host (bastion)
Host internal-server
HostName 10.0.0.5
User admin
ProxyJump jump-host
# Short alias
Host prod
HostName production.example.com
User deploy
IdentityFile ~/.ssh/deploy_key
LocalForward 5432 localhost:5432
Now you can just type:
ssh myserver # Instead of: ssh -p 2222 -i ~/.ssh/myserver_key [email protected]
ssh prod # Instead of the long command
scp file.txt myserver:/path/ # Works with scp too
Full guide: SSH Config Guide
Jump Hosts (Bastion)
# SSH through a jump host
ssh -J jump-host user@internal-server
# Multiple jump hosts
ssh -J jump1,jump2 user@final-server
# In config file
Host internal
HostName 10.0.0.5
User admin
ProxyJump bastion
Host bastion
HostName bastion.example.com
User sam
Multiplexing (Reuse Connections)
Add to ~/.ssh/config:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
# Create the sockets directory
mkdir -p ~/.ssh/sockets
First connection to a host opens a socket. Subsequent connections reuse it — instant login, no re-authentication.
Escape Sequences
While in an SSH session, press Enter then:
| Sequence | Action |
|---|---|
~. |
Disconnect (kill hung session) |
~^Z |
Suspend SSH (background it) |
~# |
List forwarded connections |
~& |
Background SSH (when waiting for connections to close) |
~? |
Show escape help |
Most useful: ~. to kill a frozen SSH session.
Security Hardening
# Disable password auth (key-only)
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
# Disable root login
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
# Change SSH port
sudo sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
# Restart SSH to apply
sudo systemctl restart sshd
Always verify changes took effect (sed silently fails if the pattern does not match):
grep PasswordAuthentication /etc/ssh/sshd_config
grep PermitRootLogin /etc/ssh/sshd_config
Before disabling password auth, make sure your key works:
ssh -i ~/.ssh/mykey user@host
# If this works, safe to disable passwords
Full guide: SSH Hardening
Troubleshooting
# Debug connection issues
ssh -vvv user@host
# Check SSH service status
sudo systemctl status sshd
# Check SSH config for errors
sudo sshd -t
# View SSH logs
sudo journalctl -u sshd -f
# Check file permissions (must be correct!)
ls -la ~/.ssh/
# Should be:
# ~/.ssh/ → 700 (drwx------)
# ~/.ssh/id_ed25519 → 600 (-rw-------)
# ~/.ssh/id_ed25519.pub → 644 (-rw-r--r--)
# ~/.ssh/authorized_keys → 600 (-rw-------)
# ~/.ssh/config → 600 (-rw-------)
# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys ~/.ssh/config
chmod 644 ~/.ssh/id_ed25519.pub
| Problem | Fix |
|---|---|
| Permission denied (publickey) | Check key permissions (600), check authorized_keys on server |
| Connection refused | SSH service not running or wrong port |
| Connection timed out | Firewall blocking, wrong IP, or server down |
| Host key verification failed | Server was reinstalled. Run ssh-keygen -R hostname |
| Too many authentication failures | Specify key: ssh -i ~/.ssh/key user@host |
Quick Reference
| Command | What It Does |
|---|---|
ssh user@host |
Connect |
ssh -p 2222 user@host |
Connect on port 2222 |
ssh -i key user@host |
Connect with specific key |
ssh-keygen -t ed25519 |
Generate key pair |
ssh-copy-id user@host |
Copy key to server |
scp file user@host:/path/ |
Copy file to server |
scp user@host:/file ./ |
Copy file from server |
ssh -L 8080:localhost:80 user@host |
Local port forward |
ssh -R 9000:localhost:3000 user@host |
Remote port forward |
ssh -D 1080 user@host |
SOCKS proxy |
ssh -J jump user@internal |
Jump through bastion |
ssh -A user@host |
Agent forwarding |
ssh -N -f user@host |
Background (no shell) |
Related Guides
- SSH Keys Setup — detailed key setup walkthrough
- SSH Config Guide — master the config file
- How to Secure SSH — hardening guide
- Complete SSH Guide — everything about SSH
- SOCKS5 Proxy Setup — SSH tunneling for proxy
- Fail2ban Setup — protect against brute force
- Server Hardening Guide — full security checklist