|$ curl https://forge-ai.dev/api/markdown?path=docs/linux/ssh
$cat docs/ssh-&-remote-access.md
updated Recently·22 min read·published
SSH & Remote Access
Introduction
SSH (Secure Shell) is the standard way to access remote Linux servers, transfer files, and tunnel traffic. Replacing password authentication with SSH keys is one of the highest-impact security improvements you can make.
SSH Keys
ssh-keys.sh
Bash
| 1 | # Generate a key pair |
| 2 | ssh-keygen -t ed25519 -C "alice@example.com" |
| 3 | |
| 4 | # Default locations: |
| 5 | # ~/.ssh/id_ed25519 private key — keep secret |
| 6 | # ~/.ssh/id_ed25519.pub public key — copy to server |
| 7 | |
| 8 | # Copy public key to server |
| 9 | ssh-copy-id alice@server.example.com |
| 10 | |
| 11 | # Or manually append to authorized_keys |
| 12 | cat ~/.ssh/id_ed25519.pub | ssh alice@server.example.com 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys' |
⚠
warning
Never share your private key. Protect it with a passphrase, or store it in an SSH agent.
ssh-agent
ssh-agent.sh
Bash
| 1 | # Start agent and add key |
| 2 | eval "$(ssh-agent -s)" |
| 3 | ssh-add ~/.ssh/id_ed25519 |
| 4 | |
| 5 | # List loaded keys |
| 6 | ssh-add -l |
| 7 | |
| 8 | # macOS keychain (stores passphrase) |
| 9 | ssh-add --apple-use-keychain ~/.ssh/id_ed25519 |
~/.ssh/config
Store connection settings to avoid remembering hostnames, ports, and key paths.
ssh-config.txt
TEXT
| 1 | Host prod |
| 2 | HostName 203.0.113.10 |
| 3 | User alice |
| 4 | IdentityFile ~/.ssh/id_ed25519 |
| 5 | Port 2222 |
| 6 | |
| 7 | Host github.com |
| 8 | User git |
| 9 | IdentityFile ~/.ssh/github_ed25519 |
| 10 | |
| 11 | Host *.internal |
| 12 | User deploy |
| 13 | ProxyJump prod |
ssh-usage.sh
Bash
| 1 | # Connect using alias |
| 2 | ssh prod |
| 3 | |
| 4 | # Copy file using alias |
| 5 | scp app.zip prod:/tmp/ |
| 6 | rsync -avz ./build/ prod:/var/www/app/ |
File Transfer
transfer.sh
Bash
| 1 | # scp — simple copy |
| 2 | scp local-file.txt user@remote:/path/ |
| 3 | scp -r local-dir/ user@remote:/path/ |
| 4 | scp user@remote:/path/file.txt ./ |
| 5 | |
| 6 | # rsync — efficient sync |
| 7 | rsync -avz --delete local-dir/ user@remote:/remote-dir/ |
| 8 | rsync -avz --progress large.iso user@remote:/tmp/ |
ℹ
info
rsync is almost always better than scp for directories because it only transfers changes and can resume interrupted transfers.
Port Forwarding
forwarding.sh
Bash
| 1 | # Local forward: access remote service as if it were local |
| 2 | ssh -L 8080:localhost:3000 prod |
| 3 | # Now http://localhost:8080 reaches port 3000 on prod |
| 4 | |
| 5 | # Remote forward: expose local service on remote machine |
| 6 | ssh -R 9090:localhost:3000 prod |
| 7 | |
| 8 | # Dynamic SOCKS proxy |
| 9 | ssh -D 1080 prod |
SSH Server Security
sshd-config.txt
Bash
| 1 | # Edit /etc/ssh/sshd_config |
| 2 | PermitRootLogin no |
| 3 | PasswordAuthentication no |
| 4 | PubkeyAuthentication yes |
| 5 | Port 2222 # optional, security through obscurity is not enough |
| 6 | AllowUsers alice bob |
⚠
warning
After changing SSH config, test it in a second session before closing your current one: sudo systemctl restart sshd. A mistake can lock you out.