Don't put your private key on a public server

Aug 25, 2010

You're administering a server (Server A), and you need access to something on another server (Server B) but access is denied from Server A because you don't have your private key on there. If this is a scenario you've run into while trying to deploy an application it's almost certain that you don't want to put your private key on the server in the home directory of your deployment user, readable to anyone that can log in as that account (i.e, people other than you!).

SSH Agent Forwarding to the rescue

To get around this SSH has built in support for forwarding on your private credentials. What happens is that when you connect to a remote server the ssh-agent creates a unix socket and then listens to connections from ssh, this socket is accessible only by your user account and root.

Yes, what this in fact means is that the root user on the remote server has access to the unix socket you've created. They can't see your private keys, they're still safely held on your client, but while you're connected to the remote server the root user on that machine could potentially use that socket to connect as you to another server. In short, make sure you trust root before you set this up (still, it's better than putting your private key in your home directory where root would now be able to see they key and use it whenever they wanted).

Configure your SSH client to use Agent Forwarding

Getting it to work is as simple as adding an entry to ~/.ssh/config (create the file if it doesn't exist):

Host remote-server.example.com

ForwardAgent yes

Just replace the Host value with the hostname or IP address of the server you are connecting to, or with * if you're brave and want to do it automatically for all hosts.

Restarting your local SSH Agent

On my Macbook Pro I've added the following to my ~/.bash_profile to make sure that the SSH Agent is started when I open a new terminal and that my identities (private keys) are added to it:

    SSH_ENV=$HOME/.ssh/environment



    function start_agent {

         echo "Initializing new SSH agent..."

         /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}

         echo succeeded

         chmod 600 ${SSH_ENV}

         . ${SSH_ENV} > /dev/null

         /usr/bin/ssh-add;

    }



    if [ -f "${SSH_ENV}" ]; then

         . ${SSH_ENV} > /dev/null

         ps -x | grep "^ *${SSH_AGENT_PID}" | grep ssh-agent$ > /dev/null || {

             start_agent;

         }

    else

         start_agent;

    fi
Hi, I'm Glenn! 👋 I've spent most of my career working with or at startups. I'm currently the Director of Product @ Ockam where I'm helping developers build applications and systems that are secure-by-design. It's time we started securely connecting apps, not networks.

Previously I led the Terraform product team @ HashiCorp, where we launched Terraform Cloud and set the stage for a successful IPO. Prior to that I was part of the Startup Team @ AWS, and earlier still an early employee @ Heroku. I've also invested in a couple of dozen early stage startups.