cafe.io

documentation

Mastering ~/.ssh/config for Faster Access

OpenSSH reads connection defaults from ~/.ssh/config, letting you trade long command flags for short aliases, enforce security standards, and share sane defaults across your team. A thoughtful config keeps production safe, lab environments reachable, and automation scripts predictable.

core building blocks

Each Host block names one or more patterns and the options that apply. Start with a narrow match, then fall back to a catch-all Host * block so every connection inherits safe defaults.

Host bastion
  HostName 35.88.12.42
  User deploy
  IdentityFile ~/.ssh/id_ed25519
  Port 22

Host *.staging.internal
  ProxyJump bastion
  User app
  IdentityFile ~/.ssh/staging_ed25519
  • Host: Alias or glob that matches ssh <alias>.
  • HostName: Real DNS name or IP that SSH should contact.
  • User: Default login account, so you skip ssh user@host.
  • Port: Non-standard port numbers without extra flags.
  • IdentityFile: Key path per environment, avoiding agent confusion.
  • ProxyJump: Hop through bastions automatically with native support for chains.

automation-friendly defaults

Layering shared defaults makes CLI tooling, Ansible runs, and IDE remote extensions behave the same way every time.

Host *
  ForwardAgent no
  ServerAliveInterval 30
  ServerAliveCountMax 3
  StrictHostKeyChecking ask
  UserKnownHostsFile ~/.ssh/known_hosts

Disable agent forwarding by default, send keepalives to survive flaky networks, and point host key storage to files you version-control. Combine these with ControlMaster, ControlPath, and ControlPersist to reuse multiplexed connections when running Git or rsync repeatedly.

advanced routing and security

  • ProxyCommand / ProxyJump: Tunnel through SSH bastions or SOC-approved jump hosts without custom scripts.
  • LocalForward / RemoteForward: Declare port tunnels inline so databases and UIs show up automatically.
  • Match: Apply rules based on user, host, or address: Match host *.prod exec "/usr/local/bin/allow-prod".
  • CanonicalizeHostname: Normalize short names to FQDNs to avoid duplicate host keys.
  • PreferredAuthentications: Force key-first auth, falling back to hardware tokens before passwords.

These options reduce the need for ad-hoc shell scripts, keep audit trails tidy, and give platform teams guardrails without slowing down developers.

breaking down large configs

As your infrastructure grows, a single monolithic file becomes hard to review. Use Include to stitch together smaller, purpose-built files.

# ~/.ssh/config
Include ~/.ssh/config.d/*.conf

Host *
  ForwardAgent no
  • Group by environment: Split into prod.conf, staging.conf, and personal.conf for clearer reviews.
  • Share with teams: Check in read-only snippets to a repo, then symlink or copy them into config.d.
  • Override locally: Later includes win, so personal tweaks can sit in local.conf without editing shared files.

tips for collaboration

  1. Document your aliases so incident responders know the real hostnames behind shortcuts.
  2. Lint configs in CI with ssh -G host to catch typos before they ship to everyone.
  3. Store secrets (keys, ControlPath sockets) outside version control; use templates or scripts to place them.
  4. Audit known_hosts additions when onboarding new teams to avoid MITM trust issues.

SSH config is a living artifact. Keep it reviewed alongside infrastructure changes so your team never reaches for raw IP addresses in the middle of an incident.