ssh-config
SSH Config
SSH key management, configuration, tunneling, and security hardening.
Key Generation
# Ed25519 (recommended — shorter, faster, more secure)
ssh-keygen -t ed25519 -C "your@email.com"
ssh-keygen -t ed25519 -f ~/.ssh/github_key -C "github" # custom filename
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "deploy" -N "" # no passphrase
# RSA 4096 (for legacy systems that don't support Ed25519)
ssh-keygen -t rsa -b 4096 -C "your@email.com"
# Change passphrase on existing key
ssh-keygen -p -f ~/.ssh/id_ed25519
# Show fingerprint / update comment
ssh-keygen -lf ~/.ssh/id_ed25519.pub
ssh-keygen -c -f ~/.ssh/id_ed25519 -C "alice@work-laptop-2024"
Copying Public Keys
# ssh-copy-id (simplest)
ssh-copy-id user@host
ssh-copy-id -i ~/.ssh/mykey.pub user@host
ssh-copy-id -p 2222 user@host
# Manual method (when ssh-copy-id isn't available)
cat ~/.ssh/id_ed25519.pub | ssh user@host 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
# Copy to clipboard (macOS) for GitHub/GitLab web UI
pbcopy < ~/.ssh/id_ed25519.pub
SSH Agent
eval "$(ssh-agent -s)" # start agent
ssh-add ~/.ssh/id_ed25519 # add key
ssh-add -t 43200 ~/.ssh/id_ed25519 # add with 12h timeout
ssh-add -l # list loaded keys
ssh-add -d ~/.ssh/id_ed25519 # remove specific key
ssh-add -D # remove all keys
macOS Keychain Integration
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
ssh-add --apple-use-keychain ~/.ssh/id_ed25519 # persist across reboots
Agent Forwarding
ssh -A user@server # forward local agent to remote host
Host myserver
ForwardAgent yes
Only forward agent to trusted hosts. A compromised host can use your agent to authenticate as you.
SSH Config File (~/.ssh/config)
Basic Host Entries
Host myserver
HostName 192.168.1.100
User admin
Port 22
IdentityFile ~/.ssh/id_ed25519
Host prod
HostName prod.example.com
User deploy
IdentityFile ~/.ssh/deploy_key
IdentitiesOnly yes
IdentitiesOnly yes prevents SSH from trying every key in the agent.
Wildcards and Defaults
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
Host *.example.com
User deploy
IdentityFile ~/.ssh/deploy_key
Host 192.168.1.*
User admin
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Multiple GitHub/GitLab Accounts
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
IdentitiesOnly yes
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
IdentitiesOnly yes
git clone git@github.com-personal:myuser/repo.git
git clone git@github.com-work:company/repo.git
git remote set-url origin git@github.com-work:company/repo.git
Jump Hosts / Bastion Hosts
ProxyJump (OpenSSH 7.3+)
Host bastion
HostName bastion.example.com
User jump
Host internal
HostName 10.0.0.5
User admin
ProxyJump bastion
# Chain: bastion -> middleware -> deep-internal
Host middleware
HostName 10.0.0.10
User app
ProxyJump bastion
Host deep-internal
HostName 172.16.0.5
User admin
ProxyJump middleware
ssh -J jump@bastion.example.com admin@10.0.0.5 # command line
ssh -J jump@bastion1,jump@bastion2 admin@10.0.0.5 # chain multiple
ProxyCommand (Legacy)
Host internal-legacy
HostName 10.0.0.5
User admin
ProxyCommand ssh -W %h:%p bastion
Port Forwarding
Local Forward (-L)
ssh -L 8080:localhost:80 user@server # local:8080 -> remote:80
ssh -L 5432:localhost:5432 user@server # remote PostgreSQL
ssh -L 8080:internal-db.example.com:5432 user@bastion # through bastion to third host
ssh -L 0.0.0.0:8080:localhost:80 user@server # bind all interfaces
Remote Forward (-R)
ssh -R 8080:localhost:3000 user@server # expose local:3000 on remote:8080
Dynamic Forward / SOCKS Proxy (-D)
ssh -D 1080 user@server # SOCKS5 proxy on localhost:1080
ssh -D 1080 -f -N user@server # background SOCKS proxy
Port Forwarding in Config
Host tunnel-db
HostName server.example.com
User admin
LocalForward 5432 localhost:5432
LocalForward 6379 localhost:6379
Host tunnel-web
HostName server.example.com
User admin
LocalForward 8080 localhost:80
DynamicForward 1080
SSH Tunnels
# Background tunnel (-f: background, -N: no remote command)
ssh -f -N -L 8080:localhost:80 user@server
pkill -f "ssh -f -N -L 8080" # kill it
# Persistent tunnel with autossh (auto-reconnects on drop)
autossh -M 0 -f -N -L 8080:localhost:80 user@server # brew/apt install autossh
# Database access through bastion
ssh -f -N -L 5432:db.internal:5432 user@bastion && psql -h localhost -p 5432 -U dbuser mydb
ssh -f -N -L 6379:redis.internal:6379 user@bastion && redis-cli -h localhost
SCP and rsync Over SSH
# SCP
scp file.txt user@host:/path/ # upload
scp user@host:/path/file.txt ./ # download
scp -r folder/ user@host:/path/ # recursive
# rsync (preferred — delta transfer, resume, compression)
rsync -avz folder/ user@host:/path/
rsync -avz --progress folder/ user@host:/path/ # with progress
rsync -avz --delete folder/ user@host:/path/ # mirror (delete extra)
rsync -avzn folder/ user@host:/path/ # dry run
rsync -avz -e "ssh -J jump@bastion" folder/ admin@internal:/path/ # via jump host
Multiplexing (Connection Reuse)
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
mkdir -p ~/.ssh/sockets # create socket directory
# First ssh opens master socket; subsequent connections reuse it (instant, no re-auth)
ssh -O check myserver # check master status
ssh -O exit myserver # close master connection
ControlPersist 600 keeps the socket alive 600s after the last session closes.
SSH Escape Sequences
Press Enter then ~ during an SSH session:
~. Disconnect (kill hung session) ~? List all escapes
~C Open command line (add -L/-R/-D mid-session)
~# List forwarded connections ~~ Send literal ~
Debugging Connection Issues
ssh -v user@host # basic debug
ssh -vvv user@host # maximum verbosity
ssh -T git@github.com # test GitHub connection
ssh -G myserver | grep -i hostname # show resolved config
# Remove stale host key after server reinstall
ssh-keygen -R hostname
ssh-keygen -R "[hostname]:port"
Common errors:
- "Permission denied (publickey)" -- wrong key, key not in agent, or not in authorized_keys
- "Host key verification failed" -- host key changed (server reinstall or MITM)
- "Connection refused" -- sshd not running or wrong port
- "Connection timed out" -- firewall, wrong IP, or host down
SSH Security Hardening
File Permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/config ~/.ssh/authorized_keys
chmod 644 ~/.ssh/id_ed25519.pub
Server Configuration (/etc/ssh/sshd_config)
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
Port 2222
AllowUsers deploy admin
PermitEmptyPasswords no
MaxAuthTries 3
X11Forwarding no
AllowAgentForwarding no
sudo sshd -t # validate config
sudo systemctl restart sshd
fail2ban (Brute-Force Protection)
sudo apt install fail2ban
# /etc/fail2ban/jail.local: [sshd] enabled=true, maxretry=3, bantime=3600, findtime=600
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd # check banned IPs
SSH Certificates vs Keys
ssh-keygen -t ed25519 -f ca_key -C "SSH CA" # create CA
ssh-keygen -s ca_key -I "alice-cert" -n alice -V +52w id_ed25519.pub # sign user key
ssh-keygen -s ca_key -I "web-server" -h -n web.example.com host_key.pub # sign host key
ssh-keygen -Lf id_ed25519-cert.pub # view cert details
Server trusts CA: add TrustedUserCAKeys /etc/ssh/ca_key.pub to sshd_config.
Client trusts host CA: add @cert-authority *.example.com <ca_key.pub contents> to known_hosts.
Certificates eliminate distributing authorized_keys to every server -- sign once, access everywhere the CA is trusted.
More from 1mangesh1/dev-skills-collection
curl-http
HTTP request construction and API testing with curl and HTTPie. Use when user asks to "test API", "make HTTP request", "curl POST", "send request", "test endpoint", "debug API", "upload file", "check response time", "set auth header", "basic auth with curl", "send JSON", "test webhook", "check status code", "follow redirects", "rate limit testing", "measure API latency", "stress test endpoint", "mock API response", or any HTTP calls from the command line.
28database-indexing
Database indexing internals, index type selection, query plan analysis, and write-overhead tradeoffs across PostgreSQL, MySQL, and MongoDB. Use when user asks to "optimize queries", "create indexes", "fix slow queries", "read EXPLAIN output", "reduce query time", "index strategy", "database performance", "composite index", "covering index", "partial index", "index bloat", "unused indexes", or needs help diagnosing and resolving database performance problems.
13secret-scanner
This skill should be used when the user asks to "scan for secrets", "find API keys", "detect credentials", "check for hardcoded passwords", "find leaked tokens", "scan for sensitive keys", "check git history for secrets", "audit repository for credentials", or mentions secret detection, credential scanning, API key exposure, token leakage, password detection, or security key auditing.
10terraform
Terraform infrastructure as code for provisioning, modules, state management, and workspaces. Use when user asks to "create infrastructure", "write Terraform", "manage state", "create module", "import resource", "plan changes", or any IaC tasks.
10dependency-audit
Dependency auditing, updating, and vulnerability management for npm, pip, and other package managers. Use when user asks to "audit dependencies", "update packages", "fix vulnerabilities", "check outdated", "npm audit", "pip audit", "upgrade dependencies safely", or any dependency management tasks.
9pytest
Python testing mastery with pytest, fixtures, parametrize, mocking, and coverage. Use when user asks to "write tests", "add pytest fixtures", "mock a function", "parametrize tests", "run coverage", "debug failing test", "set up conftest", or any Python testing tasks.
8