Skip to main content
Test Double company logo
Services
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Developers
Developers
Developers
DevOps & security

Streamlining SSH authentication with tmux: A guide to hassle-free sessions

Tired of SSH and tmux conflicts? Learn how to streamline SSH authentication with tmux in our step-by-step guide. Say goodbye to frustrating access issues!
Adam Lukens
|
November 17, 2016
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
~ $ git pull
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
~ $

Ugh. It’s happened again. I use public keys to authenticate to GitHub. I use tmux for pairing. Somehow, tmux and ssh-agent are fighting over whether they can authenticate me. But why?

Public keys

My GitHub key pairs are protected with a password. Typing it in is tedious, so I use ssh-agent to store the credentials while I’m logged in. SSH has a nifty feature called “Agent Forwarding” that will forward key requests on remote servers through an SSH tunnel to a locally running ssh-agent process. You can use it by passing the -A flag to ssh.

SSH forwards an agent by setting up a temporary socket file in your temp directory. It sets a few environment variables, primarily SSH_AUTH_SOCK. It sends requests to that socket. This temporary socket is wiped out when you end the SSH session (or the process ends by timing out), and you’ll get a new one the next time you SSH back in.

home ~ $ ssh -A remote
Last login: Fri Nov 18 03:39:46 2016 from 192.168.1.14

remote ~ $ echo $SSH_AUTH_SOCK
/tmp/ssh-4ubDInuAFh/agent.30599
remote ~ $ exit
connection to remote closed.

home ~ $ ssh -A remote
Last login: Fri Nov 18 03:40:06 2016 from 192.168.1.14

remote ~ $ echo $SSH_AUTH_SOCK
/tmp/ssh-ArPPCeB4Nm/agent.32382
remote ~ $ exit
connection to remote closed.

‍tmux

tmux is a great tool to creates a persistent, splittable, shareable interface to a terminal. It allows you to create a running terminal instance that survives you logging out, letting you keep an editor setup running even if you disconnect.

Unfortunately, it’s power is also it’s failing. tmux allows you to run programs longer than your current SSH session, which causes a number of environment variables to go stale.

Running processes

When you run a process, you’re actually forking the existing process, creating a parent and child. The parent continues on. The child process will load and run the new program, getting a copy of all existing environment variables (as well as access to file handles, etc). This is how programs we run have receive environment variables. This is why you can’t edit environment variables outside of an already running process (or at least without a debugger connected to that process).

Now, tmux also lets you store and retrieve environment variables. There’s a list of environment variables that are automatically updated every time you create or join a new tmux session. In fact, if you create a new window or pane on an old SSH session, it will give the current SSH_AUTH_SOCK variable for you.

That leaves old windows and panes, though. For that, we have two possible solutions.

Just set the variable already

One way is to create a bash function that can query tmux and get the current value of these variables.

@McPolemic I just ended up with this function for tmux + agent issues:

 fixssh() {
  eval $(tmux show-env -s |grep '^SSH_')
 }— Josh Greenwood (@JoshTGreenwood) October 12, 2016

Props to Josh Greenwood for not only solving this problem but also fitting the fix into a tweet 😄. Unfortunately, that also means that every time you connect to tmux, you’ll have to run this. In every window. In every pane. That can get a little repetitive. I was hoping to make this a little more automatic.

The socket shouldn’t really move

There are legitimate reasons to set the socket via temp files. It allows multiple SSH connections per user to have different ssh-agent settings for one. However, I don’t need that. Let’s disable that first. SSH allows you to create a file on the remote server with commands to run when you connect.

#!/bin/bash

# Fix SSH auth socket location so agent forwarding works with tmux
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

Good. Now we’ll always have our most recent agent socket symlinked to ~/.ssh/ssh_auth_sock. Now we want to tell tmux to use that tunnel. We’ll remove SSH_AUTH_SOCK from the list of environment variables that are updated (only for new sessions) every time we connect and set it to our static path instead.

# Remove SSH_AUTH_SOCK to disable tmux automatically resetting the variable
set -g update-environment "DISPLAY SSH_ASKPASS SSH_AGENT_PID \
                             SSH_CONNECTION WINDOWID XAUTHORITY"

# Use a symlink to look up SSH authentication
setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Now, while we may have to set this variable in any pre-existing windows, it will always be up-to-date going forward. As we disconnect and reconnect, our symlink will switch to the most recent SSH_AUTH_SOCK temp file.

This has a trade-off as well, though. Since it always takes the most recent socket, if you were to SSH in and disconnect, all sessions would be broken until you SSHed in again. I consider this a fair trade, though.

Bonus

Wait. I see more than one temporary-socket-looking-file in that /tmp folder. Does that mean I can access other user’s SSH credentials?

Yes, sort of. If you have sudo access, you could use those sockets to authenticate requests for SSHing into other hosts or accessing certain resources on GitHub and other hosts. Do keep that in mind, and please don’t forward on an agent connection if you don’t trust a host or the people who have access to it.

(Many thanks to Josh Greenwood and Raelyn Bangel for help with this post!)

Want more tips, tricks, and insights to level up your software game?

Sign up for the Test Double Dispatch and get the latest resources delivered right to your inbox.

Subscribe now

Related Insights

🔗
Explore the power of tmux and tmate for teamwork

Explore our insights

See all insights
Developers
Developers
Developers
You’re holding it wrong! The double loop model for agentic coding

Joé Dupuis has noticed an influx of videos and blog posts about the "correct" way of working with AI agents. Joé thinks most of it is bad advice, and has a better approach he wants to show you.

by
Joé Dupuis
Leadership
Leadership
Leadership
Don't play it safe: Improve your continuous discovery process to reduce risk

We often front-load discovery to feel confident before building—but that’s not real agility. This post explores how continuous learning reduces risk better than perfect plans ever could.

by
Doc Norton
Leadership
Leadership
Leadership
How an early-stage startup engineering team improved the bottom line fast

A fast-growing startup was burning cash faster than it could scale. Here’s how smart engineering decisions helped them improve the bottom line.

by
Jonathon Baugh
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct ManagementLegacy ModernizationDevOpsUpgrade RailsTechnical RecruitmentTechnical Assessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy Policy
© 2020 Test Double. All Rights Reserved.

Want more tips, tricks, and insights to level up your software game?

Sign up for the Test Double Dispatch and get the latest resources delivered right to your inbox.

Subscribe now