Upterm is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels.

Upterm

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

This is a blog post to describe Upterm in depth.

Usage

The host starts a terminal session:

$ upterm host -- bash

The host displays the ssh connection string:

$ 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:

$ ssh IqKsfoiclsNnxqztDKoj:[email protected]

Installation

Mac

brew install owenthereal/upterm/upterm

Standalone

upterm can be easily installed as an executable. Download the latest compiled binaries and put it in your executable path.

From source

git clone [email protected]:owenthereal/upterm.git
cd upterm
go install ./cmd/upterm/...

Upgrade

upterm comes with a command to upgrade

$ upterm upgrade # upgrade to the latest version

$ upterm upgrade VERSION # upgrade to a version

Mac

brew upgrade upterm

Quick Reference

# Host a terminal session that runs $SHELL with
# client's input/output attaching to the host's
$ upterm host

# Display the ssh connection string and share it with
# the client(s)
$ upterm session current
=== SESSION_ID
Command:                /bin/bash
Force Command:          n/a
Host:                   ssh://uptermd.upterm.dev:22
SSH Session:            ssh [email protected]

# A client connects to the host session with ssh
$ ssh [email protected]

# Host a terminal session that only allows specified client public key(s) to connect
$ upterm host --authorized-key PATH_TO_PUBLIC_KEY

# Host a session with a custom command
$ upterm host -- docker run --rm -ti ubuntu bash

# 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.
$ upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming

# Connect to uptermd.upterm.dev via WebSocket
$ upterm host --server wss://uptermd.upterm.dev -- bash

# A client connects to the host session via WebSocket
$ ssh -o ProxyCommand='upterm proxy wss://[email protected]' [email protected]:443

More advanced usage is here.

Tips

Why doesn't upterm session current show current session in Tmux?

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). So to get upterm session current to work, 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 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:

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

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 (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.

upterm flowchart

Deploy Uptermd

Kubernetes

You can deploy uptermd to a Kubernetes cluster. Install it with helm:

$ helm repo add upterm https://upterm.dev
$ helm repo update
$ helm search repo upterm
NAME            CHART VERSION   APP VERSION     DESCRIPTION
upterm/uptermd  0.1.0           0.4.1           Secure Terminal Sharing
$ helm install uptermd upterm/uptermd

Heroku

The cheapest way to deploy a worry-free Upterm server (a.k.a. uptermd) is to use Heroku. Heroku offers free Dyno hours which should be sufficient for most casual uses.

You can deploy with one click of the following button:

Deploy

You can also automate the deployment with Heroku Terraform. The Heroku Terraform scripts are in the terraform/heroku folder. A util script is provided for your convenience to automate everything:

$ git clone https://github.com/owenthereal/upterm
$ cd upterm

# Provinsion uptermd in Heroku Common Runtime.
# Follow instructions
$ bin/heroku-install

# Provinsion uptermd in Heroku Private Spaces.
# Follow instructions
$ 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
$ upterm host --server wss://YOUR_HEROKU_APP_URL -- YOUR_COMMAND

# A client connects to the host session via WebSocket
$ ssh -o ProxyCommand='upterm proxy wss://TOKEN@YOUR_HEROKU_APP_URL' TOKEN@YOUR_HEROKU_APP_URL:443

Digital Ocean

There is an util script that makes provinsioning Digital Ocean Kubernetes and an Upterm server easier:

TF_VAR_do_token=$DO_PAT \
TF_VAR_uptermd_host=uptermd.upterm.dev \
TF_VAR_uptermd_acme_email=YOUR_EMAIL \
TF_VAR_uptermd_helm_repo=http://localhost:8080 \
TF_VAR_uptermd_host_keys_dir=PATH_TO_HOST_KEYS \
bin/do-install

How is Upterm compared to prior arts?

Upterm is an alternative to Tmate.

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.

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.

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 in any cloud environment with zero dependencies.

License

Apache 2.0

Comments
  • Upterm rejecting all ssh connections

    Upterm rejecting all ssh connections

    I was trying to spin up my first upterm session; after running upterm host -- bash I am presented with the expected ssh session information, but when I attempt to connect to that session from another system, I get a "permission denied" error:

    [lars@madhatter ~]$ ssh hGjlbiMJqi0M9Jjo4SSo:[email protected]
    hGjlbiMJqi0M9Jjo4SSo:[email protected]: Permission denied (publickey).
    

    I haven't included any --authorized-key argument in my upterm host command so I expected any ssh client to be able to connect.

  • Heroku hosted server and permission denied

    Heroku hosted server and permission denied

    I've used your instructions to deploy to Heroku. I have the host running and the session current command is giving the appropriate ssh command pointing at the Heroku app. But when executed on the Mac to connect, I get a Permission denied (publickey). Here are the logs from the Heroku app:

    2021-11-03T22:58:24.656438+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=7c41e010-56d7-4381-938e-9febbf558f88 fwd="198.217.125.15" dyno=web.1 connect=0ms service=772ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:30.721907+00:00 app[web.1]: time="2021-11-03T22:58:30Z" level=info msg="dialing sshproxy session" addr="0.0.0.0:2222" app=uptermd com=ws-sshproxy-dialer network=mem network-opt="[]" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" sshproxy-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:31.052368+00:00 app[web.1]: time="2021-11-03T22:58:31Z" level=info msg="dialing session" addr="0.0.0.0:2222" app=uptermd com=ssh-conn-dialer network=mem network-opt="[]" node="0.0.0.0:2222" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:31.567653+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=62845bfc-7769-41bd-9f9a-55410f3de5cf fwd="198.217.125.15" dyno=web.1 connect=0ms service=845ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:31.567441+00:00 app[web.1]: time="2021-11-03T22:58:31Z" level=error msg="error piping" app=uptermd com=ws-proxy error="readfrom tcp 127.0.0.1:53424->127.0.0.1:2222: websocket: close 1006 (abnormal closure): unexpected EOF" network=mem network-opt="[]" node-addr="0.0.0.0:2222" ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.138609+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=info msg="dialing sshproxy session" addr="0.0.0.0:2222" app=uptermd com=ws-sshproxy-dialer network=mem network-opt="[]" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" sshproxy-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.460306+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=info msg="dialing session" addr="0.0.0.0:2222" app=uptermd com=ssh-conn-dialer network=mem network-opt="[]" node="0.0.0.0:2222" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.971328+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=f3603b62-d4be-4a48-9195-04b74629b484 fwd="198.217.125.15" dyno=web.1 connect=0ms service=832ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:49.971068+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=error msg="error piping" app=uptermd com=ws-proxy error="readfrom tcp 127.0.0.1:54220->127.0.0.1:2222: websocket: close 1006 (abnormal closure): unexpected EOF" network=mem network-opt="[]" node-addr="0.0.0.0:2222" ssh-addr="[::]:2222" ws-addr="[::]:36680"
    

    Any suggestions?

  • Private key required when ssh-agent already populated

    Private key required when ssh-agent already populated

    Hello, we are trying upterm as an alternative to tmate, and it's seems to be working great, so, first of all, thanks for this project!

    On my machine though, I don't have any private key files, they are stored in a safe (KeePassXC) and, when I unlock my safe, my key is added to my ssh-agent.

    My workaround for upterm is to create an ssh-key, but I wonder if we could have an option to specify an ssh-agent directly where it could retrieve the keys and the signers.

    If you agree with that, I could try and create a PR

  • Automatic authorized keys from github/gitlab

    Automatic authorized keys from github/gitlab

    I would like to simplify something like upterm host --authorized-key <(curl https://github.com/rothgar.keys)

    It would be great if this can be a single option like --github-user rothgar. If we want to make it more flexible maybe it could be something like --git-user rothgar@github which would automatically fetch https://github.com/rothgar.keys. This could limit the amount of flags and still make it pluggable for things like jgarr@gitlab

  • Can't connect: Permission denied (publickey)

    Can't connect: Permission denied (publickey)

    Hi ! I've tried replacing tmate with upterm today, and I've faced an issue, when I try to connect to the remote machine, I get a public key denied (but I didn't make a private key ?) The objective is to quickly connect from one machine to the other to help a friend with some stuff, on the remote machine, I just do upterm host -- <some shell here> then press q on the other machine, here are the logs with ssh -vvv

    $ ~> ssh -vvv yK11b5BHuYSCIaRD5hRk:[email protected]
    OpenSSH_8.8p1, OpenSSL 1.1.1m  14 Dec 2021
    debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> '/home/byjumperx4/.ssh/known_hosts'
    debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> '/home/byjumperx4/.ssh/known_hosts2'
    debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling
    debug2: resolving "uptermd.upterm.dev" port 22
    debug3: resolve_host: lookup uptermd.upterm.dev:22
    debug3: ssh_connect_direct: entering
    debug1: Connecting to uptermd.upterm.dev [157.230.199.75] port 22.
    debug3: set_sock_tos: set socket 3 IP_TOS 0x48
    debug1: Connection established.
    debug1: identity file /home/byjumperx4/.ssh/id_rsa type 0
    debug1: identity file /home/byjumperx4/.ssh/id_rsa-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_dsa type -1
    debug1: identity file /home/byjumperx4/.ssh/id_dsa-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ecdsa type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ecdsa-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ecdsa_sk type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ecdsa_sk-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ed25519 type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ed25519-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ed25519_sk type -1
    debug1: identity file /home/byjumperx4/.ssh/id_ed25519_sk-cert type -1
    debug1: identity file /home/byjumperx4/.ssh/id_xmss type -1
    debug1: identity file /home/byjumperx4/.ssh/id_xmss-cert type -1
    debug1: Local version string SSH-2.0-OpenSSH_8.8
    debug1: Remote protocol version 2.0, remote software version uptermd
    debug1: compat_banner: no match: uptermd
    debug2: fd 3 setting O_NONBLOCK
    debug1: Authenticating to uptermd.upterm.dev:22 as 'yK11b5BHuYSCIaRD5hRk:MTAuMjQ0LjAuNjU6MjI='
    debug3: record_hostkey: found ca key type ED25519 in file /home/byjumperx4/.ssh/known_hosts:1
    debug3: load_hostkeys_file: loaded 1 keys from uptermd.upterm.dev
    debug1: load_hostkeys: fopen /home/byjumperx4/.ssh/known_hosts2: No such file or directory
    debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
    debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
    debug3: order_hostkeyalgs: prefer hostkeyalgs: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected]
    debug3: send packet: type 20
    debug1: SSH2_MSG_KEXINIT sent
    debug3: receive packet: type 20
    debug1: SSH2_MSG_KEXINIT received
    debug2: local client KEXINIT proposal
    debug2: KEX algorithms: curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,ext-info-c
    debug2: host key algorithms: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,[email protected],[email protected],rsa-sha2-512,rsa-sha2-256
    debug2: ciphers ctos: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
    debug2: ciphers stoc: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
    debug2: MACs ctos: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
    debug2: MACs stoc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
    debug2: compression ctos: none,[email protected],zlib
    debug2: compression stoc: none,[email protected],zlib
    debug2: languages ctos: 
    debug2: languages stoc: 
    debug2: first_kex_follows 0 
    debug2: reserved 0 
    debug2: peer server KEXINIT proposal
    debug2: KEX algorithms: [email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1
    debug2: host key algorithms: [email protected]
    debug2: ciphers ctos: [email protected],[email protected],aes128-ctr,aes192-ctr,aes256-ctr
    debug2: ciphers stoc: [email protected],[email protected],aes128-ctr,aes192-ctr,aes256-ctr
    debug2: MACs ctos: [email protected],hmac-sha2-256,hmac-sha1,hmac-sha1-96
    debug2: MACs stoc: [email protected],hmac-sha2-256,hmac-sha1,hmac-sha1-96
    debug2: compression ctos: none
    debug2: compression stoc: none
    debug2: languages ctos: 
    debug2: languages stoc: 
    debug2: first_kex_follows 0 
    debug2: reserved 0 
    debug1: kex: algorithm: [email protected]
    debug1: kex: host key algorithm: [email protected]
    debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
    debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none
    debug3: send packet: type 30
    debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
    debug3: receive packet: type 31
    debug1: SSH2_MSG_KEX_ECDH_REPLY received
    debug1: Server host certificate: [email protected] SHA256:9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE, serial 0 ID "uptermd" CA ssh-ed25519 SHA256:9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE valid forever
    debug2: Server host certificate hostname: uptermd.upterm.dev
    debug3: record_hostkey: found ca key type ED25519 in file /home/byjumperx4/.ssh/known_hosts:1
    debug3: load_hostkeys_file: loaded 1 keys from uptermd.upterm.dev
    debug1: load_hostkeys: fopen /home/byjumperx4/.ssh/known_hosts2: No such file or directory
    debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
    debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
    debug1: Host 'uptermd.upterm.dev' is known and matches the ED25519-CERT host certificate.
    debug1: Found CA key in /home/byjumperx4/.ssh/known_hosts:1
    debug3: check_host_key: certificate host key in use; disabling UpdateHostkeys
    debug3: send packet: type 21
    debug2: set_newkeys: mode 1
    debug1: rekey out after 134217728 blocks
    debug1: SSH2_MSG_NEWKEYS sent
    debug1: expecting SSH2_MSG_NEWKEYS
    debug3: receive packet: type 21
    debug1: SSH2_MSG_NEWKEYS received
    debug2: set_newkeys: mode 0
    debug1: rekey in after 134217728 blocks
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_rsa RSA SHA256:5zhaqED4v7LBmJ7KfXk+AZiuLUEPvGZNYgLlROgzcL8
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_dsa 
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_ecdsa 
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_ecdsa_sk 
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_ed25519 
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_ed25519_sk 
    debug1: Will attempt key: /home/byjumperx4/.ssh/id_xmss 
    debug2: pubkey_prepare: done
    debug3: send packet: type 5
    debug3: receive packet: type 6
    debug2: service_accept: ssh-userauth
    debug1: SSH2_MSG_SERVICE_ACCEPT received
    debug3: send packet: type 50
    debug3: receive packet: type 51
    debug1: Authentications that can continue: publickey
    debug3: start over, passed a different list publickey
    debug3: preferred publickey,keyboard-interactive,password
    debug3: authmethod_lookup publickey
    debug3: remaining preferred: keyboard-interactive,password
    debug3: authmethod_is_enabled publickey
    debug1: Next authentication method: publickey
    debug1: Offering public key: /home/byjumperx4/.ssh/id_rsa RSA SHA256:5zhaqED4v7LBmJ7KfXk+AZiuLUEPvGZNYgLlROgzcL8
    debug1: send_pubkey_test: no mutual signature algorithm
    debug1: Trying private key: /home/byjumperx4/.ssh/id_dsa
    debug3: no such identity: /home/byjumperx4/.ssh/id_dsa: No such file or directory
    debug1: Trying private key: /home/byjumperx4/.ssh/id_ecdsa
    debug3: no such identity: /home/byjumperx4/.ssh/id_ecdsa: No such file or directory
    debug1: Trying private key: /home/byjumperx4/.ssh/id_ecdsa_sk
    debug3: no such identity: /home/byjumperx4/.ssh/id_ecdsa_sk: No such file or directory
    debug1: Trying private key: /home/byjumperx4/.ssh/id_ed25519
    debug3: no such identity: /home/byjumperx4/.ssh/id_ed25519: No such file or directory
    debug1: Trying private key: /home/byjumperx4/.ssh/id_ed25519_sk
    debug3: no such identity: /home/byjumperx4/.ssh/id_ed25519_sk: No such file or directory
    debug1: Trying private key: /home/byjumperx4/.ssh/id_xmss
    debug3: no such identity: /home/byjumperx4/.ssh/id_xmss: No such file or directory
    debug2: we did not send a packet, disable method
    debug1: No more authentication methods to try.
    yK11b5BHuYSCIaRD5hRk:[email protected]: Permission denied (publickey).
    $ ~>
    
  • Cannot build in Windows inside MINGW32 bash session

    Cannot build in Windows inside MINGW32 bash session

    Hello!

    I'm unable to build from sources for Windows running inside a bash session of Mingw32:

    $ go build ./cmd/upterm/...
    # github.com/jingweno/upterm/host/internal
    host\internal\command.go:86:21: undefined: syscall.SIGWINCH
    host\internal\command.go:87:9: undefined: syscall.SIGWINCH
    host\internal\pty.go:13:12: undefined: pty.Start
    host\internal\pty.go:33:9: undefined: pty.Getsize
    host\internal\pty.go:54:11: undefined: pty.Winsize
    host\internal\pty.go:58:9: undefined: pty.Setsize
    ```
  • Remove session confirmation

    Remove session confirmation

    Remove session confirmation to simplify the workflow. The original thought is to ask the users for confirmation that the session is about to allow remote clients to connect. But it seems users will always press to continue anyways.

    This fixes https://github.com/owenthereal/upterm/issues/120

  • Add --github-user and --gitlab-user flags

    Add --github-user and --gitlab-user flags

    This adds new flags to use a GitHub/GitLab's user public keys as authorized keys. The keys are downloaded, processed and added to any existing authorized keys provided by the --authorized-key flag.

    This fixes #72.

  • Can't connect. Connection closed.

    Can't connect. Connection closed.

    Version: Upterm version v0.7.3

    Terminal 1:

    ➜  ~ upterm host
    Enter passphrase for key '/home/langit/.ssh/id_ed25519': 
    === RU3JOU8EBSCQRSH53NCW                                                                 
    Command:                /bin/fish                                                       
    Force Command:          n/a                                                             
    Host:                   ssh://uptermd.upterm.dev:22                                     
    SSH Session:            ssh rU3jou8ebSCQRsh53ncw:[email protected]
    Press <q> or <ctrl-c> to continue...
    

    Terminal 2: (one minutes later)

    ➜  ~ ssh rU3jou8ebSCQRsh53ncw:[email protected]
    Connection closed by 157.230.199.75 port 22
    
  • "upterm upgrade" fails with "no binary for your system"

    I'm running upterm (v0.6.7) locally, and trying to run upterm upgrade results in:

    Error: no binary for your system
    Usage:
      upterm upgrade [flags]
    
    Examples:
      # Upgrade to the latest version
      upterm upgrade
    
      # Upgrade to a specific version
      $ upterm upgrade 0.2.0
    
    Flags:
      -h, --help   help for upgrade
    
    FATA[0000] no binary for your system
    

    That's an odd error (it's just a regular amd64 system), and the error message doesn't really provide enough information to be actionable.

  • QUESTION: Use with Visual Studio Code possible?

    QUESTION: Use with Visual Studio Code possible?

    The Question

    I am an avid terminal user, Neovim, tmux, and all the like so Upterm is amazing for me. However, some of my co-workers and friends do not live inside the terminal and use GUI IDE's such as Visual Studio Code. Is there a way use VSCode's Remote Development -SSH extension to connect to Upterm's SSH Server and be able to view with me as I work?

    Current Error Output

    [12:54:26.383] Log Level: 2
    [12:54:26.386] [email protected]
    [12:54:26.386] linux x64
    [12:54:26.387] SSH Resolver called for "ssh-remote+uptermd.upterm.dev", attempt 1
    [12:54:26.388] "remote.SSH.useLocalServer": true
    [12:54:26.388] "remote.SSH.path": undefined
    [12:54:26.388] "remote.SSH.configFile": undefined
    [12:54:26.388] "remote.SSH.useFlock": true
    [12:54:26.389] "remote.SSH.lockfilesInTmp": false
    [12:54:26.389] "remote.SSH.localServerDownload": auto
    [12:54:26.389] "remote.SSH.remoteServerListenOnSocket": false
    [12:54:26.389] "remote.SSH.showLoginTerminal": false
    [12:54:26.389] "remote.SSH.defaultExtensions": []
    [12:54:26.390] "remote.SSH.loglevel": 2
    [12:54:26.390] SSH Resolver called for host: uptermd.upterm.dev
    [12:54:26.390] Setting up SSH remote "uptermd.upterm.dev"
    [12:54:26.395] Acquiring local install lock: /tmp/vscode-remote-ssh-48a5ecb6-install.lock
    [12:54:26.430] Looking for existing server data file at /var/home/dudleyp/.var/app/com.visualstudio.code/config/Code/User/globalStorage/ms-vscode-remote.remote-ssh/vscode-ssh-host-48a5ecb6-507ce72a4466fbb27b715c3722558bb15afa9f48-0.65.8/data.json
    [12:54:26.431] Using commit id "507ce72a4466fbb27b715c3722558bb15afa9f48" and quality "stable" for server
    [12:54:26.439] Install and start server if needed
    [12:54:26.476] PATH: /app/bin:/usr/bin:/app/tools/podman/bin:/usr/lib/sdk/golang/bin:/var/home/dudleyp/.var/app/com.visualstudio.code/data/node_modules/bin
    [12:54:26.476] Checking ssh with "ssh -V"
    [12:54:26.485] > OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    
    [12:54:26.490] askpass server listening on /run/user/1000/vscode-ssh-askpass-59f8107e5f8a89dfd1a5728c561edb170e91f293.sock
    [12:54:26.490] Spawning local server with {"serverId":1,"ipcHandlePath":"/run/user/1000/vscode-ssh-askpass-a68ca513540bb777882508442662771abd6fea3c.sock","sshCommand":"ssh","sshArgs":["-v","-T","-D","42591","-o","ConnectTimeout=15","uptermd.upterm.dev"],"dataFilePath":"/var/home/dudleyp/.var/app/com.visualstudio.code/config/Code/User/globalStorage/ms-vscode-remote.remote-ssh/vscode-ssh-host-48a5ecb6-507ce72a4466fbb27b715c3722558bb15afa9f48-0.65.8/data.json"}
    [12:54:26.490] Local server env: {"DISPLAY":":99.0","ELECTRON_RUN_AS_NODE":"1","SSH_ASKPASS":"/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/local-server/askpass.sh","VSCODE_SSH_ASKPASS_NODE":"/app/extra/vscode/code","VSCODE_SSH_ASKPASS_MAIN":"/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/askpass-main.js","VSCODE_SSH_ASKPASS_HANDLE":"/run/user/1000/vscode-ssh-askpass-59f8107e5f8a89dfd1a5728c561edb170e91f293.sock"}
    [12:54:26.497] Spawned 315
    [12:54:26.641] > local-server-1> Spawned ssh, pid=323
    [12:54:26.643] stderr> OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    [12:54:26.971] stderr> Connection closed by 157.230.199.75 port 22
    [12:54:26.974] > local-server-1> ssh child died, shutting down
    [12:54:26.980] Local server exit: 0
    [12:54:26.980] Received install output: local-server-1> Spawned ssh, pid=323
    OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    Connection closed by 157.230.199.75 port 22
    local-server-1> ssh child died, shutting down
    
    [12:54:26.982] Failed to parse remote port from server output
    [12:54:26.983] Resolver error: Error: 
    	at Function.Create (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:397041)
    	at Object.t.handleInstallOutput (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:395684)
    	at Object.e [as tryInstallWithLocalServer] (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:435292)
    	at processTicksAndRejections (internal/process/task_queues.js:93:5)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:452665
    	at async Object.t.withShowDetailsEvent (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:456460)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:433816
    	at async C (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:430392)
    	at async Object.t.resolveWithLocalServer (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:433431)
    	at async Object.t.resolve (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:454065)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:526942
    [12:54:26.990] ------
    

    I do know that there is already a "co-editing" experience called Live Share for Visual Studio and VSCode, but I was having issues with it reverting changes we had made, and syncing improperly.

  • Client sessions change dimensions of host terminal.

    Client sessions change dimensions of host terminal.

    Hi, thank you for the great project.

    I noticed that client sessions, including read-only sessions, affect dimensions of host terminal. (https://github.com/owenthereal/upterm/blob/master/host/internal/server.go#L253) In my case it shouldn't be like that but I wonder if it's something that's expected by other use cases. (e.g. tmux based sessions).

  • Question: upterm token and ports

    Question: upterm token and ports

    Hello!

    How does upterm achieve forwarding of encrypted traffic of multiple users on the same port?

    It seems the token would be needed to determine where to forward traffic to but the proxy could not get to that if ssh connection were end-to-end encrypted. The diagram shows two tunnels however does not explain port and purpose.

    Is an upterm session comprised of 2 consecutive SSH sessions with data decrypted and reencrypted at the proxy?

  • Invalid entry added to known hosts

    Invalid entry added to known hosts

    After running upterm an invalid entry is added to the known_hosts file. Attempting to run upterm later results in the following error:

    FATA[0000] knownhosts: /Users/daniel/.ssh/known_hosts:4: address [2a09:8280:1::3:4b89]: missing port in address
    

    OS: Darwin 21.6.0 Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:22 PDT 2022; root:xnu-8020.140.41~1/RELEASE_ARM64_T6000 arm64 Upterm: Upterm version v0.9.0 Removing the entry enables you to run upterm again. Manually adding port 22 to the address resolves the issue.

  • Packet loss causing upterm to crash?

    Packet loss causing upterm to crash?

    Hi,

    We use Upterm + tmux almost every day to pair but lately I've been experiencing quite a bit of unexpected disconnects. We have a theory that it may be coinciding with temporary moments of high packet loss, but are not entirely sure. Usually the session completely dies when this happens and I have to issue a new SSH upterm connection to my pair.

    Do you have any recommendations for how to debug this?

  • `upterm host` should reject any unauthenticated users when `--authorized-key`, `--github-user` or `--gitlab-user` option is present

    `upterm host` should reject any unauthenticated users when `--authorized-key`, `--github-user` or `--gitlab-user` option is present

    Problem: I ran into an issue where I had a passed an empty file to --authorized-key option for the upterm host command.

    Steps to reproduce

    1. Start a new upterm host session in a docker container:
    # start a new ubuntu docker container
    docker run --rm -it ubuntu:20.04 bash
    
    # in the container run these commands to start upterm
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends curl openssh-client ca-certificates
    curl -sL https://github.com/owenthereal/upterm/releases/download/v0.7.6/upterm_linux_amd64.tar.gz | \
      tar zxvf - -C /tmp upterm && \
      install /tmp/upterm /usr/local/bin/ && rm -rf /tmp/upterm
    mkdir -p ~/.ssh && chmod 0700 ~/.ssh
    ssh-keygen -q -t ed25519 -N "" -f ~/.ssh/id_ed25519
    # Auto-generate ~/.ssh/known_hosts by attempting connection to uptermd.upterm.dev
    ssh -i ~/.ssh/id_ed25519 -o 'StrictHostKeyChecking no' uptermd.upterm.dev
    cat <(cat ~/.ssh/known_hosts | awk '{ print "@cert-authority * " $2 " " $3 }' | sort | uniq) >> ~/.ssh/known_hosts
    touch ~/.ssh/authorized_keys
    upterm host -a $HOME/.ssh/authorized_keys -- bash
    
    1. Use the SSH session string in another terminal. The client connects to the upterm session. This is unexpected since -a $HOME/.ssh/authorized_keys is passed to upterm host.

    Expected behavior

    upterm host should reject any unauthenticated users when --authorized-key, --github-user or --gitlab-user option is present. An empty authorized keys file shouldn't be an exception.

Simple CLI tool for creating gotd sessions.

Simple CLI tool for creating gotd sessions.

Sep 29, 2022
Terminal chat with multiroom support over custom protocol.

Terminal Chat Content Content Overview Download Commands Protocol Room URL Platforms Examples Overview It is a multiroom terminal chat. It allows comm

Sep 3, 2022
Terminal based wordle clone. Uses the amazing charm.sh libraries to render and expose the game over SSH

Terminal based wordle clone. Uses the amazing charm.sh libraries to render and expose the game over SSH

Nov 17, 2022
Song lyrics in your terminal via Genius
Song lyrics in your terminal via Genius

lyric Song lyrics in your terminal via the Genius API. Usage Search by song name, artist, parts of lyrics, or a combination. lyric "bohemian rhapsody"

Nov 9, 2022
CLI for Shamir's Secret Sharing and AES key generation, encryption, and decryption.
CLI for Shamir's Secret Sharing and AES key generation, encryption, and decryption.

Shush ?? This simple program will help you run Shamir's Secret Sharing algorithm on any file using the split and merge commands.

Feb 1, 2022
A personal knowledge management and sharing system for VSCode
A personal knowledge management and sharing system for VSCode

Foam ?? This is an early stage project under rapid development. For updates join the Foam community Discord! ?? Foam is a personal knowledge managemen

Jan 9, 2023
VSCode Remote-SSH and configuration sharing on WSL.

Wslssh Wslssh forwards SSH command from VSCode Remote-SSH to WSL and enables SSH configuration sharing. Quick Start Guide Download or compile wslssh a

Dec 2, 2021
Clipsync: a high performance clipboard sharing application for linux

clipsync: Clipboard sync Clipsync is a high performance clipboard sharing applic

Sep 18, 2022
Gowget - A simple wget tool built using golang to download files from the internet whether it is zip

gowget wget built using golang About: A simple wget tool built using golang to d

May 21, 2022
Speedtest - Simple package to measure internet speed

Speedtest Simple package to measure internet speed Provides a simple API to meas

Oct 12, 2022
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.

Stonks is a terminal based stock visualizer and tracker. Installation Requirements: golang >= 1.13 Manual Clone the repo Run make && make install Pack

Dec 16, 2022
A wrapper around cd and xdg-open to use aliases to directory paths in terminal

CDD - Change directories Dynamically I am a lazy linux user and turns out that basic tab completion wasn't enough for me to navigate through my direct

Dec 15, 2022
Go terminal app listing open pull requests in chosen GitHub repositories
Go terminal app listing open pull requests in chosen GitHub repositories

go-pr-watcher About Shows open pull requests on configured GitHub repositories. Getting started Create GitHub personal token with read permissions Cre

Aug 23, 2022
Downloader written in golang to download the public data files from RUC Paraguay.

rucpy-downloader Downloader written in golang to download the public data files(RUC Paraguay) from set.gov.py. The downloader will download the public

Dec 6, 2021
Mass download all github repositories(public & private) of an organization, ideally in a few seconds.

Git Mass Mass download all github repositories(public & private) of an organization, ideally in a few seconds. Writing this as a simple bash script wo

Dec 27, 2021
A repo for making my first public golang moduel.

demoMod My first public Golang moduel Packages Two very simple packages. First is converter that converts the NOK - USD or BP. Using the current excha

Jan 11, 2022
cli tools for list all pages in logseq repo, marked with public or private

logseq-pages A cli tool for list all pages in logseq repo, marked with public or private. When I using logseq to build my knowledge base and publish p

Dec 12, 2022
🚀 Platform providing a powerful and fast public script parsing API dedicated to the Skript community.

SkriptMC-Parser is currently a prototype in the early stages of development of a system that allows the Skript community to test their scripts via a public API for potential errors or warnings. This is a quick and easy way to check your scripts without having to set up a Spigot server on your environment.

Mar 3, 2022
Source code of a YouTube tutorial about writing terminal applications with Golang

Bubble Tea Demo 00 Source code of a YouTube tutorial about writing terminal applications with Golang by using Bubble Tea. Contains a simple counter ap

Nov 10, 2022