Skip to content

v1.0 — Admin console, self-hosted assets, hardened multi-arch image

Latest

Choose a tag to compare

@treyyoder treyyoder released this 06 Sep 17:26
· 2 commits to master since this release

Quake III Arena in the browser, fully self-hosted — no dependency on content.quakejs.com. This first release turns the bare QuakeJS server into a complete, operable product: a web admin console, a public front page, your own retail assets, and a hardened, self-deploying image built for amd64 and arm64.

Play

  • Front page at / — a lobby showing the server name, the current map with its picture, who's on, and the leaderboard, with a Join button. The game itself is at /play.html.
  • Name in game — type a name in Play as (or in the console) and it's the name you appear under; it's remembered in your browser.
  • One published port — the page, the game's websocket traffic, the assets, and the console all share port 80, so a single port-forward or reverse-proxy host is all a public server needs. HTTPS/wss is supported end to end.

Admin console (/admin/, or press ` in game)

A web console that drives the dedicated server live, organised in tabs:

  • Chat — a messenger threading public chat and private messages; set your in-game name here.
  • Stats — a leaderboard built from the engine's own game log; survives restarts, forgets names unseen for 90 days.
  • Server — current map with levelshot, switch maps (filtered to the gametype), restart, broadcast, and Backup (export/import + automatic daily backups).
  • Match — one-click presets (casual FFA, duel, TDM, CTF, party) plus gametype, limits, slots, mutators, server name and MOTD; values are validated and persisted across restarts.
  • Players — who's connected with their address, kick, move teams, add bots (as many as fit — see below), and timed bans with a reason.
  • Maps — upload a .pk3/.zip or your own retail paks, install from ..::LvL by id, and build the map rotation from presets.
  • Log — the live server log, an audit trail of every admin action, and crash notes.

The console opens in a public messenger mode anyone can use; Admin login unlocks the rest. Sign-in has a lockout keyed on the player's real address.

Your own Quake 3 assets

  • Nothing licensed ships in the image — it carries only the freely redistributable demo content and point-release paks.
  • Supply your own pak0.pk3 by uploading it in the console or pointing EXTRA_PAKS at a URL you control. The full game — all 31 stock maps, every bot, retail textures — then appears.
  • Slimming tool (tools/add-retail.py) trims music and cinematics (~62% of pak0, which a browser never plays), taking it from 457 MB to ~175 MB so it loads reliably in the browser client.

Moderation & multiplayer

  • Real client addresses — players' addresses are read from X-Forwarded-For through your reverse proxy (TRUSTED_PROXIES), so kicks and bans land on the player rather than the proxy.
  • Timed bans with a reason — an hour to thirty days, or permanent; a timed ban lifts itself, and every ban is re-applied if the game server restarts (the game module forgets them otherwise).
  • Bots up to the measured ceiling — the Add button offers as many as actually fit: free client slots or the game module's memory limit (24 bots — its allocator fails at 26–27, measured), whichever is lower, shown live.
  • Player votes, a leaderboard, and an optional Discord/Slack webhook that pings when someone starts playing on an empty server.

Operations

  • No root at runtime — the entrypoint hands the volumes to an unprivileged quake user and drops privileges; Apache binds port 80 through a file capability, not as root.
  • No baked-in password — one is generated on first start and printed once to the log (docker logs … | grep generated); set ADMIN_PASSWORD to choose your own, or empty to disable the console.
  • Persistent state — settings, rotation, leaderboard, bans, audit trail, crash notes and installed maps live in named volumes and survive redeploys.
  • Backups — export/import the whole state as one file from the console, plus an automatic daily backup (seven kept).
  • Log rotation — Apache logs to the container output (Docker rotation applies); games.log and the console log are capped and rotated.
  • Healthcheck covers the page, the game port, the crash marker, and the console — a dead console no longer reads as healthy, and the entrypoint restarts it.
  • Audit trail & crash notes — every admin action and sign-in is recorded with its address; a crash keeps the last 200 log lines with the map and bot count.

Security

  • Request-body size cap and per-read timeout, checked before authentication.
  • Sign-in lockout keyed on the real client address; Authorization: Basic counts against it.
  • Secure + HttpOnly + SameSite cookies behind TLS; a strict Content-Security-Policy on the console (nothing inline, script or style); nosniff and frame-ancestors on every page; no version banners.
  • Private messages are scoped to their sender and to admins.
  • SSRF guard on the map-download path — every fetch and every redirect must resolve to a public address, blocking loopback, private ranges, and the cloud-metadata endpoint.
  • Console passwords hashed with PBKDF2-HMAC-SHA256 at 600,000 rounds; older hashes upgrade on next sign-in.

Under the hood

  • The console is a small, tested Python package (admin/qadmin/), one module per concern, with a single settings spec shared with the config builder.
  • Unit and smoke tests run on the host, at image build, and inside the built image — a regression can't produce a published image.
  • Multi-arch, signed images — built for linux/amd64 and linux/arm64 from digest- and checksum-pinned inputs, and signed with cosign in CI.
  • Install and user guide in the README, with screenshots of every console tab.

Image

Published to Docker Hub for amd64 and arm64:

docker run -d --name quakejs -p 8080:80 \
  -v quakejs-assets:/var/www/html/assets \
  -v quakejs-state:/var/lib/quakejs \
  treyyoder/quakejs:latest

Verify the signature:

cosign verify treyyoder/quakejs:latest \
  --certificate-identity-regexp 'https://github.com/treyyoder/quakejs-docker/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

See the README for the full install and user guide.