SSH (Secure Shell) provides encrypted remote access to servers. It's the primary tool for Linux system administration. SSH key authentication is more secure than passwords and required by most cloud providers.
| Item | Syntax / Value | Description |
|---|---|---|
| ssh | ssh user@host / ssh -p 2222 user@host | Connect to remote host |
| ssh -i | ssh -i ~/.ssh/mykey.pem ubuntu@host | Use specific private key |
| ssh-keygen | ssh-keygen -t ed25519 -C 'alice@example.com' | Generate SSH key pair |
| ssh-keygen rsa | ssh-keygen -t rsa -b 4096 -C 'comment' | Generate RSA key (legacy compatibility) |
| ssh-copy-id | ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host | Copy public key to server |
| authorized_keys | ~/.ssh/authorized_keys | Server-side file of allowed public keys |
| ~/.ssh/config | Host alias with connection settings | Shortcut: 'ssh myserver' instead of 'ssh -i key ubuntu@1.2.3.4' |
| ssh -L | ssh -L 8080:localhost:3000 user@host | Local port forward: localhost:8080 goes to host:3000 |
| ssh -R | ssh -R 9090:localhost:80 user@host | Remote port forward: expose local port on remote |
| ssh -D | ssh -D 1080 user@host | Dynamic SOCKS proxy — route traffic through host |
| ssh -N | ssh -N -L 5432:db:5432 user@jumphost | No command — tunnels only |
| ssh -J | ssh -J jumphost user@target | Jump through bastion/proxy host |
| ssh-agent | eval $(ssh-agent) && ssh-add ~/.ssh/id_ed25519 | Load key into agent — no passphrase prompts |
| StrictHostKeyChecking | StrictHostKeyChecking no # ~/.ssh/config | Skip host key verification (dev only — insecure!) |
| scp | scp file.txt user@host:/remote/path/ | Copy file to remote host |
| scp -r | scp -r ./local-dir/ user@host:/remote/ | Copy directory recursively |
| scp -P | scp -P 2222 file.txt user@host:/path/ | SCP on non-standard port |
| scp from remote | scp user@host:/remote/file.txt ./local/ | Download file from remote |
| sftp | sftp user@host | Interactive SFTP session |
| sftp put | sftp> put localfile remotefile | Upload file in SFTP session |
| sftp get | sftp> get remotefile localfile | Download file in SFTP session |
| sftp mput | sftp> mput *.html | Upload multiple files |
| rsync | rsync -avz ./local/ user@host:/remote/ | Sync files — only transfers changes |
| rsync --delete | rsync -avz --delete ./local/ user@host:/remote/ | Delete files on remote not in local |
| rsync --dry-run | rsync -avz --dry-run ./local/ user@host:/remote/ | Preview changes without syncing |
| rsync -e | rsync -avz -e 'ssh -p 2222' ./local/ user@host:/remote/ | rsync over non-standard SSH port |
| /etc/sshd_config | PermitRootLogin no, PasswordAuthentication no | Server SSH hardening configuration |
# ── SSH Key Setup ─────────────────────────────────────────────
# Generate ED25519 key (preferred — faster and more secure than RSA)
ssh-keygen -t ed25519 -C "alice@mywebuniversity.com" -f ~/.ssh/mwu_ed25519
# Files created: ~/.ssh/mwu_ed25519 (private) and ~/.ssh/mwu_ed25519.pub (public)
# View public key (copy this to server's authorized_keys)
cat ~/.ssh/mwu_ed25519.pub
# Copy public key to server
ssh-copy-id -i ~/.ssh/mwu_ed25519.pub ubuntu@mywebuniversity.com
# Or manually: cat ~/.ssh/mwu_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# ── ~/.ssh/config ─────────────────────────────────────────────
cat > ~/.ssh/config << 'EOF'
Host mwu
HostName mywebuniversity.com
User ubuntu
IdentityFile ~/.ssh/mwu_ed25519
Port 22
ServerAliveInterval 60
ServerAliveCountMax 3
Host mwu-jump
HostName 192.168.1.10
User ubuntu
IdentityFile ~/.ssh/mwu_ed25519
ProxyJump mwu # connect through mwu first
Host *
AddKeysToAgent yes
IdentitiesOnly yes
StrictHostKeyChecking accept-new
EOF
chmod 600 ~/.ssh/config
# Now connect simply:
ssh mwu # instead of: ssh -i ~/.ssh/mwu_ed25519 ubuntu@mywebuniversity.com
ssh mwu-jump # jump through bastion
# ── SSH Tunnels ───────────────────────────────────────────────
# Access remote PostgreSQL on localhost:5432
ssh -L 5432:localhost:5432 mwu -N -f
psql -h localhost -p 5432 -U admin mywebuniversity
# Access remote Redis on localhost:6379
ssh -L 6379:localhost:6379 mwu -N -f
redis-cli -h localhost
# Access remote web server through firewall
ssh -L 8080:localhost:80 mwu -N -f
curl http://localhost:8080/
# ── File Transfer ─────────────────────────────────────────────
# SCP — simple file copy
scp index.html mwu:/var/www/React/prod/
scp -r ./html/ mwu:/var/www/React/prod/
scp mwu:/var/log/apache2/error.log ./error.log # download
# rsync — smart sync (only transfers changes)
rsync -avz --progress ./html/ mwu:/var/www/React/prod/
rsync -avz --delete ./html/ mwu:/var/www/React/prod/ # mirror (deletes remote extras)
rsync -avz --exclude='*.log' --exclude='.git/' ./ mwu:/app/
# ── SSH server hardening /etc/ssh/sshd_config ─────────────────
sudo tee /etc/ssh/sshd_config.d/hardening.conf << 'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers ubuntu deploy
ClientAliveInterval 300
ClientAliveCountMax 2
Protocol 2
EOF
sudo sshd -t # test config
sudo systemctl reload sshd
# ── Python: Paramiko SSH ──────────────────────────────────────
# pip install paramiko
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('mywebuniversity.com', username='ubuntu',
key_filename='/home/user/.ssh/mwu_ed25519')
# Run commands
stdin, stdout, stderr = client.exec_command('df -h / && uptime')
print(stdout.read().decode())
# Upload file
sftp = client.open_sftp()
sftp.put('deploy.sh', '/tmp/deploy.sh')
sftp.close()
client.close()
# python3 ssh_demo.py