When managing multiple Linux clients and remote servers, maintaining consistent SSH configurations across machines becomes crucial. The traditional approach of using -F
flag with every SSH command creates friction when working with SSH-dependent tools like rsync, scp, or git.
While SSH doesn't directly support environment variables for config file paths, we have several effective workarounds:
Solution 1: SSH_CONFIG Environment Variable
Create a wrapper script for ssh that checks an environment variable:
#!/bin/bash
# ~/workspace/bin/ssh_wrapper
if [ -n "$SSH_CONFIG_FILE" ]; then
/usr/bin/ssh -F "$SSH_CONFIG_FILE" "$@"
else
/usr/bin/ssh "$@"
fi
Solution 2: PATH Modification with Wrapper
Prepend your custom directory to PATH in your bashrc:
# In workspace/bashrc
export PATH=~/workspace/bin:$PATH
export SSH_CONFIG_FILE=~/workspace/etc/ssh_config
For rsync and similar tools, create corresponding wrappers:
#!/bin/bash
# ~/workspace/bin/rsync_wrapper
if [ -n "$SSH_CONFIG_FILE" ]; then
/usr/bin/rsync -e "ssh -F $SSH_CONFIG_FILE" "$@"
else
/usr/bin/rsync "$@"
fi
For more permanent solutions, consider these approaches:
# Option 1: Symlink default config location
ln -s ~/workspace/etc/ssh_config ~/.ssh/config
# Option 2: Include directive in main config
echo "Include ~/workspace/etc/ssh_config" >> ~/.ssh/config
Your shared ssh_config might contain:
Host server1
HostName server1.example.com
User admin
Port 2222
IdentityFile ~/workspace/keys/server1_key
ServerAliveInterval 60
Enhance your rsync script to maintain permissions:
#!/bin/bash
rsync -avz --delete --perms --chmod=600 \
~/workspace/etc/ssh_config \
other-client:~/workspace/etc/
Consider storing your workspace in git for better change tracking:
cd ~/workspace
git init
echo "etc/ssh_config" >> .gitignore # if containing sensitive data
git add bin/ bashrc
git commit -m "Initial workspace setup"
As a Linux sysadmin juggling multiple client machines (all running Debian in my case), maintaining consistent SSH configurations across devices becomes crucial. My current setup involves:
~/workspace/
├── bashrc
└── etc/
└── ssh_config
The challenge emerges when non-interactive SSH commands (rsync, scp, etc.) need to reference my custom configuration. While interactive SSH works perfectly with aliases like:
alias s1='ssh -F ~/workspace/etc/ssh_config server1.example.com'
Other tools force verbose command-line specifications:
rsync -Pavz --delete -e "ssh -F $HOME/workspace/etc/ssh_config" ...
OpenSSH actually provides multiple ways to handle this without environment variables:
- System-wide configuration: Place your config in
/etc/ssh/ssh_config.d/
- XDG Base Directory Specification: Use
~/.config/ssh/config
- SSH_CONFIG environment variable: Sadly doesn't exist (contrary to popular belief)
Here are three battle-tested approaches I've implemented:
1. Symbolic Link Strategy
ln -s ~/workspace/etc/ssh_config ~/.ssh/config
Pros:
- Zero configuration changes needed in commands
- Works with all SSH-based utilities
2. SSH Wrapper Function
Add to your bashrc
:
ssh() {
command ssh -F ~/workspace/etc/ssh_config "$@"
}
3. RSYNC_RSH Environment Variable
For rsync specifically:
export RSYNC_RSH="ssh -F $HOME/workspace/etc/ssh_config"
For teams managing multiple environments:
#!/bin/bash
# sync-ssh-config.sh
CONFIG_REPO="git@github.com:ourteam/ssh-configs.git"
pull_latest() {
git -C ~/workspace/etc/ pull origin main
}
deploy_all() {
ln -sf ~/workspace/etc/ssh_config ~/.ssh/config
ln -sf ~/workspace/etc/ssh_config /etc/ssh/ssh_config.d/99_our_config
}
Remember to:
- Set strict permissions:
chmod 600 ~/workspace/etc/ssh_config
- Use
Include
directives for machine-specific overrides - Consider SSH certificate authentication for large deployments
Example config snippet:
Host *.example.com
IdentityFile ~/workspace/keys/production_key
CertificateFile ~/workspace/keys/production_key-cert.pub
Include ~/workspace/etc/ssh_config.d/region-specific