I need a flipchart or a whiteboard while teaching, but during online sessions I resort to using a terminal and a text editor and quickly got tired of having to swap sharing different windows in Zoom, Big Blue Button, & co. (I share individual windows, not the whole screen.) I share a window of a Web browser with my presentation in one tab and an open terminal using gotty in the second, and can flip between the two with CMD-1 / CMD-2.
I stumbled over gotty some years ago, and have used it to enable users to login to systems if they can’t SSH in (think corporate firewalls). It works well and is reliable. During the new setup I’m doing for training machines I need one gotty per user which is easily accomplished using distinct TCP port numbers. My first attempt in launching them was by templating out an rc.local
script, but I wanted something more elegant.
I recalled that systemd services can take an argument via the service@argument
syntax which fits in well with my user numbering, and after a bit of experimentation came up with a solution which works well.
[Unit]
Description=GoTTY Web Terminal %i
After=network.target
[Service]
User=user%i
Group=user%i
WorkingDirectory=/home/user%i
ExecStart=/usr/local/sbin/gotty -p 91%i tmux new-session -A -s user%i
[Install]
WantedBy=multi-user.target
The unit file’s WorkingDirectory
is needed or gotty starts in /
, and the tmux
invocation is to automatically start or attach to tmux in an SSH session. Users can SSH into the machine and/or use gotty and see the same screen. More importantly, I can, once given consent by a student, login and see their screen, help with error messages, give tips, etc.
Each user’s home directory has a ~/.gotty
preferences file containing
address = "127.0.0.1"
credential = "username:password"
title_format = "Ansible:username"
permit_write = true
preferences {
font_size = 20
background_color = "rgb(255, 255, 255)"
foreground_color = "rgb(0, 0, 0)"
}
The required number of gotty sessions are launched during setup of the machine with Ansible. (The sequence
lookup produces a list of numbers 00
, 01
, 02
based on the number of users I expect to welcome.)
- name: "Gotty: start gotty services"
systemd: name="gotty@{{ item }}" enabled=true state=started
with_sequence: '{{ nusers }}'
This is the resulting process list:
$ ps aux|grep g[o]tty
user01 1209 ... /usr/local/sbin/gotty -p 9101 tmux new-session -A -s user01
user00 1244 ... /usr/local/sbin/gotty -p 9100 tmux new-session -A -s user00
Each gotty listens on the loopback interface. A templated-out configuration lets a TLS-protected nginx reverse proxy talk to the gottys.
location /tty00/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
rewrite ^/tty00/?$ / break;
rewrite ^/tty00/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:9100;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
It’s only just now while writing this, that I realize GoTTY, which means “tty thing written in Go” actually reminds me of getty(8). :-)
Updates
-
There’s a newer and maintained version at https://github.com/sorenisanerd/gotty. The only way I can get it to understand my font/colour preferences is if I configure
term = "hterm"
, but that, precisely, is what this fork appears to be dropping in favor ofxterm
.