SSH Commands and Configuration: A Practical Guide
April 3, 2026 · 7 min read
SSH (Secure Shell) is the standard protocol for securely connecting to remote servers. Beyond basic login, SSH supports file transfers, port forwarding, tunnelling, and agent forwarding. This guide covers the commands and config options you will use daily.
Connecting to a Server
ssh user@hostname ssh user@192.168.1.10 ssh user@hostname -p 2222 # custom port ssh -i ~/.ssh/my_key user@hostname # specify key file ssh -v user@hostname # verbose (debug connection issues)
Key Management
Generating a key pair
# ED25519 — modern, fast, recommended ssh-keygen -t ed25519 -C "alice@example.com" # RSA — widely compatible fallback ssh-keygen -t rsa -b 4096 -C "alice@example.com" # Output: ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public)
Copying your public key to a server
ssh-copy-id user@hostname ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname # Manual alternative cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
The SSH agent
eval "$(ssh-agent -s)" # start the agent ssh-add ~/.ssh/id_ed25519 # add your key ssh-add -l # list loaded keys ssh-add -D # remove all keys
Copying Files
scp — simple file copy
# Local to remote scp file.txt user@hostname:/remote/path/ # Remote to local scp user@hostname:/remote/file.txt ./local/ # Copy entire directory scp -r ./my-folder user@hostname:/remote/ # Custom port scp -P 2222 file.txt user@hostname:/path/
rsync — efficient sync
# Sync local dir to remote (only transfers changes) rsync -avz ./src/ user@hostname:/remote/src/ # Flags: -a (archive: preserve permissions/timestamps), -v (verbose), -z (compress) # --delete: remove files on remote that don't exist locally rsync -avz --delete ./src/ user@hostname:/remote/src/ # Dry run first rsync -avzn ./src/ user@hostname:/remote/src/
Port Forwarding (Tunnelling)
Local port forwarding
Makes a remote port accessible on your local machine. Useful for accessing databases or internal services:
# Access remote MySQL (port 3306) as localhost:3307 ssh -L 3307:localhost:3306 user@hostname # Access a service on a third machine (jump host) ssh -L 8080:internal-server:80 user@jump-host # Use it: connect to localhost:3307 in your DB client
Remote port forwarding
Makes a local port accessible on the remote server. Useful for exposing a local dev server:
# Make localhost:3000 accessible as remote:9000 ssh -R 9000:localhost:3000 user@hostname
Dynamic port forwarding (SOCKS proxy)
ssh -D 1080 user@hostname # Configure your browser to use SOCKS5 proxy at localhost:1080
The SSH Config File
Stop typing long commands. Put your connection settings in ~/.ssh/config:
Host myserver
HostName 203.0.113.42
User alice
Port 2222
IdentityFile ~/.ssh/id_ed25519
ForwardAgent yes
Host bastion
HostName bastion.example.com
User ops
Host internal
HostName 10.0.0.5
User ops
ProxyJump bastion # connect via jump hostAfter this, ssh myserver does everything. The ProxyJump directive handles bastion/jump hosts cleanly without needing a multi-step command.
Useful Flags
ssh -N user@host # don't execute a command (tunnel only) ssh -f user@host # run in background ssh -A user@host # forward the SSH agent ssh -X user@host # forward X11 (GUI apps) ssh -T user@host # disable pseudo-terminal (good for scripts) # Run a single command ssh user@hostname "ls -la /var/log" ssh user@hostname "sudo systemctl restart nginx"
Hardening SSH Servers
On servers you manage, edit /etc/ssh/sshd_config and restart the service:
PermitRootLogin no # never log in as root PasswordAuthentication no # keys only PubkeyAuthentication yes Port 2222 # non-default port (minor obscurity) AllowUsers alice bob # whitelist MaxAuthTries 3 LoginGraceTime 20
After changing sshd_config, always test with sshd -t before restarting — a syntax error in the config file will lock you out. Keep a second terminal session open until you confirm the new session works.