How to Automatically Load Custom .bashrc and Config Files on SSH Login Without Server Modifications


35 views

As DevOps engineers and system administrators, we frequently encounter temporary server environments where:

  • Ephemeral cloud instances spin up and down constantly
  • Short-lived test environments get recycled daily
  • Temporary troubleshooting sessions require quick access

The traditional approach of manually copying dotfiles to each server becomes impractical when dealing with dozens of transient systems.

The solution lies in SSH's LocalCommand and RemoteCommand options. Create or modify your local ~/.ssh/config:

Host *
    PermitLocalCommand yes
    RemoteCommand bash --rcfile <(echo "source /dev/stdin" <<< "$(cat ~/path/to/your/bashrc)")

For a more robust solution that handles multiple config files:

function ssh_with_dotfiles() {
    local host=$1
    local bashrc_content=$(cat ~/.bashrc_custom)
    local gitconfig_content=$(cat ~/.gitconfig_custom)
    
    ssh -t $host < /tmp/.bashrc_temp_$$
        echo '$gitconfig_content' > /tmp/.gitconfig_temp_$$
        bash --rcfile /tmp/.bashrc_temp_$$ -i
        rm -f /tmp/.bashrc_temp_$$ /tmp/.gitconfig_temp_$$
EOF
}

For enterprise environments, combine SSH certificates with forced commands:

# In your CA-signed certificate
force-command="bash --rcfile <(curl -s https://your.domain.com/bashrc_profile)"
  • Use base64 encoding for complex dotfiles to avoid quoting issues
  • Consider timeout mechanisms for slow connections
  • Implement cleanup traps for temporary files

If you encounter problems:

  1. Verify SSH client version supports these features (ssh -V)
  2. Check server-side PermitUserRC setting
  3. Test with -vvv flag for verbose debugging

As infrastructure becomes more ephemeral with containerized workloads and auto-scaling groups, maintaining consistent developer environments across multiple short-lived instances has become a pain point. When SSHing into dozens of temporary servers daily, manually transferring .bashrc, .vimrc, or gitconfig files becomes impractical.

The most elegant approach combines SSH's RemoteCommand with bash's --rcfile parameter. Add this to your local ~/.ssh/config:

Host *.temporary-servers.com
  RemoteCommand bash --rcfile <(curl -s https://example.com/remote_bashrc)
  RequestTTY force

This downloads and executes your custom bashrc from a central location without leaving any files on the remote server.

For more complex setups, use SSH environment passing with AcceptEnv:

# Local machine:
ssh -o SendEnv=MY_BASHRC_CONTENT server.com

# Remote server /etc/ssh/sshd_config:
AcceptEnv MY_BASHRC_CONTENT

Then in your default remote .bashrc:

[[ -n "$MY_BASHRC_CONTENT" ]] && 
  source <(echo "$MY_BASHRC_CONTENT")

The same principle applies to git configurations:

ssh -t server.com "git config --global include.path /dev/stdin <<'EOF'
[user]
  name = Your Name
  email = your@email.com
EOF"

For maximum flexibility, create a bash function:

function smart_ssh() {
  local host=$1
  ssh -t $host "bash --rcfile <(
    echo 'alias ll=\"ls -alh\"';
    echo 'export PS1=\"\$$\\033[01;32m\$$\\u@\\h\$$\\033[00m\$$:\$$\\033[01;34m\$$\\w\$$\\033[00m\$$\\$ \"';
    cat ~/base_bashrc
  )"
}

When implementing these solutions:

  • Use HTTPS for remote config fetching
  • Validate content with checksums
  • Consider SSH certificate-based auth
  • Avoid storing sensitive data in shared configs