Background
My team has been pair programming for several months. We work out of New York City, but some of us are based in other cities where we spend time. We tried a few different methods of pair programming remotely, but nothing really captured the feeling of being at the same computer.
We tried the various methods for screen sharing such as Skype, Google+ Hangouts, and direct Mac screen sharing. We also tried using the SubEthaEdit editor which worked for basic document editing but didn’t fit in with the flow of coding wanted. After reading several blog posts about tmux, I felt that we could use this tool along with the vim editor to create a real remote pairing environment that did not impede our existing workflow.
Fortunately, none of the developers on our team are particularly attached to any one editor or IDE, so using vim was not a big deal. We use RubyMine, Sublime Text 2, and Macvim on a day-to-day basis. The only change is the need to use console vim over Macvim.
My goal in this experiment was to setup my Macbook Pro such that one of my pair partners would log in and share a tmux session with me. I had a couple of aborted starts, but finally arrived at a useful setup. I’ll walk you through the setup. One thing to note is that all hardware on all sides of this is Apple hardware. I see no reason one couldn’t do this with another flavor of Unix or maybe even Windows, but I have not tried it myself.
Making The Connection
The first step, in this instance, was to get my partner connected to my local machine securely. If you and your pairing partner are on the same network, you can probably skip this step. If you don’t have direct control of your network infrastructure, you may need to get your IT department involved.
I’m behind a cable model and use an Apple Airport Extreme wireless base station to provide wifi throughout my house. Since my Macbook uses a private internal IP address, the first thing I needed to do was turn on port forwarding for SSH remote logins to my machine. The Airport Extreme makes this easy, and other wirelss and wired routers should be similarly simple. Here is what I did for the Airport:
- The Airport ships with a management utility, start it up and click “Manual Setup”.
- Choose the “Advanced” from the Settings menu (or click the tool bar icon).
- Select the Port Mapping tab and click the “+” to add a new port mapping.
- From the Service drop-down, select “Remote Login – SSH”.
- The defaults should be fine. The public and private TCP ports are 22 and the private IP address should be the private address your machine has been assigned on the network by the router. To verify your private IP, you can look at Network in the System Preferences. If you are not comfortable opening port 22 because it seems a little too obvious, you can mape some other TCP/IP port on the public side, such as port 2000.
- Once you accept the configuration, you should see the new port mapping for “Remote Login – SSH” in the “Allow” box and the check box next to it should be checked. Accept the change and the Airport Extreme will reboot.
You are now set to accept incoming SSH connections to your local machine.
The next step is for your remote colleague to connect securely to your machine. There are several ways to go about this, but it seemed to me that the most expedient way was to allow a key-based SSH connection to my machine using my own account. The idea being that once that connection is made, my partner would be logged in to my account as me.
WARNING: There are good reasons not to do this. My colleague now has full access to my home directory with the same permissions I have myself — including my sudo rights. There is no reason one couldn’t setup a separate account with tighter access controls rather than using your personal account. I trust my pair partner and wasn’t particularly worried about him accessing my machine.
Your mileage may vary.
To get my pair partner logged in securely, he sent me his public SSH key and I added that to my own ~/.ssh/authorized_keys file so he could make a key-based SSH connection. Once that key was in place, he issued this command from a terminal on his machine:
ssh troy@[my public IP address]
If you choose non-standard public TCP/IP port, it would be something like:
ssh -p 2000 troy@[my public IP address]
That’s the IP address that is assigned to the public side of my router by my cable model provider. You can find out what that IP address should be by simply typing “what is my IP address” into Google.
Again, he’s logging into my account (“troy”) on my local Macbook Pro. Once this connection is established, he will have a shell on my computer and be in my home directory.
Tmux
On my Macbook Pro, I start a tmux session and specify a socket:
tmux -S /tmp/remotepair
My pair partner then starts a tmux session and attaches to that socket:
tmux -S /tmp/remotepair attach
Now, if one of us types in the terminal in the tmux session, the other should see it. Time to fire up vim.
Vim
If you’re using vim, then you have your own configuration and you’ll need to negotiate that configuration with your pairing partner. <a href=”http://tomdale.net/2012/01/tildes-pairing-setup/”>See this article for some pointers on that topic</a>.
I do want to address a couple things that I ran into running vim in tmux.
For some reason that I don’t understand, yanking or deleting text in vim and then trying to paste that text back in wasn’t working. We kept getting a message that the pastebin was empty. A little Googling found that we needed to remove this line in .vimrc:
set clipboard=unnamed
This was originally in place so that vim would put yanked/deleted text in the OSX clipboard.
The other problem I found was that syntax highlighting was not working when running console vim under tmux. Back to the Googles! Where I found lots of references to the terminal being set incorrectly. I messed around a great deal with my shell environment without success. And finally concluded that my .tmux.conf file is where this needed to be set. So, in my .tmux.conf I have:
set -g default-terminal "screen-256color"
Syntax highlighting works like a champ now.
Refinements
To make this setup really work well, my pair partners and I are going to have to come up with a vim configuration we’re both comfortable with and stick to that. Just bouncing onto my machine and being thrown into my configuration was, I’m sure, not completely comfortable for my partner.
One issue that can keep this setup from working is not having control of you gateway router. If neither programmer in the pair can control the port mapping for their NATed internet connection, then what I’ve described above won’t work. I’m experimenting with setting up a Linux server on EC2 to allow both programmers to connect and work there — spinning the machine down after the coding session.
To that end, I just saw this on Remote Pair Programming: so far there’s just a video of the alpha from pario.io. It integrates with Github to make setting up pairing environments easy. I am looking forward to trying it out when it hits beta.