— Nov 16, 2013
TL;DR Armed with my
ng scripts in one hand and ngrok
in the other, I have finally found a quick, effective and secure way to pair
program with anyone, anywhere using tmux on my local box.
If you want more information about the setup, read on.
**Updated** November 17, 2013
Tmux is a fantastic productivity tool for developers that prefer to stick with the command line. The hardest part is sharing a session from anywhere (securely).
I’d like to share my setup for remote tmux pair programming with you. Here’s what we’re going to accomplish:
Seriously, you don’t want to hand out passwords. PKI is a great way to allow connections by handshake with users. True story: if you’re a Github user, your public keys are publically available. Don’t worry, they’re supposed to be public, and this allows us to do very cool things.
Chris Hunt’s github-auth
gem allows you to manage Github users’ public keys in your
~/.ssh/authorized_keys file so that you can easily allow/revoke users’
ability to remote into your machine.
$ gem install github-auth
We use the gem’s binary
gh-auth to authorize Github users to remote into our
machine. It’s pretty straightforward:
$ gh-auth add --users="iamvery" --command="$(which tmux) attach -s pairing"
This adds the public keys for the specified Github user “iamvery” (me!) to the
~/.ssh/authorized_keys file. The
--command option allows us to specify
a forced command
(you’ll have to browse down for section on “Forced Commands”) which
automatically connects them to the tmux session.
You can remove added users by the similar
gh-auth remove command. Luckily
all of this is wrapped up for simplicity by my
This is the holy grail of a solid tmux pairing setup. It’s not very practical to pair with someone logged into your account locally. In most cases your pair is far removed from you, and networking is hard. You might be at a coffee shop or tethering to your 3G smartphone on the way to Disney World. In these situations it’s tricky to provide an SSH connection back to your machine without access to a firewall’s port forwarding settings (if even you would want to do such a thing).
The beautiful people at ngrok.com have created an excellent tool for establishing reverse tunnels back to your machine. This is great for sharing a local development web server over the Internet. However, with their inclusion of TCP in the list of supported protocols, they hit it out of the park. The implication is that we can establish a reverse TCP connection back to our computer through their service. Yes.
Signup, download and
ngrok (I like to keep it in my
~/bin directory). Then spin up a TCP
tunnel for SSH:
$ ngrok --proto=tcp 22 # tunneling to SSH ngrok (Ctrl+C to quit) Tunnel Status online Version 1.6/1.5 Forwarding tcp://ngrok.com:12345 -> 127.0.0.1:22 Web Interface 127.0.0.1:4040 # Conn 0 Avg Conn Time 0.00ms
This command takes over the terminal with some connection information, so you
may want to open up another terminal window to test it out. You’ll notice the
connection to your machine is available at
ngrok.com on port
connect to our machine through ngrok and make sure the setup is working:
$ ssh -p 12345 [email protected] Password: # unless you're use key-based auth... You are using key-based auth, right? $ # :boom:
Any connection error when running this SSH command indicates a problem with your ngrok setup or perhaps a typo in the SSH command.
I encourge you to support this service. They probably just made your day.
I was recently turned on to this service. http://tmate.io is an interesting take on terminal pairing. It’s a fork of tmux proper that does the heavy lifting of setting up and securing the connection between you and your pair. Check it out, it may be exactly what you need, but do take the time to understand the tradeoffs.
I keep a lot of my environment on Github. I have been working on a couple scripts to make this process easier. They’re not perfect, but hopefully they’re helpful. I’ll to continue to improve them over time.
pair script. makes the processes of adding and
removing tmux users a little easier. It also automates the process of spinning
up your pairing environment.
When all the dependencies are met, type the command:
$ pair up iamvery # where "iamvery" is the github username of your pair
pair --help for the full command signature.
ng script is a small wrapper of the ngrok command.
It also figures out the SSH command needed to connect to your tunnel. Since
ngrok doesn’t provide a simple means for determining the port it selected for
your connection we have to do a little scraping of the local ngrok web server
to gather all the pieces.
The end result is a couple of helpful commands:
$ ng connect # connects and runs the ngrok tunnel $ ng ssh ssh -p 12345 [email protected]
This script is used by the
pair script to put all the pieces together for a
quick remote pairing session.
One thing that is currently excluded from github-auth is the ability to disable forwarding (see the section named “Disabling Forwarding”). This would prevent connecting users from establishing tunnels through their connection to your machine. For now I use a local build of the gem that includes these additional options.
For some reason it creeps me out a little bit to hand out my local username to pairs. That may be silly, but it prompted me to learn about a neat little feature of Mac OS X, user aliases. I’m not sure this really provides any security, but I do like the feel of having the pair SSH with the “tmux” username.
Wow, this was a long winded post, but hopefully full of great information. Pair programming with tmux is a fantastic in a lot of ways, but doing it remotely has always been a little tricky. It feels great to finally have a setup that’s quick and easy to spin up when the mood strikes.
What do you think of the method? Is it horribly insecure? Do you love it? Hate it? Let me know!