X11 forwarding doesn't work with multiple tmux sessions

If I start a tmux session locally and leave it open, then ssh in remotely and start a new tmux session (not attaching to the old one, a brand spanking new session) X11 forwarding seems to break. I've tried this workaround for a similar issue with screen but to no avail...

The error message when I try to launch a GUI app (like xeyes) is something to the effect of can't open display: wrong authentication. I actually don't know what it is for sure because it seems like it's outputting a carriage return and overwriting part of the error message with a new one...

For now I just go through and manually close all the tmux sessions that I had started locally before starting my new remote session. Is there any way to get X11 forwarding working with mixed local/remote tmux sessions?


Solution 1:

Not 100% sure it'll work for you, but that link didn't work for me either and I just copied the DISPLAY variable from the initial terminal and wrote export DISPLAY=${copied from outside tmux} which worked fine - i.e.

log in ...
echo $DISPLAY # remember this
tmux a
export DISPLAY=${variable from memory}

the function from that link gave me a completely different DISPLAY which didn't work

Solution 2:

I had a similar problem. In my situation, setting DISPLAY wasn't enough. By default, some of the environment is set when starting the tmux server (when starting the first session), not just any new session. The following works for me, but I doubt it's optimal.

In .tmux.conf, make tmux remember the variables that you want to keep from the outside environment. I used ones that differed between locally using Gnome Terminal and remotely using Terminal.app. Some of them probably aren't necessary, but I'm not sure which. The -g flag might not be correct.

set -g update-environment "\
  CLUTTER_IM_MODULE \
  DBUS_SESSION_BUS_ADDRESS \
  DBUS_SESSION_BUS_ADDRESS \
  DEFAULTS_PATH \
  DESKTOP_AUTOSTART_ID \
  DESKTOP_SESSION \
  DISPLAY \
  GDMSESSION \
  GNOME_DESKTOP_SESSION_ID \
  GPG_AGENT_INFO \
  GTK_IM_MODULE \
  GTK_MODULES \
  SESSION_MANAGER \
  SSH_AGENT_PID \
  SSH_ASKPASS \
  SSH_AUTH_SOCK \
  SSH_CONNECTION \
  WINDOWID \
  WINDOWPATH \
  XAUTHORITY \
  XDG_CONFIG_DIRS \
  XDG_CURRENT_DESKTOP \
  XDG_DATA_DIRS \
  XDG_MENU_PREFIX \
  XDG_RUNTIME_DIR \
  XDG_SEAT \
  XDG_SESSION_DESKTOP \
  XDG_SESSION_ID \
  XDG_SESSION_TYPE \
  XDG_VTNR \
  XMODIFIERS \
  "

Despite the name "update-environment", the setting doesn't seem to actually change the environment. You can, however, retrieve it using tmux show-environment. So I used it to update the environment in my .zshrc:

zshrc_restore_x11_vars()
{
  if [[ -z $TMUX ]]
  then
    return 0
  fi

  local tmux_env="$(tmux show-environment)"

  for var_line in ${(f)tmux_env}
  do
    if [[ $var_line == -[A-Za-z_]* ]]
    then
      local var=${var_line#-}
      unset $var

    elif [[ $var_line == [A-Za-z_]*'='* ]]
    then
      export $var_line

    fi
  done
}

precmd()
{
  zshrc_restore_x11_vars
}

preexec()
{
  zshrc_restore_x11_vars
}

Using tmux show-environment -s probably would have been better. But I didn't know about that until I re-read part of man tmux to write this answer.

Still, I have to detach and reattach sometimes, when using an existing session. Though it is much less annoying than before.

Full disclosure: The idea of using tmux show-environment in theprecmd and preexec hooks wasn't my own, but I forget where I saw it. Thank you, to whoever wrote that, wherever you wrote it.