If you manage more than one server, you have probably typed something like this hundreds of times:
ssh -i ~/.ssh/work_key -p 2222 [email protected]
Every single time. The IP, the key, the port, the username. It gets old fast.
The SSH config file (~/.ssh/config) lets you define all of this once and then connect with just:
ssh myserver
This guide shows you how to set it up, with practical examples for every common scenario.
The Config File
The SSH config file lives at ~/.ssh/config. If it does not exist, create it:
touch ~/.ssh/config
chmod 600 ~/.ssh/config
The permissions must be 600 (owner read/write only) or SSH will refuse to use it.
Basic Host Alias
The simplest use case — give a server a short name:
Host myserver
HostName 10.0.0.35
User sam
Now instead of ssh [email protected], just type:
ssh myserver
This also works with scp, rsync, and any tool that uses SSH:
scp file.txt myserver:/tmp/
rsync -avz ./project/ myserver:/opt/project/
Common Options
Host myserver
HostName 10.0.0.35
User sam
Port 2222
IdentityFile ~/.ssh/work_key
IdentitiesOnly yes
ServerAliveInterval 60
ServerAliveCountMax 3
Compression yes
| Option | Purpose |
|---|---|
HostName |
The actual IP or domain |
User |
Username to log in as |
Port |
SSH port (default 22) |
IdentityFile |
Path to private key |
IdentitiesOnly |
Only use the specified key (don't try others) |
ServerAliveInterval |
Send keepalive every N seconds (prevents timeout) |
ServerAliveCountMax |
Disconnect after N missed keepalives |
Compression |
Compress data (useful for slow connections) |
Multiple Servers
Host web
HostName 10.0.0.10
User www-data
Host db
HostName 10.0.0.20
User postgres
Host monitor
HostName 10.0.0.30
User admin
Port 2222
Host vpn
HostName vpn.samnet.dev
User sam
IdentityFile ~/.ssh/vpn_key
Now you have four memorable aliases:
ssh web
ssh db
ssh monitor
ssh vpn
Wildcard and Default Settings
Apply settings to all hosts with Host *:
# Apply to all connections
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yes
# Specific server
Host myserver
HostName 10.0.0.35
User sam
Apply to a group of hosts with patterns:
# All hosts in the 10.0.0.x range
Host 10.0.0.*
User sam
IdentityFile ~/.ssh/homelab_key
# All hosts ending in .prod
Host *.prod
User deploy
IdentityFile ~/.ssh/prod_key
LogLevel ERROR
SSH Key Management
Generate a Key Pair
# Ed25519 (recommended, modern, fast)
ssh-keygen -t ed25519 -C "[email protected]"
# RSA 4096-bit (wider compatibility)
ssh-keygen -t rsa -b 4096 -C "[email protected]"
Different Keys for Different Servers
Host work-*
IdentityFile ~/.ssh/work_ed25519
Host personal-*
IdentityFile ~/.ssh/personal_ed25519
Host github.com
IdentityFile ~/.ssh/github_ed25519
Host gitlab.com
IdentityFile ~/.ssh/gitlab_ed25519
Copy Your Key to a Server
ssh-copy-id -i ~/.ssh/mykey.pub myserver
Or manually:
cat ~/.ssh/mykey.pub | ssh myserver "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Key Permissions
SSH is strict about permissions. If they are wrong, authentication fails silently:
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/id_ed25519 # Private key
chmod 644 ~/.ssh/id_ed25519.pub # Public key
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config
Use our Chmod Calculator to verify the correct permission values.
Jump Hosts (ProxyJump)
When you need to SSH through a bastion/jump host to reach an internal server:
# The bastion host (publicly accessible)
Host bastion
HostName bastion.samnet.dev
User sam
# Internal server (only reachable from bastion)
Host internal-db
HostName 10.0.1.50
User admin
ProxyJump bastion
Now ssh internal-db automatically tunnels through the bastion:
Your laptop → bastion.samnet.dev → 10.0.1.50
Multi-Hop
Chain multiple jump hosts:
Host internal-deep
HostName 172.16.0.100
User root
ProxyJump bastion,middle-server
SSH Tunnels (Port Forwarding)
Local Port Forward
Access a remote service as if it were local:
Host db-tunnel
HostName 10.0.0.20
User admin
LocalForward 5433 localhost:5432
ssh db-tunnel
# Now connect to localhost:5433 to reach the remote PostgreSQL
Dynamic SOCKS Proxy
Route your browser traffic through a remote server:
Host socks-proxy
HostName myserver.com
User sam
DynamicForward 1080
ssh socks-proxy
# Configure browser to use SOCKS5 proxy at localhost:1080
Remote Port Forward
Expose a local service to the remote server:
Host expose-local
HostName myserver.com
User sam
RemoteForward 8080 localhost:3000
This makes your local port 3000 accessible as port 8080 on the remote server.
Security Best Practices
Disable Password Authentication
Once you have key-based auth working, disable passwords on the server:
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
sudo systemctl restart sshd
Change Default Port
Moving SSH off port 22 reduces automated brute-force attempts:
# /etc/ssh/sshd_config
Port 2222
Update your config file:
Host myserver
HostName 10.0.0.35
Port 2222
Use Fail2Ban
Install fail2ban to automatically ban IPs after failed login attempts:
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
Audit Your SSH Access
Check who is logging into your servers:
# Recent logins
last -10
# Failed attempts
journalctl -u sshd | grep "Failed password"
# Currently connected
who
Complete Example Config
Here is a realistic ~/.ssh/config for someone managing a homelab and work servers:
# === Defaults ===
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yes
Compression yes
# === Homelab ===
Host homelab
HostName 10.0.0.35
User sam
IdentityFile ~/.ssh/homelab_ed25519
Host nas
HostName 10.0.0.50
User admin
Port 2222
IdentityFile ~/.ssh/homelab_ed25519
# === Work ===
Host work-bastion
HostName bastion.company.com
User shesami
IdentityFile ~/.ssh/work_ed25519
Host work-web
HostName 10.1.0.10
User deploy
ProxyJump work-bastion
IdentityFile ~/.ssh/work_ed25519
Host work-db
HostName 10.1.0.20
User postgres
ProxyJump work-bastion
LocalForward 5433 localhost:5432
# === Git ===
Host github.com
IdentityFile ~/.ssh/github_ed25519
Host gitlab.com
IdentityFile ~/.ssh/gitlab_ed25519
Related Tools
- Chmod Calculator — get the right permissions for SSH key files
- Port Scanner — check if your SSH port is accessible from outside
- Server Hardening Guide
- chmod Guide
- Cron Job Examples