← All articles
TERMINAL SSH for Developers: Config, Keys, Tunneling, and Sec... 2026-02-09 · 5 min read · ssh · security · terminal

SSH for Developers: Config, Keys, Tunneling, and Security

Terminal 2026-02-09 · 5 min read ssh security terminal devops tunneling

SSH for Developers: Config, Keys, Tunneling, and Security

SSH is one of those tools that most developers use daily but few configure well. A properly set up SSH config saves you from typing long commands, makes multi-server workflows painless, and improves your security posture. Here's everything you need to know.

SSH Config File Mastery

The SSH config file (~/.ssh/config) lets you define named hosts with specific connection settings. Instead of typing ssh -i ~/.ssh/work_key -p 2222 [email protected], you type ssh staging.

Basic Structure

# ~/.ssh/config

# Personal GitHub
Host github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal

# Work GitHub (different account)
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work

# Production server
Host prod
    HostName 203.0.113.50
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_work

# Staging server (behind VPN)
Host staging
    HostName 10.0.1.50
    User deploy
    ProxyJump bastion

# Bastion/jump host
Host bastion
    HostName bastion.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519_work

Wildcard Patterns

Apply settings to multiple hosts at once:

# All work servers
Host *.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519_work
    ServerAliveInterval 60
    ServerAliveCountMax 3

# Default settings for all connections
Host *
    AddKeysToAgent yes
    IdentitiesOnly yes
    HashKnownHosts yes

ServerAliveInterval 60 sends a keepalive packet every 60 seconds, preventing connections from dropping during idle periods. IdentitiesOnly yes prevents SSH from trying every key in your agent, which can cause authentication failures when you have many keys.

Useful Options

Option What it does
IdentitiesOnly yes Only try keys specified by IdentityFile
ServerAliveInterval 60 Send keepalive every 60 seconds
Compression yes Compress data (useful for slow connections)
ControlMaster auto Reuse connections (see multiplexing below)
ForwardAgent yes Forward SSH agent (use cautiously)

Connection Multiplexing

Multiplexing reuses a single TCP connection for multiple SSH sessions to the same host. This eliminates reconnection overhead.

Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600
mkdir -p ~/.ssh/sockets

After the first connection to a host, subsequent ssh, scp, and rsync commands connect instantly. ControlPersist 600 keeps the connection alive for 10 minutes after the last session closes.

Key Management

Generate ed25519 Keys

Always use ed25519. RSA keys still work but ed25519 is faster, shorter, and more secure.

# Generate a key with a descriptive comment
ssh-keygen -t ed25519 -C "hailey@work-laptop-2026"

# Generate a key with a custom filename
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "work"

Always use a passphrase. A key without a passphrase is equivalent to writing your password in a file on disk.

ssh-agent

The SSH agent holds your decrypted private keys in memory so you only enter your passphrase once per session.

# Start the agent (usually automatic on modern systems)
eval "$(ssh-agent -s)"

# Add a key
ssh-add ~/.ssh/id_ed25519

# Add with a time limit (key is forgotten after 4 hours)
ssh-add -t 4h ~/.ssh/id_ed25519

# List loaded keys
ssh-add -l

On macOS, add this to your SSH config to use the Keychain:

Host *
    UseKeychain yes
    AddKeysToAgent yes

On Linux with GNOME or KDE, the desktop environment typically runs an SSH agent automatically. systemd users can also enable ssh-agent.service.

1Password SSH Agent

1Password can act as your SSH agent, storing keys in its vault. This is excellent for teams because keys are backed up, synced across devices, and protected by 1Password's security model.

# ~/.ssh/config
Host *
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

On Linux:

Host *
    IdentityAgent ~/.1password/agent.sock

When you SSH somewhere, 1Password prompts for biometric authentication. The private key never leaves 1Password's secure storage. This is the most convenient and secure approach for individual developers.

Jump Hosts and Tunneling

Jump Hosts (ProxyJump)

A jump host (bastion) is a server that sits between you and your target. Use ProxyJump instead of the older ProxyCommand syntax.

Host internal-db
    HostName 10.0.2.100
    User admin
    ProxyJump bastion.example.com
# Command line equivalent
ssh -J bastion.example.com [email protected]

# Multiple jumps
ssh -J bastion1,bastion2 admin@target

ProxyJump creates an encrypted tunnel through the bastion. The bastion never sees the traffic to the final destination in plaintext.

SSH Tunneling (SOCKS Proxy)

Create a SOCKS proxy to route all traffic through a remote server:

ssh -D 1080 -N remote-server

Configure your browser or application to use localhost:1080 as a SOCKS5 proxy. Useful for accessing internal web applications without a VPN.

Port Forwarding for Local Development

Port forwarding is one of SSH's most underused features for development. It lets you securely access remote services as if they were running locally.

Local Port Forwarding

Access a remote service through a local port:

# Forward local port 5432 to a remote PostgreSQL server
ssh -L 5432:localhost:5432 db-server

# Forward to a service on the remote network (not the SSH server itself)
ssh -L 5432:internal-db.example.com:5432 bastion

# Run in background
ssh -fNL 5432:localhost:5432 db-server

Now psql -h localhost -p 5432 connects to the remote database through an encrypted tunnel.

Remote Port Forwarding

Expose a local service to a remote server:

# Make local port 3000 available on the remote server's port 8080
ssh -R 8080:localhost:3000 remote-server

Useful for sharing a local development server with a colleague or testing webhooks.

Config File Forwarding

Host dev-db
    HostName db-server.example.com
    User admin
    LocalForward 5432 localhost:5432
    LocalForward 6379 localhost:6379

Now ssh dev-db automatically sets up port forwarding for both PostgreSQL and Redis.

Secure Practices

Do

Don't

Hardening sshd_config

If you manage servers, these settings matter:

# /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
MaxAuthTries 3
AllowUsers deploy admin

Quick Reference

# Test connection
ssh -T [email protected]

# Copy public key to server
ssh-copy-id user@server

# Copy file
scp file.txt server:/path/

# Sync directory
rsync -avz ./local/ server:/remote/

# Check SSH config syntax
ssh -G hostname

# Verbose connection debugging
ssh -vvv hostname

The -G flag is invaluable for debugging config issues. It prints the resolved configuration for a host without connecting, showing you exactly which settings will be applied.

Recommendations