Upterm - Secure Terminal Sharing
Tags: go, terminal, pairprogramming, cli
Published: 2020-07-13 17:40:02

[Upterm](https://github.com/jingweno/upterm) is an open-sourced solution for sharing terminal sessions instantly over the public internet via SSH tunnels.
It is good for

* Remote pair programming
* Access remote computers behind NATs and firewalls
* Remote debugging

Upterm is written in Go and is open-sourced at [https://github.com/jingweno/upterm](https://github.com/jingweno/upterm).

## How it works

You run the `upterm` program by hosting a terminal session.
Upterm starts an SSH server on your machine and connects to an Upterm server (a.k.a. uptermd) via reverse SSH tunnel.
Your friends connect to your terminal session using ssh via the same Upterm server.

Here is a diagram on the technical details:

![diagram](https://raw.githubusercontent.com/jingweno/upterm/gh-pages/upterm-flowchart.svg?sanitize=true)

## Demo

[![asciicast](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7.svg)](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7)

## Quickstart

Install `upterm` by following [this guide](https://github.com/jingweno/upterm#installation).

On your machine, host a terminal session by specifying a command:

```
$ upterm host -- bash
```

`upterm` will start the command and pop up an ssh connection string that one can connect.
In case you miss the connection string, display it with:

```
$ upterm session current
=== IQKSFOICLSNNXQZTDKOJ
Command:                bash
Force Command:          n/a
Host:                   ssh://uptermd.upterm.dev:22
SSH Session:            ssh IqKsfoiclsNnxqztDKoj:MTAuMC40OS4xNjY6MjI=@uptermd.upterm.dev
```

Open a new terminal and connect to the session:

```
$ ssh IqKsfoiclsNnxqztDKoj:MTAuMC40OS4xNjY6MjI=@uptermd.upterm.dev
```

You should see the input and output of both terminals are linked!

If you want only authorized clients to connect to your session, you can specify the clients' authorized keys with

```
$ upterm host --authorized-key PATH_TO_PUBLIC_KEY -- bash
```

If you are looking for a [Tmate](https://tmate.io)-like experience, create a [Tmux](https://github.com/tmux/tmux) session, and "force" clients to attach to the Tmux session:

```
$ upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming
```

The above creates a Tmux session by running `tmux new -t pair-programming`.
After a client connects, Upterm will attach the client's input and output to the input and output of the Tmux session "pair-programming".

If you are concerned with others accessing your root file system, wrap the terminal session in a Docker container:

```
$ upterm host -- docker run --rm -ti ubuntu bash
```

I will write another blog post in the future to share how I securely host a terminal session using containers.

## How is Upterm compared to prior arts?

Upterm is an alternative to [Tmate](https://tmate.io).

Tmate is a fork of an older version of Tmux. It adds terminal sharing capability on top of Tmux 2.x.
Tmate doesn't intend to catch up with the latest Tmux (at this time of the post, the latest Tmux is 3.x), so any Tmate & Tmux users must maintain two versions of the configuration.
For example, you must [bind the same keys twice with a condition](https://github.com/tmate-io/tmate/issues/108).

Upterm is designed from the group up not to be a fork of anything.
It builds around the concept of linking the input & output of any shell command between a host and its clients.
As you see above, you can share any command besides `tmux`.
This opens up a door for securely sharing a terminal session using containers (I will explain more in a future post).

Upterm is written in Go.
It is more friendly hackable than Tmate that is written in C because Tmux is C.
The Upterm CLI and server (`uptermd`) are compiled into a single binary.
You can quickly [spawn up your pairing server](https://github.com/jingweno/upterm#deploy-uptermd) in any cloud environment with zero dependencies.

## Tips

### Why doesn't upterm show the current terminal session in Tmux?

`upterm session current` shows the connection info of the current terminal session.
It needs the `UPTERM_ADMIN_SOCKET` environment variable to function.
By default, Tmux doesn't carry over environment variables that are not in its [default list](http://man.openbsd.org/i386/tmux.1#GLOBAL_AND_SESSION_ENVIRONMENT) to a Tmux session unless you tell it.
So add the following line to your `~/.tmux.conf`

```
set-option -ga update-environment " UPTERM_ADMIN_SOCKET"
```

### How to make it obvious that I am in an upterm session?

It can be confusing whether your terminal session is an upterm session or not.
As an example, I add an emoji to my prompt to identify an upterm session:

```bash
# in your ~/.bashrc or ~/.zshrc 
export PS1="$([[ ! -z "${UPTERM_ADMIN_SOCKET}"  ]] && echo -e '\xF0\x9F\x86\x99 ')$PS1" # Add an emoji
```

This is what it looks like :-):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/37atfmpmzk0ci8erjbhm.png)

## Deploy Uptermd

Upterm needs an Upterm server (a.k.a. `uptermd`) to expose terminal sessions securely.
There is a community server running at `uptermd.upterm.dev` for your convenience (please put it into good use!).
However, if you want to host your pairing server on [Kubernetes](https://kubernetes.io/) or [Heroku](https://heroku.com), follow [this deployment guide](https://github.com/jingweno/upterm#how-it-works).
You are welcome to contribute one for your favorite cloud platforms.
I am pleased to review it if you shoot me a [PR](https://github.com/jingweno/upterm/pulls) :-).

To talk to a different uptermd server other than the community server, you specify with the `--server` flag:

```
# Use your Uptermd server via SSH on TCP
$ upterm host --server ssh://YOUR_SERVER -- YOUR_COMMAND

# Use your Uptermd server via SSH on WebSocket
$ upterm host --server wss://YOUR_SERVER -- YOUR_COMMAND

# Client connects to the host session via SSH on WebSocket
$ ssh -o ProxyCommand='upterm proxy wss://TOKEN@YOUR_SERVER' TOKEN@YOUR_SERVER:443
```

## Conclusion

I am super excited about `upterm`, and I dogfood it daily to pair program with my coworkers (Disclaimer: I work remotely for Heroku).
If you like what you see here, give upterm a shot.
I am looking forward to your valuable feedback and contributions: [https://github.com/jingweno/upterm/issues](https://github.com/jingweno/upterm/issues) :-). 

---

Originally published at [https://owenou.com](https://owenou.com/upterm/) on July 11, 2020.