Fix noVNC WebSocket routing

This commit is contained in:
jjbrunton committed 2026-08-08 14:48:58 +01:00
1 parent 316dc3dd3e
commit 78e84fe36b
3 files changed
+37 -6

No files matched your search

+16 -1
View File
@@ -17,7 +17,9 @@ The bot has been updated to support automated login using environment variables.
* `OPENROUTER_API_KEY`: Your OpenRouter API key.
* `REDDIT_USERNAME`: Your Reddit username.
* `REDDIT_PASSWORD`: Your Reddit password.
* `BROWSER_HEADLESS`: `true` (Important for server environments).
* `BROWSER_HEADLESS`: `false` (required for interactive noVNC login).
* `VNC_PASSWORD`: A strong password for the interactive VNC session.
* `NOVNC_PUBLIC_URL`: `http://<dokploy-host>:16080`.
3. **Volumes (Persistence)**:
* The `docker-compose.yml` is already configured to mount a `./data` volume.
@@ -28,6 +30,19 @@ The bot has been updated to support automated login using environment variables.
* Push your code to your Git repository connected to Dokploy.
* Click "Deploy".
## noVNC networking
The Compose configuration publishes noVNC directly on host port `16080`.
Do not route it through a Dokploy/Traefik domain: the upstream proxy strips
the WebSocket Upgrade request that noVNC requires, producing `rfb.js:688` with
WebSocket code `1011` and “Failed to connect to downstream server”.
Set `NOVNC_PUBLIC_URL` to `http://<dokploy-host>:16080`, then open that URL in
a separate tab from the dashboard. If the dashboard itself is HTTPS, browsers
will not embed this HTTP endpoint in its iframe; the separate-tab link is the
intended route. Restrict inbound TCP `16080` at the Dokploy host firewall to
your own IP or VPN subnet.
## How it works
1. On the first run, the bot will see the `data/browser-session` folder is empty/invalid.
+9 -5
View File
@@ -15,11 +15,14 @@ services:
# path on every restart.
volumes:
- reddit_bot_data:/app/data
# Ports are NOT published to the host. Dokploy/Traefik routes traffic
# to the container's internal ports via configured domains.
# The dashboard goes through Traefik. noVNC must bypass the upstream
# proxy because it strips WebSocket Upgrade requests needed by websockify.
# Restrict host port 16080 with the host firewall; VNC_PASSWORD still
# authenticates the VNC session.
ports:
- "16080:6080"
expose:
- "3000" # Web dashboard
- "6080" # noVNC for human login
environment:
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
# Required whenever the web dashboard is enabled; never commit its value.
@@ -30,8 +33,9 @@ services:
- BROWSER_HEADLESS=false
# Required to lock down the VNC endpoint.
- VNC_PASSWORD=${VNC_PASSWORD}
# Public Traefik route used by the dashboard's recovery button.
- NOVNC_PUBLIC_URL=https://red-vnc.apps.jbrunton.co.uk
# Direct noVNC URL, e.g. http://<dokploy-host>:16080. It must not go
# through the WebSocket-stripping reverse proxy.
- NOVNC_PUBLIC_URL=${NOVNC_PUBLIC_URL}
volumes:
reddit_bot_data:
+12
View File
@@ -0,0 +1,12 @@
import { readFile } from 'node:fs/promises';
import { describe, expect, it } from 'vitest';
describe('Dokploy noVNC deployment configuration', () => {
it('publishes noVNC directly and leaves its public URL deployment-configured', async () => {
const compose = await readFile(new URL('../docker-compose.yml', import.meta.url), 'utf8');
expect(compose).toMatch(/ports:\s*\r?\n\s*- "16080:6080"/);
expect(compose).toMatch(/NOVNC_PUBLIC_URL=\$\{NOVNC_PUBLIC_URL\}/);
expect(compose).not.toContain('https://red-vnc.apps.jbrunton.co.uk');
});
});