Dynamic SSH Host Configuration with Wildcard Patterns and Variable Substitution


2 views

When administering multiple servers through an SSH gateway, maintaining individual entries in ~/.ssh/config becomes unwieldy. A typical scenario looks like this:

Host server1-via-gateway
Hostname server1.internal
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc %h 22

Host server2-via-gateway
Hostname server2.internal
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc %h 22

SSH config does support pattern matching and variable substitution, though not as extensively as shell scripting. Here's the solution:

Host *.via-gateway
Hostname %h
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc ${${(%):-%n}#*.} 22

For more complex transformations, use a wrapper script:

Host *
ProxyCommand /usr/local/bin/ssh-proxy-wrapper %h

Then create ssh-proxy-wrapper:

#!/bin/bash
# Extract the actual hostname from the pattern
TARGET_HOST="${1%.via-gateway}"
exec ssh gateway.example.com nc $TARGET_HOST 22

For dynamic environments, generate configs programmatically:

#!/bin/bash
# Generate SSH config entries for all hosts in inventory
while read host; do
  echo "Host $host.via-gateway"
  echo "  Hostname $host"
  echo "  ProxyCommand ssh gateway nc $host 22"
  echo
done < host-list.txt >> ~/.ssh/config

SSH 7.3+ supports includes for modular configurations:

Include config.d/*.conf

Then maintain separate files for different host groups.

Remember to:

  • Set proper permissions: chmod 600 ~/.ssh/config
  • Audit generated configurations
  • Use SSH certificates for large deployments

When managing multiple servers behind a gateway, manually maintaining SSH config entries becomes tedious. Here's a smarter approach to automate this process while maintaining security and convenience.

The standard approach requires individual entries for each host:

Host server1
  Hostname server1.internal
  ProxyCommand ssh gateway -W %h:%p

Host server2
  Hostname server2.internal
  ProxyCommand ssh gateway -W %h:%p

We can leverage pattern matching and variable substitution in SSH config:

Host *.internal
  ProxyCommand ssh gateway -W $(echo %h | sed 's/.internal$//'):%p
  User admin
  IdentityFile ~/.ssh/gateway_key

For more complex naming schemes, consider these approaches:

# For hosts following pattern dev-XXX
Host dev-*
  ProxyCommand ssh gateway -W $(echo %h | cut -d'-' -f2).dev.env:%p

# Using different environments
Host *.prod
  ProxyCommand ssh prod-gateway -W %h:%p
Host *.stage
  ProxyCommand ssh stage-gateway -W %h:%p

To keep your config manageable:

  • Group related hosts with common patterns
  • Document naming conventions in config comments
  • Consider generating config snippets from inventory systems

When automating configurations:

# Restrict access to specific hosts
Host restricted-*
  ProxyCommand ssh gateway -W $(echo %h | sed 's/restricted-//').secure:%p
  User limited
  IdentityFile ~/.ssh/restricted_key