-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9504252
commit 5036c68
Showing
1 changed file
with
76 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,21 @@ | ||
# Upterm | ||
# Upterm: Instant Terminal Sharing | ||
|
||
[Upterm](https://github.com/owenthereal/upterm) is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels. | ||
Upterm is good for | ||
|
||
* Remote pair programming | ||
* Access remote computers behind NATs and firewalls | ||
* Remote debugging | ||
* \<insert your creative use cases\> | ||
[Upterm](https://github.com/owenthereal/upterm) is an open-source tool enabling developers to share terminal sessions securely over the web. It’s perfect for remote pair programming, accessing computers behind NATs/firewalls, remote debugging, and more. | ||
|
||
This is a [blog post](https://owenou.com/upterm) to describe Upterm in depth. | ||
|
||
## Usage | ||
|
||
The host starts a terminal session: | ||
|
||
```console | ||
$ upterm host -- bash | ||
``` | ||
|
||
The host displays the ssh connection string: | ||
## :movie_camera: Quick Demo | ||
|
||
```console | ||
$ upterm session current | ||
=== IQKSFOICLSNNXQZTDKOJ | ||
Command: bash | ||
Force Command: n/a | ||
Host: ssh://uptermd.upterm.dev:22 | ||
SSH Session: ssh IqKsfoiclsNnxqztDKoj:[email protected] | ||
``` | ||
|
||
The client opens a terminal and connects to the host's session: | ||
[![asciicast](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7.svg)](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7) | ||
|
||
```console | ||
$ ssh IqKsfoiclsNnxqztDKoj:[email protected] | ||
``` | ||
## :rocket: Getting Started | ||
|
||
## Installation | ||
|
||
### Mac | ||
|
||
```console | ||
$ brew install owenthereal/upterm/upterm | ||
brew install owenthereal/upterm/upterm | ||
``` | ||
|
||
### Standalone | ||
|
@@ -50,135 +25,115 @@ $ brew install owenthereal/upterm/upterm | |
### From source | ||
|
||
```console | ||
$ git clone [email protected]:owenthereal/upterm.git | ||
$ cd upterm | ||
$ go install ./cmd/upterm/... | ||
git clone [email protected]:owenthereal/upterm.git | ||
cd upterm | ||
go install ./cmd/upterm/... | ||
``` | ||
|
||
## Upgrade | ||
## :wrench: Basic Usage | ||
|
||
`upterm` comes with a command to upgrade | ||
1. Host starts a terminal session: | ||
|
||
Upgrade to the latest version | ||
```console | ||
$ upterm upgrade | ||
upterm host | ||
``` | ||
|
||
Upgrade to a specific version | ||
2. Host retrieves and shares the SSH connection string: | ||
|
||
```console | ||
$ upterm upgrade VERSION | ||
upterm session current | ||
``` | ||
|
||
### Mac | ||
3. Client connects using the shared string: | ||
|
||
```console | ||
$ brew upgrade upterm | ||
ssh TOKEN@uptermd.upterm.dev | ||
``` | ||
|
||
## Quick Reference | ||
## :blue_book: Quick Reference | ||
|
||
Host a terminal session that runs `$SHELL` with client's input/output attaching to the host's | ||
```console | ||
$ upterm host | ||
``` | ||
Dive into more commands and advanced usage in the [documentation](docs/upterm.md). | ||
Below are some notable highlights: | ||
|
||
Display the ssh connection string and share it with the client(s) | ||
```console | ||
$ upterm session current | ||
=== SESSION_ID | ||
Command: /bin/bash | ||
Force Command: n/a | ||
Host: ssh://uptermd.upterm.dev:22 | ||
SSH Session: ssh [email protected] | ||
``` | ||
### Command Execution | ||
|
||
A client connects to the host session with `ssh` | ||
```console | ||
$ ssh [email protected] | ||
``` | ||
Host a session with any desired command: | ||
|
||
Host a terminal session that only allows specified client public key(s) to connect | ||
```console | ||
$ upterm host --authorized-key PATH_TO_PUBLIC_KEY | ||
upterm host -- docker run --rm -ti ubuntu bash | ||
``` | ||
|
||
Host a terminal session that only allows specified GitHub user client public key(s) to connect. | ||
This is compatible with `--authorized-keys`. | ||
```console | ||
$ upterm host --github-user username | ||
``` | ||
### Access Control | ||
|
||
Host a terminal session that only allows specified GitLab user client public key(s) to connect. | ||
This is compatible with `--authorized-keys`. | ||
```console | ||
$ upterm host --gitlab-user username | ||
``` | ||
Host a session with specified client public key(s) authorized to connect: | ||
|
||
Host a terminal session that only allows specified SourceHut user client public key(s) to connect. | ||
This is compatible with `--authorized-keys`. | ||
```console | ||
$ upterm host --srht-user username | ||
upterm host --authorized-key PATH_TO_PUBLIC_KEY | ||
``` | ||
|
||
Host a session with a custom command | ||
Authorize specified GitHub, GitLab, or SourceHut users with their corresponding public keys: | ||
|
||
```console | ||
$ upterm host -- docker run --rm -ti ubuntu bash | ||
upterm host --github-user username | ||
upterm host --gitlab-user username | ||
upterm host --srht-user username | ||
``` | ||
|
||
Host a session that runs 'tmux new -t pair-programming' and force clients to join with `tmux attach -t pair-programming`. | ||
This is similar to what tmate offers. | ||
### Force command | ||
|
||
Host a session initiating `tmux new -t pair-programming`, while ensuring clients join with `tmux attach -t pair-programming`. | ||
This mirrors functionarity provided by tmate: | ||
|
||
```console | ||
$ upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming | ||
upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming | ||
``` | ||
|
||
Connect to uptermd.upterm.dev via WebSocket | ||
### WebSocket Connection | ||
|
||
In scenarios where your host restricts ssh transport, establish a connection to `uptermd.upterm.dev` (or your self-hosted server) via WebSocket: | ||
|
||
```console | ||
$ upterm host --server wss://uptermd.upterm.dev -- bash | ||
upterm host --server wss://uptermd.upterm.dev -- bash | ||
``` | ||
|
||
A client connects to the host session via WebSocket | ||
Clients can connect to the host session via WebSocket as well: | ||
|
||
```console | ||
$ ssh -o ProxyCommand='upterm proxy wss://[email protected]' [email protected]:443 | ||
ssh -o ProxyCommand='upterm proxy wss://[email protected]' [email protected]:443 | ||
``` | ||
|
||
More advanced usage is [here](https://github.com/owenthereal/upterm/blob/master/docs/upterm.md). | ||
## :bulb: Tips | ||
|
||
### Resolving Tmux Session Display Issue | ||
|
||
## Tips | ||
**Issue**: The command `upterm session current` does not display the current session when used within Tmux. | ||
|
||
**Why doesn't `upterm session current` show current session in Tmux?** | ||
**Cause**: This occurs because `upterm session current` requires the `UPTERM_ADMIN_SOCKET` environment variable, which is set in the specified command. Tmux, however, does not carry over environment variables not on its default list to any Tmux session unless instructed to do so ([Reference](http://man.openbsd.org/i386/tmux.1#GLOBAL_AND_SESSION_ENVIRONMENT)). | ||
|
||
`upterm session current` needs the `UPTERM_ADMIN_SOCKET` environment variable to function. | ||
And this env var is set in the specified command. | ||
Unfotunately, Tmux doesn't carry over environment variables that are not in its default list to any Tmux session unless you tell it to ([Ref](http://man.openbsd.org/i386/tmux.1#GLOBAL_AND_SESSION_ENVIRONMENT)). | ||
So to get `upterm session current` to work, add the following line to your `~/.tmux.conf` | ||
**Solution**: To rectify this, add the following line to your `~/.tmux.conf`: | ||
|
||
```conf | ||
set-option -ga update-environment " UPTERM_ADMIN_SOCKET" | ||
``` | ||
|
||
**How to make it obvious that I am in an upterm session?** | ||
### Identifying Upterm Session | ||
|
||
**Issue**: It might be unclear whether your shell command is running in an upterm session, especially with common shell commands like `bash` or `zsh`. | ||
|
||
It can be confusing whether your shell command is running in an upterm session or not, especially if the shell command is `bash` or `zsh`. | ||
Add the following line to your `~/.bashrc` or `~/.zshrc` and decorate your prompt to show a sign if the shell command is in a terminal session: | ||
**Solution**: To provide a clear indication, amend your `~/.bashrc` or `~/.zshrc` with the following line. This decorates your prompt with an emoji whenever the shell command is running in an upterm session: | ||
|
||
```bash | ||
export PS1="$([[ ! -z "${UPTERM_ADMIN_SOCKET}" ]] && echo -e '\xF0\x9F\x86\x99 ')$PS1" # Add an emoji to the prompt if `UPTERM_ADMIN_SOCKET` exists | ||
``` | ||
|
||
## Demo | ||
|
||
[![asciicast](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7.svg)](https://asciinema.org/a/LTwpMqvvV98eo3ueZHoifLHf7) | ||
|
||
## How it works | ||
## :gear: How it works | ||
|
||
You run the `upterm` program by specifying the command for your terminal session. | ||
Upterm starts an SSH server (a.k.a. `sshd`) in the host machine and sets up a reverse SSH tunnel to a [Upterm server](https://github.com/owenthereal/upterm/tree/master/cmd/uptermd) (a.k.a. `uptermd`). | ||
Clients connect to your terminal session over the public internet via `uptermd` using `ssh` using TCP or WebSocket. | ||
A community Upterm server is running at `uptermd.upterm.dev` and `upterm` points to this server by default. | ||
Clients connect to a terminal session over the public internet via `uptermd` using `ssh` or `ssh` over WebSocket. | ||
|
||
![upterm flowchart](https://raw.githubusercontent.com/owenthereal/upterm/gh-pages/upterm-flowchart.svg?sanitize=true) | ||
|
||
## Deploy Uptermd | ||
## :hammer_and_wrench: Deployment | ||
|
||
### Kubernetes | ||
|
||
|
@@ -207,31 +162,35 @@ The Heroku Terraform scripts are in the [terraform/heroku folder](./terraform/he | |
A [util script](./bin/heroku-install) is provided for your convenience to automate everything: | ||
|
||
```console | ||
$ git clone https://github.com/owenthereal/upterm | ||
$ cd upterm | ||
git clone https://github.com/owenthereal/upterm | ||
cd upterm | ||
``` | ||
|
||
Provision uptermd in Heroku Common Runtime. Follow instructions. | ||
|
||
```console | ||
$ bin/heroku-install | ||
bin/heroku-install | ||
``` | ||
|
||
Provision uptermd in Heroku Private Spaces. Follow instructions. | ||
|
||
```console | ||
$ TF_VAR_heroku_region=REGION TF_VAR_heroku_space=SPACE_NAME TF_VAR_heroku_team=TEAM_NAME bin/heroku-install | ||
TF_VAR_heroku_region=REGION TF_VAR_heroku_space=SPACE_NAME TF_VAR_heroku_team=TEAM_NAME bin/heroku-install | ||
``` | ||
|
||
You **must** use WebScoket as the protocol for a Heroku-deployed Uptermd server because the platform only support HTTP/HTTPS routing. | ||
This is how you host a session and join a session: | ||
|
||
Use the Heroku-deployed Uptermd server via WebSocket | ||
|
||
```console | ||
$ upterm host --server wss://YOUR_HEROKU_APP_URL -- YOUR_COMMAND | ||
upterm host --server wss://YOUR_HEROKU_APP_URL -- YOUR_COMMAND | ||
``` | ||
|
||
A client connects to the host session via WebSocket | ||
|
||
```console | ||
$ ssh -o ProxyCommand='upterm proxy wss://TOKEN@YOUR_HEROKU_APP_URL' TOKEN@YOUR_HEROKU_APP_URL:443 | ||
ssh -o ProxyCommand='upterm proxy wss://TOKEN@YOUR_HEROKU_APP_URL' TOKEN@YOUR_HEROKU_APP_URL:443 | ||
``` | ||
|
||
### Digital Ocean | ||
|
@@ -253,28 +212,20 @@ A hardened systemd service is provided in `systemd/uptermd.service`. You can use | |
secured `uptermd` on your machine: | ||
|
||
```console | ||
$ cp systemd/uptermd.service /etc/systemd/system/uptermd.service | ||
$ systemctl daemon-reload | ||
$ systemctl start uptermd | ||
cp systemd/uptermd.service /etc/systemd/system/uptermd.service | ||
systemctl daemon-reload | ||
systemctl start uptermd | ||
``` | ||
|
||
## How is Upterm compared to prior arts? | ||
## :balance_scale: Comparasion with Prior Arts | ||
|
||
Upterm is an alternative to [Tmate](https://tmate.io). | ||
Upterm stands as a modern 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, 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). | ||
Tmate originates as a fork from an older iteration of Tmux, extending terminal sharing capabilities atop Tmux 2.x. However, Tmate has no plans to align with the latest Tmux updates, compelling Tmate & Tmux users to manage two separate configurations. For instance, the necessity to [bind identical keys twice, conditionally](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. | ||
On the flip side, Upterm is architected from the ground up to be an independent solution, not a fork. It embodies the idea of connecting the input & output of any shell command between a host and its clients, transcending beyond merely `tmux`. This paves the way for securely sharing terminal sessions utilizing containers. | ||
|
||
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](#deploy-uptermd) in any cloud environment with zero dependencies. | ||
Written in Go, Upterm is more hack-friendly compared to Tmate, which is crafted in C, akin to Tmux. The seamless compilation of Upterm CLI and server (`uptermd`) into a single binary facilitates swift [deployment of your pairing server](#hammer_and_wrench-deployment) across any cloud environment, devoid of dependencies. | ||
|
||
## License | ||
|
||
|