Hosting fTelnet to access your BBS

While I much prefer native clients (or even terminal clients on retro PCs) for accessing a BBS, you can't argue that a web-based client is certainly more accessible and friendly to use, especially for people who may be less technically inclined.

So, as part of my ongoing setup of a BBS, I've also set up a website and local copy of the fTelnet client and required websocket proxy, and wanted to document the steps I went through to get here, as the documentation around some of this is either a bit incomplete or plain missing.

The first part is simply to make a web page with the embedded client, but thankfully that code is provided as part of the fTelnet release, as provided on GitHub, so all you need to do is clone that repo, and you've got a good starting point.

I had to make a couple of changes to how the script is being called, since I'm running my own proxy and you need to set where you're connecting to as well, so the script tags I'm using include a little bit of extra detail over the default options.

       <script src="ftelnet.norip.xfer.js" id="fTelnetScript"></script>
          <script>
             var Options = new fTelnetOptions();
             Options.BitsPerSecond = 57600;
             Options.Font = 'CP437';
             Options.Hostname = 'bbs.uncomfortable.business';
             Options.Port = 6423;
             Options.ProxyHostname = 'bbs.uncomfortable.business';
             Options.SendLocation = false;
             Options.SplashScreen = 'BIG STRING HERE';             
             var Client = new fTelnetClient('fTelnetContainer', Options);
          </script>

The main changes I made were to specify the ProxyHostname, since I'm hosing my own proxy, and adding the ANSI splash screen in the SplashScreen variable.

The splash screen option replaces the very very blue default splash screen with one of your choosing. You need to convert the ANSI file you're wanting to use into Base64 and then paste the resulting string into the field. There's lots of ways to do this, but I just uploaded the ANSI file to a website and got back the Base64 string

You can use the proxies generously provided by the fTelnet developer, but I'm a personal fan of self-hosting everything whenever possible, because you never know when someone's going to get hit by a truck or decide to stop providing a service you're relying on, and a websocket proxy is relatively simple.

I say relatively simple, because while the websockify proxy I was attempting to use is simple piece of software, so is the documentation and error messaging, and it took me FAR longer than I'd like to admit to determine why it wasn't passing traffic.

Before we get into deployment, if the site hosting fTelnet is encrypted, your websockify proxy MUST be encrypted, and you need to use a cert for the same domain as where the fTelnet client is hosted, or you'll get some SSL cert errors in the browser which could be confusing for your users.

I already had a wildcard cert for my domain from LetsEncrypt, so I simply went ahead and used the cert that was already there for the cert/key values in the websockify config.

After far too much fiddling, and finding a few weird edge cases, the Docker Compose file I ended up with:

version: "3.3"

services:
    websockify:
        image: novnc/websockify:latest
        restart: unless-stopped
        container_name: websockify
        hostname: websockify
        command: '--cert /data/live/uncomfortable.business/cert.pem --key /data live/uncomfortable.business/privkey.pem 11235 10.4.10.132:23'
        ports:
          - 11235:11235
        volumes:
          - /etc/letsencrypt:/data:ro

The big gotcha I ran into was that i was attempting to restrict the volume bind mount to JUST the specific certs for that specific domain, but was running into failures. Worse, and more confusingly, if I ran the non-docker version with the exact same options, it worked fine.

As it turns out, the certificate and key in the live path are not actually files but are symlinks that lead two steps up the directory tree, so I had to bind mount the whole /etc/letsencrypt path to get the proper certs actually visible to the container. Not ideal, but also not catastrophic.

The command line options are pretty straight forward: the cert and key variables are for the SSL key you're using.

The rest of the command line is the port the service is listening on, and the ip:port it should proxy to.

Also keep in mind the websockify proxy must be publicly accessible if you're using this on a public-facing website, so you'll want to forward the port you've chosen if you're behind nat/allow traffic through the firewall.

The only other changes I made were some color choices, and it turns out that the colors for the fTelnet UI are located in two places: some are in the CSS, and other are in the JavaScript code itself.

I wanted to change the status bar coloring to match the theme of the rest of the site, and the 'idle' coloring is in the ftelnet.css file, at the bottom:

.fTelnetStatusBar {
    background-color: rgb(19, 18, 18);
    border: 1px red;
    color: white;
    font: 14px Arial, Helvetica, sans-serif;
    margin: auto;
    padding: 5px;
    text-align: left;
}

I just changed the RGB value to my choice of grey, and on a reload the status bar was grey, as long as you're not connecting, connected, or disconnected from a session. Turns out those colors are actually in the JavaScript and you have to go digging to find and change them.

There are several different places required to change this color, and you can find them by searching for a single string, which is repeated for the various different statuses:

this._StatusBar.style.backgroundColor

You can use the same rgb(xx, xx, xx) formatting you'd use for CSS in javascript as well, even though by default the code is using color names

this._StatusBar.style.backgroundColor = 'rgb(19, 18, 18)';

So, after a couple of hours of fiddling with colors, command line options, and editing the HTML for the site itself to include a bit about the BBS and contact details and such, I ended up with a lovely site for accessing my BBS.