MeshWorld India LogoMeshWorld.

SSH Config & Aliases: The Developer's Connection Kit

Listen to ArticleAI Speech
~8 min read narration
100%
SSH Config & Aliases: The Developer's Connection Kit

Typing ssh -i ~/.ssh/prod_key -p 2222 -J bastion.example.com admin@webserver.internal.corp gets old fast. SSH config files turn that mess into ssh prod-web. This guide shows you how to automate connections, manage keys, forward ports, and secure your remote access.

The SSH Config File

Your SSH config lives at ~/.ssh/config. Create it if it doesn’t exist:

BASH
touch ~/.ssh/config
chmod 600 ~/.ssh/config  # Required permissions

Basic Structure

PLAINTEXT
# Global settings (apply to all hosts)
Host *
    User defaultuser
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60

# Specific host alias
Host myserver
    HostName 192.168.1.100
    User ubuntu
    Port 22
    IdentityFile ~/.ssh/myserver_key

Now instead of:

BASH
ssh -i ~/.ssh/myserver_key ubuntu@192.168.1.100

Just type:

BASH
ssh myserver

Essential Config Options

Connection Basics

OptionDescriptionExample
HostNameActual server addressserver.example.com or 192.168.1.1
UserLogin usernameubuntu, root, deploy
PortSSH port (default 22)2222, 443
IdentityFilePrivate key path~/.ssh/id_ed25519
IdentitiesOnlyUse only specified keyyes (prevents SSH agent offering wrong keys)

Connection Persistence

PLAINTEXT
Host *
    # Keep connections alive
    ServerAliveInterval 60
    ServerAliveCountMax 3
    
    # Reuse connections (much faster)
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 4h

Create the socket directory:

BASH
mkdir -p ~/.ssh/sockets

Security Hardening

PLAINTEXT
Host *
    # Only use strong algorithms
    HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
    
    # Disable password auth (keys only)
    PasswordAuthentication no
    
    # Verify host keys strictly
    StrictHostKeyChecking accept-new
    
    # Hash known_hosts for privacy
    HashKnownHosts yes

Real-World Examples

Development Server

PLAINTEXT
Host dev
    HostName dev.example.com
    User developer
    Port 22
    IdentityFile ~/.ssh/dev_key
    LocalForward 3000 localhost:3000  # Forward dev server
    LocalForward 8080 localhost:8080  # Forward API

Usage:

BASH
ssh dev
# Access http://localhost:3000 on your machine
# Connects to dev server at localhost:3000

Production Server (Restricted)

PLAINTEXT
Host prod
    HostName prod.example.com
    User deploy
    Port 2222
    IdentityFile ~/.ssh/prod_key
    IdentitiesOnly yes
    ServerAliveInterval 30
    
    # Restrict what can be done
    PermitLocalCommand no

Multiple Servers with Patterns

PLAINTEXT
# Match all staging servers
Host staging-*
    HostName %h.staging.internal
    User deploy
    IdentityFile ~/.ssh/staging_key
    
# Match all production servers
Host prod-*
    HostName %h.prod.internal
    User deploy
    IdentityFile ~/.ssh/prod_key
    IdentitiesOnly yes

Usage:

BASH
ssh staging-web1    # Connects to staging-web1.staging.internal
ssh prod-api2       # Connects to prod-api2.prod.internal

Jump Hosts (Bastion)

PLAINTEXT
Host bastion
    HostName bastion.example.com
    User admin
    IdentityFile ~/.ssh/bastion_key

Host internal-*
    HostName %h.internal.corp
    User ubuntu
    IdentityFile ~/.ssh/internal_key
    ProxyJump bastion
    # Or: ProxyJump admin@bastion.example.com

Usage:

BASH
ssh internal-webserver  # Automatically hops through bastion

Method 2: ProxyCommand (Legacy)

PLAINTEXT
Host internal-server
    HostName 10.0.0.5
    User ubuntu
    IdentityFile ~/.ssh/internal_key
    ProxyCommand ssh bastion -W %h:%p

Multiple Jump Hosts

PLAINTEXT
Host secure-internal
    HostName secure-server.internal
    User admin
    ProxyJump bastion1,bastion2  # Chain through both

Port Forwarding

Local Forward (Local → Remote)

Access remote services as if they’re local:

PLAINTEXT
Host db-server
    HostName db.internal.com
    User admin
    LocalForward 5433 localhost:5432  # Local 5433 → Remote 5432

Usage:

BASH
ssh db-server
# In another terminal:
psql -h localhost -p 5433 -U postgres  # Connects to remote DB

Remote Forward (Remote → Local)

Let remote server access your local services:

PLAINTEXT
Host dev-server
    HostName dev.remote.com
    User developer
    RemoteForward 8080 localhost:3000  # Remote 8080 → Your local 3000

Usage:

BASH
ssh dev-server
# Colleagues can access your local dev server at dev.remote.com:8080

Dynamic Forward (SOCKS Proxy)

PLAINTEXT
Host proxy
    HostName jump-server.com
    User admin
    DynamicForward 1080  # Creates SOCKS proxy on port 1080

Usage:

BASH
ssh proxy
# Configure browser to use SOCKS5://localhost:1080
# All traffic routes through jump-server

SSH Key Management

Generating Keys

BASH
# Modern, secure, compact
ssh-keygen -t ed25519 -C "your@email.com" -f ~/.ssh/id_ed25519

# For legacy systems (RSA)
ssh-keygen -t rsa -b 4096 -C "your@email.com" -f ~/.ssh/id_rsa

# For specific services
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_key
ssh-keygen -t ed25519 -C "work-server" -f ~/.ssh/work_key

SSH Agent

BASH
# Start agent
eval "$(ssh-agent -s)"

# Add keys
ssh-add ~/.ssh/id_ed25519
ssh-add ~/.ssh/work_key

# List loaded keys
ssh-add -l

# Remove specific key
ssh-add -d ~/.ssh/work_key

# Clear all keys
ssh-add -D

Config with Multiple Keys

PLAINTEXT
# GitHub
Host github.com
    User git
    IdentityFile ~/.ssh/github_key
    IdentitiesOnly yes

# GitLab
Host gitlab.com
    User git
    IdentityFile ~/.ssh/gitlab_key
    IdentitiesOnly yes

# Work servers
Host *.work.com
    User developer
    IdentityFile ~/.ssh/work_key
    IdentitiesOnly yes

Advanced Configurations

LocalCommand (Run on Connect)

PLAINTEXT
Host server-with-notification
    HostName server.example.com
    User admin
    LocalCommand notify-send "Connected to %n" 2>/dev/null
    PermitLocalCommand yes

Include External Configs

PLAINTEXT
# Main config
Host *
    ServerAliveInterval 60

# Include work-specific config
Include ~/.ssh/config.work

# Include personal config
Include ~/.ssh/config.personal

Match Directives

PLAINTEXT
# Different settings for specific networks
Match host *.internal.corp exec "is_vpn_connected"
    User admin
    IdentityFile ~/.ssh/corp_key

Match host * !exec "is_vpn_connected"
    # Don't allow corp connections without VPN
    HostName invalid

Environment Variables

PLAINTEXT
Host dynamic-server
    HostName %h.dynamic-dns.com
    User %u  # Uses local username

Complete Example Config

PLAINTEXT
# ~/.ssh/config

# ==========================================
# Global Settings
# ==========================================
Host *
    # Connection
    ServerAliveInterval 60
    ServerAliveCountMax 3
    
    # Performance
    Compression yes
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 4h
    
    # Security
    HashKnownHosts yes
    StrictHostKeyChecking accept-new
    
    # Default key
    IdentityFile ~/.ssh/id_ed25519

# ==========================================
# Personal Servers
# ==========================================
Host home-server
    HostName 192.168.1.50
    User ubuntu
    LocalForward 8080 localhost:8080
    LocalForward 3000 localhost:3000

Host pi
    HostName raspberrypi.local
    User pi
    IdentityFile ~/.ssh/pi_key

# ==========================================
# Work Infrastructure
# ==========================================
Host work-bastion
    HostName bastion.work.com
    User admin
    IdentityFile ~/.ssh/work_bastion_key

Host work-*
    HostName %h.internal.work.com
    User deploy
    IdentityFile ~/.ssh/work_key
    IdentitiesOnly yes
    ProxyJump work-bastion

Host work-db
    HostName database.internal.work.com
    User dbadmin
    LocalForward 5433 localhost:5432
    ProxyJump work-bastion

Host work-cache
    HostName redis.internal.work.com
    User admin
    LocalForward 6380 localhost:6379
    ProxyJump work-bastion

# ==========================================
# Cloud Providers
# ==========================================
Host aws-*
    User ec2-user
    IdentityFile ~/.ssh/aws_key
    StrictHostKeyChecking accept-new

Host gcp-*
    User %u
    IdentityFile ~/.ssh/gcp_key

Host do-*
    User root
    IdentityFile ~/.ssh/do_key
    HostName %h.droplet.hostname

# ==========================================
# Git Services
# ==========================================
Host github.com
    User git
    IdentityFile ~/.ssh/github_personal
    IdentitiesOnly yes

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_work
    IdentitiesOnly yes

Host gitlab.com
    User git
    IdentityFile ~/.ssh/gitlab_key
    IdentitiesOnly yes

Useful SSH Commands

BASH
# Test config validity
ssh -t git@github.com

# Verbose connection (debugging)
ssh -vvv myserver

# Connect with specific config
ssh -F ~/.ssh/config.work myserver

# Force specific key
ssh -i ~/.ssh/custom_key myserver

# Disable strict host checking (temporary, not recommended)
ssh -o StrictHostKeyChecking=no myserver

# Run command without interactive shell
ssh myserver "ls -la /var/log"

# Copy file via SCP with alias
scp myfile myserver:/tmp/

# Copy via jump host
scp -J bastion myfile internal-server:/tmp/

# Mount remote filesystem (SSHFS)
sshfs myserver:/remote/path /local/mount

# Sync with rsync over SSH
rsync -avz -e ssh ./local/ myserver:/remote/

Troubleshooting

Permission Issues

BASH
# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# Fix SELinux (if enabled)
restorecon -Rv ~/.ssh

Too Many Authentication Failures

BASH
# Server rejects after too many key attempts
ssh -o IdentitiesOnly=yes myserver

Connection Timeout

PLAINTEXT
Host slow-server
    HostName slow.example.com
    ConnectTimeout 30
    ServerAliveInterval 30

Debug Connection Issues

BASH
# See exactly what's happening
ssh -vvv myserver 2>&1 | head -50

# Check which config is used
ssh -G myserver  # Shows parsed config

Security Best Practices

  1. Use Ed25519 keys — Modern, secure, compact
  2. Disable password auth — Keys only in production
  3. Use separate keys per service — Compartmentalize
  4. Enable strict host checking — Prevent MITM attacks
  5. Hash known_hosts — Hide which servers you connect to
  6. Use ProxyJump — Don’t manually hop through bastions
  7. ControlMaster carefully — Understand connection reuse implications
  8. Review permissions — 600 for private keys, 700 for .ssh

Summary

  • Config file: ~/.ssh/config turns long commands into short aliases
  • Host patterns: Use wildcards for server groups (prod-*, *.internal)
  • ProxyJump: Automatic bastion hopping
  • Port forwarding: Access remote services locally (LocalForward)
  • Connection reuse: ControlMaster for speed
  • Multiple keys: Separate keys per service with IdentitiesOnly

A good SSH config saves hours of typing and prevents connection errors. Set it up once, benefit forever.


Reader Quality Feedback

Did this technical guide help solve your problem?

Suggest Errata ($0)
Jena
Primary Author

Jena

Systems Engineer and Linux specialist. Deeply focused on infrastructure automation, terminal productivity, and performance tuning for high-availability systems.

Explore Author Archive
Compute Fuel & Open Testbed
100% Independent & Verified

Fuel High-Density, Zero-Fluff Engineering Deep-Dives

Every guide on MeshWorld is validated on physical Linux nodes and reproducible testbeds. If this article saved you hours of debugging or unblocked production, consider funding our next cluster run.

Weekly Dispatch

Join MeshWorld Dispatch

Get practical tutorials, system blueprints, and curated AI engineering notes straight to your inbox. No fluff, zero spam.

Zero spam. 1-click unsubscribe anytime.Prefer RSS?
Curated Continuations

Up Next in This Domain.

Browse Full Archive