SSH Client Configuration¶
Configuration Files¶
SSH client reads configuration from multiple sources in order:
- Command-line options (
-o Option=value) - User config (
~/.ssh/config) - System config (
/etc/ssh/ssh_config)
First match wins - put specific hosts before wildcards.
~/.ssh/config Structure¶
# Global defaults (apply to all hosts)
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
# Specific host
Host myserver
HostName 192.168.1.100
User admin
Port 22
IdentityFile ~/.ssh/server_key
# Pattern matching
Host *.example.com
User deploy
IdentityFile ~/.ssh/deploy_key
# Alias for complex connection
Host jump
HostName bastion.example.com
User jumpuser
IdentityFile ~/.ssh/jump_key
Basic Options¶
Connection Settings¶
Host server
# Required
HostName server.example.com # IP or hostname
User username # Login user
# Optional
Port 22 # SSH port (default: 22)
AddressFamily inet # inet (IPv4), inet6 (IPv6), any
BindAddress 192.168.1.50 # Source IP to use
ConnectTimeout 10 # Connection timeout in seconds
Authentication¶
Host server
# Key-based
IdentityFile ~/.ssh/server_key
IdentitiesOnly yes # Only use specified key
# Password (if needed)
PreferredAuthentications publickey,keyboard-interactive,password
# Batch mode (no prompts)
BatchMode yes
Keep-Alive¶
Host *
# Client sends keep-alive every 60 seconds
ServerAliveInterval 60
# Disconnect after 3 missed responses
ServerAliveCountMax 3
# TCP keep-alive (different from ServerAlive)
TCPKeepAlive yes
Host Aliases¶
Simple Alias¶
Use: ssh web
Multiple Aliases¶
Use: ssh web or ssh webserver or ssh prod
Pattern Matching¶
# Wildcard
Host *.dev.example.com
User developer
IdentityFile ~/.ssh/dev_key
# Negation
Host * !*.internal
ProxyJump bastion
# Character class
Host server[0-9]
User admin
Common Configurations¶
Development Server¶
Host dev
HostName dev.example.com
User developer
IdentityFile ~/.ssh/dev_key
ForwardAgent yes
LocalForward 3000 localhost:3000
LocalForward 5432 localhost:5432
Production Server (Restricted)¶
Host prod
HostName prod.example.com
User deploy
IdentityFile ~/.ssh/prod_key
IdentitiesOnly yes
ForwardAgent no
ForwardX11 no
RequestTTY no
Jump Host / Bastion¶
Host bastion
HostName bastion.example.com
User jump
IdentityFile ~/.ssh/bastion_key
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
Host internal-*
ProxyJump bastion
User admin
IdentityFile ~/.ssh/internal_key
Host internal-web
HostName 10.0.0.10
Host internal-db
HostName 10.0.0.20
Use: ssh internal-web (automatically jumps through bastion)
GitHub/GitLab¶
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
IdentitiesOnly yes
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_key
AWS EC2¶
Host aws-*
User ec2-user
IdentityFile ~/.ssh/aws_key.pem
StrictHostKeyChecking accept-new
Host aws-web
HostName ec2-xx-xx-xx-xx.compute.amazonaws.com
Host aws-db
HostName ec2-yy-yy-yy-yy.compute.amazonaws.com
Advanced Options¶
Agent Forwarding¶
Security
Only enable on trusted servers. A compromised server could use your forwarded agent.
X11 Forwarding¶
Compression¶
Connection Multiplexing¶
Create socket directory:
Escape Characters¶
Escape sequences (press Enter first): - ~. - Disconnect - ~^Z - Suspend - ~# - List forwarded connections - ~~ - Send literal ~
Host Key Verification¶
# Strict (default, recommended)
Host *
StrictHostKeyChecking ask
# Auto-accept new hosts (convenient but less secure)
Host trusted-network-*
StrictHostKeyChecking accept-new
# Skip verification (dangerous!)
Host test-vm
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Port Forwarding in Config¶
Local Forward¶
Host dbserver
HostName db.example.com
# Access remote MySQL on local port
LocalForward 3306 localhost:3306
# Access remote web on local port
LocalForward 8080 localhost:80
Remote Forward¶
Host expose-local
HostName server.example.com
# Expose local service on remote
RemoteForward 8080 localhost:3000
Dynamic (SOCKS)¶
Environment¶
Send Environment Variables¶
Server must allow with AcceptEnv.
Set Environment¶
Includes¶
Include Other Config Files¶
# ~/.ssh/config
# Include all configs in directory
Include config.d/*
# Include specific file
Include work_config
# Conditional include
Match host *.work.com
Include work_settings
Organized Config Structure¶
~/.ssh/
├── config # Main config with includes
├── config.d/
│ ├── personal # Personal servers
│ ├── work # Work servers
│ └── cloud # Cloud providers
└── keys/
├── personal_ed25519
├── work_ed25519
└── aws.pem
Complete Example¶
# ~/.ssh/config
# ============================================
# Global Defaults
# ============================================
Host *
# Security
IdentitiesOnly yes
HashKnownHosts yes
# Performance
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
Compression yes
# Keep-alive
ServerAliveInterval 60
ServerAliveCountMax 3
# Convenience
AddKeysToAgent yes
# ============================================
# Personal
# ============================================
Host home
HostName home.example.com
User me
IdentityFile ~/.ssh/personal_ed25519
Port 2222
Host pi
HostName 192.168.1.50
User pi
IdentityFile ~/.ssh/personal_ed25519
# ============================================
# Work
# ============================================
Host work-bastion
HostName bastion.work.com
User admin
IdentityFile ~/.ssh/work_ed25519
Host work-*
ProxyJump work-bastion
User deploy
IdentityFile ~/.ssh/work_ed25519
Host work-web
HostName 10.0.1.10
Host work-api
HostName 10.0.1.20
Host work-db
HostName 10.0.1.30
LocalForward 5432 localhost:5432
# ============================================
# Cloud
# ============================================
Host aws-*
User ec2-user
IdentityFile ~/.ssh/aws.pem
StrictHostKeyChecking accept-new
Host gcp-*
User admin
IdentityFile ~/.ssh/gcp_ed25519
# ============================================
# Git
# ============================================
Host github.com
User git
IdentityFile ~/.ssh/github_ed25519
Host gitlab.com
User git
IdentityFile ~/.ssh/gitlab_ed25519
Debugging Configuration¶
Test Config Parsing¶
Shows resolved configuration for hostname.