SSH Config and Tricks
~/.ssh/config (or /etc/ssh/ssh_config) is the most powerful SSH file most people barely use. It lets you define aliases, proxy jumps, identity files, and connection options per-host — once set up, everything is ssh myserver instead of remembering -i ~/.ssh/key -p 2222 user@host.
Basic Config
# ~/.ssh/config
Host myserver
HostName 192.168.1.100
User darshan
Port 22
IdentityFile ~/.ssh/id_ed25519
Host web
HostName web.example.com
User ubuntu
Port 2222
IdentityFile ~/.ssh/prod_key
StrictHostKeyChecking no # don't prompt on first connect
UserKnownHostsFile /dev/nullThen just ssh web instead of ssh -p 2222 -i ~/.ssh/prod_key ubuntu@web.example.com.
ProxyJump (Jump Host)
Access a server that isn’t directly reachable from your machine — go through a jump/bastion host:
# Manual:
ssh -J bastion.example.com internal-server.local
# Config:
Host internal-server
HostName 192.168.1.50
User ubuntu
ProxyJump bastion.example.com
Host bastion
HostName bastion.example.com
User darshan
Port 2222Now ssh internal-server automatically proxies through bastion. Works with -W (netcat mode) or ProxyJump -J.
ProxyCommand
For older servers without ProxyJump support, use netcat mode:
Host internal-server
HostName 192.168.1.50
User ubuntu
ProxyCommand ssh -q bastion.example.com nc %h %p
# nc = netcat, %h = target host, %p = target port
# -q suppresses warningsFor ProxyJump-capable OpenSSH 7.3+, just use ProxyJump.
ControlMaster (Multiplexing)
Reuse a single SSH connection for multiple sessions to the same host — no new authentication for subsequent connections:
Host *
# Master connection lives here:
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlMaster auto
ControlPersist 10m # keep master alive 10min after last session closes
# Create sockets directory:
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/socketsNow your first ssh web opens the master connection. Second ssh web in another terminal reuses it — instant, no auth.
Host Patterns
# Wildcards
Host *.internal
User admin
ProxyJump jump.internal
Host 10.0.0.*
User ubuntu
StrictHostKeyChecking no
Host dev-* prod-*
User deploy
IdentityFile ~/.ssh/deploy_key
# Negation
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Host !bastion * # apply to all except bastion
ServerAliveInterval 30Authentication and Keys
# Add key to agent on first use:
AddKeysToAgent yes
# Specific key per host:
Host gitlab
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_ed25519
Host github
HostName github.com
User git
IdentityFile ~/.ssh/github_ed25519
IdentitiesOnly yes # only use this key, not ssh-agent keys
# Key forwarding (ssh-agent):
Host target-server
HostName 192.168.1.50
ForwardAgent yes # forward your ssh-agent to this server
# Now your agent is available on target-server for git push, etc.Connection Options
Host remote-server
HostName remote.example.com
User darshan
# Don't disconnect after inactivity:
ServerAliveInterval 60 # send keepalive every 60s
ServerAliveCountMax 3 # disconnect after 3 failed keepalives
# Connection multiplexing keeps the connection alive:
ControlMaster auto
ControlPersist 10m
# Reconnect automatically:
ConnectionAttempts 3
# TCP forwarding:
LocalForward 8080 localhost:80 # forward local 8080 to remote's port 80
RemoteForward 2222 localhost:22 # forward remote's 2222 to your local SSH
# Use a different IP/hostname for the local part:
HostName %h
LocalForward 127.0.0.1:8080 127.0.0.1:80Match Blocks
Match blocks apply settings conditionally — by user, host, or address:
Host myserver
HostName 192.168.1.100
User darshan
# Apply to all hosts, but only when connecting as root:
Match User root
IdentityFile ~/.ssh/root_key
AllowAgentForwarding no # don't allow agent forward as root
# Match by host:
Match Host "10.0.*"
StrictHostKeyChecking accept-new
Match Host "192.168.*"
User admin
# Match by address:
Match LocalAddress 192.168.1.*
Gateway yes
# Match all:
Match all
ForwardAgent noPort Forwarding
# Local forward: local port → remote target
Host app
HostName app.example.com
LocalForward 8080 localhost:8080 # access app's port 8080 via localhost:8080
LocalForward 5432 localhost:5432 # local postgresql client
# Dynamic forward (SOCKS proxy):
Host vpn
HostName jump.example.com
DynamicForward 1080 # SOCKS proxy on localhost:1080
# Then: curl --socks5 localhost:1080 https://example.com
# Remote forward: remote port → local target
Host home
HostName home.example.com
RemoteForward 2222 localhost:22 # from home, ssh to :2222 → your local SSHUseful Global Options
# /etc/ssh/ssh_config or ~/.ssh/config
# Global defaults:
Host *
# Security:
StrictHostKeyChecking ask
UserKnownHostsFile ~/.ssh/known_hosts
# Performance:
Compression yes # compress data (slow links)
TCPKeepAlive yes # detect dead connections
ServerAliveInterval 120
# Security (modern cipher suites):
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,ecdh-sha2-nistp521Known Hosts Management
# Remove a known host (when server IP changes or rebuild):
ssh-keygen -R hostname
ssh-keygen -R 192.168.1.100
ssh-keygen -R "[server]:2222"
# Add without prompt:
ssh-keyscan -H hostname >> ~/.ssh/known_hosts
ssh-keyscan -H -p 2222 hostname >> ~/.ssh/known_hosts
# Show fingerprint:
ssh-keygen -lf ~/.ssh/known_hosts
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# Hash a hostname (obfuscate known_hosts):
ssh-keygen -H -f ~/.ssh/known_hostsSSH Over Proxy
# Through HTTP proxy:
Host external
HostName server.com
ProxyCommand connect -H proxy.company.com:8080 %h %p
# Through SOCKS5:
Host external
HostName server.com
ProxyCommand connect -S proxy.company.com:1080 %h %p
# connect tool: apt install connect-proxyQuick Reference
# ~/.ssh/config key options:
Host # hostname alias
HostName # actual hostname/IP
User # username
Port # port
IdentityFile # key file
ProxyJump # jump host (-J)
ProxyCommand # custom connection command
LocalForward # local port forward
RemoteForward # remote port forward
DynamicForward # SOCKS proxy
ServerAliveInterval # keepalive seconds
ServerAliveCountMax # max missed keepalives
ControlMaster # connection sharing
ControlPath # socket path for multiplexing
ControlPersist # master connection lifetime
ForwardAgent # forward ssh-agent
StrictHostKeyChecking # yes/ask/no
UserKnownHostsFile # known_hosts path
AddKeysToAgent # add key to agent on use
IdentitiesOnly # only use specified identity
Match # conditional settings