WebSocket / Web Interface Server
WebSocket Login Server
Section titled “WebSocket Login Server”The WebSocket Login Server provides secure (wss://) as well as non-secure (ws://) WebSocket login access. This is most commonly combined with a browser-based client such as VTX or fTelnet to give users a web browser entry point to your BBS.
Configuration
Section titled “Configuration”Enable the WebSocket server by adding a webSocket block to loginServers in config.hjson:
loginServers: { webSocket: { ws: { // non-secure ws:// — suitable for LAN/local testing or when // sitting behind a TLS-terminating reverse proxy (see below) port: 8810 enabled: true
// optional: bind to a specific address (e.g. loopback when proxied) address: 127.0.0.1 } wss: { // secure wss:// — ENiGMA handles TLS directly port: 8811 enabled: true certPem: /path/to/https_cert.pem keyPem: /path/to/https_cert_key.pem }
// Set proxied: true when a TLS-terminating reverse proxy (e.g. nginx) // forwards connections to ENiGMA's plain ws:// port. From a trusted // proxy (see Trusted Proxies below), ENiGMA then takes the caller's // address from X-Forwarded-For / X-Real-IP, and treats a connection // carrying "X-Forwarded-Proto: https" as secure, which is required for // 2FA/OTP and other security-sensitive features. Leave false // (default) if ENiGMA is exposed directly. proxied: true }}Restart ENiGMA and confirm the server started in the logs:
INFO: Listening for connections (server="WebSocket (insecure)", port=8810)INFO: Listening for connections (server="WebSocket (secure)", port=8811)Deployment Architectures
Section titled “Deployment Architectures”There are two supported ways to expose a secure WebSocket endpoint to browser clients.
Option A — Reverse Proxy (recommended)
Section titled “Option A — Reverse Proxy (recommended)”A reverse proxy such as nginx or Caddy handles TLS and forwards plain ws:// traffic to ENiGMA. This is the most common setup because it reuses your existing web certificate and keeps ENiGMA out of the certificate-management business.
Browser (wss://) → nginx (TLS termination) → ENiGMA ws:// port 8810ENiGMA config:
loginServers: { webSocket: { ws: { port: 8810 enabled: true address: 127.0.0.1 // loopback only — nginx is the public face } proxied: true // read forwarded headers from the proxy }}nginx location block (inside your existing server { ... } block with a valid TLS certificate):
location /wss { proxy_pass http://127.0.0.1:8810; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https;}Point wsConnect in vtxdata.js to wss://your-hostname.here/wss.
See nginx WebSocket proxying for more detail.
Caddy’s reverse_proxy and Traefik set X-Forwarded-For and X-Forwarded-Proto by themselves.
Trusted Proxies
Section titled “Trusted Proxies”Forwarded headers are believed only from the addresses in the top-level trustedProxies setting, which the web server uses too. The default covers loopback and the private ranges (127.0.0.0/8, ::1/128, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7), so a proxy on the same host, in another Docker container or on the LAN needs no change. A proxy on any other address must be listed:
trustedProxies: [ "127.0.0.0/8" "::1/128" "203.0.113.10"]Entries are IPv4 or IPv6 addresses or CIDRs. Setting trustedProxies replaces the default list, so keep the entries you still need.
trustedProxies should name your proxies. The default covers the private ranges, so a client your proxy sees with a private address (a LAN user, or every user when a container setup hides client addresses and the proxy sees, say, the Docker gateway) is taken for another proxy hop and its own X-Forwarded-For entries are believed. If your proxy sees clients that way, set trustedProxies to the proxy’s own address or addresses only.
The proxy must set X-Forwarded-For itself, as in the nginx example above ($proxy_add_x_forwarded_for appends the address nginx sees, which is fine). A header the proxy passes through unchanged was written by the client.
With proxied: true:
- The caller’s address comes from
X-Forwarded-For, read right to left, skipping addresses that are themselves trusted proxies; failing that, fromX-Real-IP. X-Forwarded-Proto: httpsmarks the connection as secure.- Forwarded headers from a peer not in
trustedProxiesare ignored. The log says so once per address, namingtrustedProxies: if that address is your proxy, add it. - Callers that come through the proxy are never treated as local, whatever address it forwards.
- If the proxy sends no client address, every caller appears to come from the proxy, and the log suggests sending
X-Forwarded-For.
The Forwarded header (RFC 7239) is not read.
Option B — ENiGMA handles TLS directly
Section titled “Option B — ENiGMA handles TLS directly”ENiGMA listens on a dedicated wss:// port and manages the certificate itself. Useful if you don’t already run a reverse proxy.
Browser (wss://) → ENiGMA wss:// port 8811ENiGMA config:
loginServers: { webSocket: { wss: { port: 8811 enabled: true certPem: /path/to/https_cert.pem keyPem: /path/to/https_cert_key.pem } }}Point wsConnect in vtxdata.js to wss://your-hostname.here:8811.
VTX Web Client
Section titled “VTX Web Client”ENiGMA supports the VTX WebSocket client for in-browser BBS access. Example deployment: Xibalba.
-
Enable the WebSocket server as described above. For a public deployment use Option A or B.
-
Download VTX_ClientServer. Visit github.com/codewar65/VTX_ClientServer and download the release you intend to use. Unpack it to a temporary directory.
-
Download the example HTML file. Save vtx.html to your webserver root.
-
Create the asset directory structure:
├── assets│ └── vtx└── vtx.html -
Copy VTX client files. From the unpacked VTX_ClientServer package, copy the contents of the
wwwdirectory intoassets/vtx/. -
Create
assets/vtx/vtxdata.js:var vtxdata = {sysName: "Your Awesome BBS",wsConnect: "wss://your-hostname.here:8811", // or wss://your-hostname.here/wss for Option Aterm: "ansi-bbs",codePage: "CP437",fontName: "UVGA16",fontSize: "24px",crtCols: 80,crtRows: 25,crtHistory: 500,xScale: 1,initStr: "",defPageAttr: 0x1010,defCrsrAttr: ['thick', 'horizontal'],defCellAttr: 0x0007,telnet: 1,autoConnect: 0,wsProtocol: 'telnet',wsDataType: 'arraybuffer',};Update
sysNameandwsConnectfor your system. Note thatdefCrsrAttrmust be an array, not a hex value — passing a hex integer here causes a black screen. -
Navigate to
https://your-hostname.here/vtx.html. You should see a splash screen like:
Configuration Reference
Section titled “Configuration Reference”| Key | Required | Description |
|---|---|---|
ws.enabled | Enable non-secure ws:// listener. Default: false. | |
ws.port | Port for ws://. Default: 8810. | |
ws.address | Bind address for ws://. Omit to bind all interfaces. | |
wss.enabled | Enable secure wss:// listener. Default: false. | |
wss.port | Port for wss://. Default: 8811. | |
wss.address | Bind address for wss://. | |
wss.certPem | Yes (if wss enabled) | Path to TLS certificate in PEM format. |
wss.keyPem | Yes (if wss enabled) | Path to TLS private key in PEM format. |
proxied | Set true when behind a TLS-terminating proxy. Reads the caller’s address and X-Forwarded-Proto: https from proxies in trustedProxies. Default: false. |
trustedProxies is a top-level setting, not part of the webSocket block: see Trusted Proxies.