Why do I have to re-set env vars in tmux when I re-attach?

Since I received the Bounty, I'll repost my key-comment for completeness sake - and to avoid setting visitors with the same problem on the wrong track:

Tmux will remove Environment Variables

Tmux' man page states that update-environment will remove variables "that do not exist in the source environment [...] as if -r was given to the set-environment command".

Apparently that what caused the issue. See Chris' response below. However, I still can't imagine how the variable could be absent in the "source environment" and yet be valid in the newly created tmux window...


Previous Answer:

How SSH forwarding works

On the remote machine, take a look at the environment of your shell after establishing the SSH connection:

user@remote:~$ env | grep SSH
SSH_CLIENT=68.38.123.35 45926 22
SSH_TTY=/dev/pts/0
SSH_CONNECTION=68.38.123.35 48926 10.1.35.23 22
SSH_AUTH_SOCK=/tmp/ssh-hRNwjA1342/agent.1342

The important one here is SSH_AUTH_SOCK which is currently set to some file in /tmp. If you examine this file, you'll see that it's a Unix domain socket -- and is connected to the particular instance of ssh that you connected in on. Importantly, this changes every time you connect.

As soon as you log out, that particular socket file is gone. Now, if you go and reattach your tmux session, you'll see the problem. It has the environment from when tmux was originally launched -- which could have been weeks ago. That particular socket is long since dead.

Solution

Since we know the problem has to do with knowing where the currently live SSH authentication socket is, let's just put it in a predictable place!

In your .bashrc or .zshrc file on the remote machine, add the following:

# Predictable SSH authentication socket location.
SOCK="/tmp/ssh-agent-$USER-screen"
if test $SSH_AUTH_SOCK && [ $SSH_AUTH_SOCK != $SOCK ]
then
    rm -f /tmp/ssh-agent-$USER-screen
    ln -sf $SSH_AUTH_SOCK $SOCK
    export SSH_AUTH_SOCK=$SOCK
fi

I don't think you even have to put an 'update-environment command' in your tmux.conf. According to the man page, SSH_AUTH_SOCK is already covered by default.

Credit

My response is an excerpt of this blog post by Mark 'xb95' Smith who explains the same problem for screen.


I figured this out. Short answer, I needed to remove SSH_AUTH_SOCK from update-environment. Since it was in that list, the value was being blown away every time I reattached. Thanks to @djf for the clue. The salient bit from the tmux(1) man page in the update-environment section:

Any variables that do not exist in the source environment are set to be removed from the session environment (as if -r was given to the set-environment command).


Instead of using tmux to handle my ssh-agent, I have bash handle it with:

### SSH Agent ### {{{
SSH_ENV="$HOME/.ssh/environment"

function start_agent {
    echo "Initialising 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;
}

## Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
  else
    start_agent;
fi
### End SSH Agent ### }}}

I have this in my ~/bashrc, and it works great.