Deployments on 1.0.31 or earlier cannot take an image update without changing their compose file and .env, and nothing in the repo said so. Document the migration from the two-container setup to the single flashpoint-web image, the environment variables added, removed, and changed since 1.0.31, and per-version release notes for 1.0.32-1.0.36. Link it from the README and both documentation indexes.
12 KiB
Upgrade Guide and Release Notes
How to move an existing deployment to a newer version, and what changed in each release. Versions follow the git tags published on Docker Hub.
Upgrading from 1.0.31 or earlier? The deployment model changed in 1.0.32: the separate backend and frontend containers were replaced by a single image. Read Upgrading from 1.0.31 before pulling.
Upgrading from 1.0.31
What changed
Up to 1.0.31 a deployment ran two containers: darkraise/flashpoint-backend
(Node/Express, port 3100) and darkraise/flashpoint-frontend (nginx serving the
built React app on port 8080, proxying /api to the backend).
From 1.0.32 there is one image, darkraise/flashpoint-web. The Express backend
serves the built React UI and its SPA fallback alongside the API and game
content, so the whole app lives on one origin and one port.
Before (<= 1.0.31) After (>= 1.0.32)
flashpoint-frontend :80 -> nginx flashpoint-web :80 -> :3100
flashpoint-backend :3100 -> Express / built React UI
/api, /game-proxy, /game-zip
The old flashpoint-backend and flashpoint-frontend images are no longer
built or published. 1.0.31 is the last version available under those names.
Migration steps
-
Stop and remove the old stack. From the directory holding your existing compose file:
docker compose downThis removes the
flashpoint-backendandflashpoint-frontendcontainers. Named volumes and bind mounts are kept. -
Replace
docker-compose.ymlwith the single-service version from the README. The service is now namedflashpoint-web, maps${WEB_PORT:-80}to container port3100, and has nofrontendservice and nodepends_on. -
Update
.env— see the variable tables below. At minimum, deleteAPI_PORT,BACKEND_HOST, andBACKEND_PORT; they are no longer read by anything. -
Check the Flashpoint mount. As of 1.0.36 the shipped compose mounts it read-write (no
:ro). Downloading games, recording downloaded state inflashpoint.sqlite, and metadata sync all write into that directory. Leaving:roin place still allows browsing and playing already-downloaded games, but the Downloaded page will stay empty and the reconciler logs a warning on every boot. -
Update your reverse proxy, if you have one. Configurations that defined two upstreams — the UI on the web port and the API on port 3100 — must be collapsed into a single upstream on
WEB_PORT. Any rule routing/apito port 3100 will break, because nothing listens there on the host anymore. Firewall rules opening port 3100 can be removed. -
Pull and start.
docker compose pull && docker compose up -d
What is preserved
Application data is untouched by the migration. user.db (accounts, playlists,
favourites, play history, settings) lives in the DATA_PATH bind mount at
/app/data and is used unchanged by the new image. Log and Flashpoint mounts
keep their paths. No database migration is required beyond the ones the backend
applies on startup.
Environment variable changes
Removed — delete these from .env; they have no effect:
| Variable | Replacement |
|---|---|
API_PORT |
WEB_PORT — one port now serves both the UI and API |
BACKEND_HOST |
none — there is no cross-container proxy |
BACKEND_PORT |
none — same reason |
PORT and HOST were documented as configurable before 1.0.32 but never were:
the backend binds 0.0.0.0:3100 unconditionally, and the Docker EXPOSE and
healthcheck depend on that. The docs were corrected rather than the code.
Added:
| Variable | Default | Since | Description |
|---|---|---|---|
SERVE_FRONTEND |
true in production, else false |
1.0.32 | Serve the built UI and SPA fallback from the backend |
FRONTEND_DIST_PATH |
/app/frontend/dist in image |
1.0.32 | Where the built UI lives; rarely needs overriding |
FLASHPOINT_GAMES_PATH |
<FLASHPOINT_PATH>/Data/Games |
1.0.32 | Override the game ZIP directory |
OTEL_METRICS_EXPORT_INTERVAL |
60000 |
1.0.32 | Metrics export interval in milliseconds |
OTEL_LOG_LEVEL |
info |
1.0.32 | OpenTelemetry SDK log level |
COOKIE_SECURE |
auto |
1.0.34 | Secure flag on auth cookies: auto, true, false |
UV_THREADPOOL_SIZE |
16 |
1.0.36 | File I/O threads; Node's own default of 4 throttles image reads |
DB_WORKER_COUNT |
4 |
1.0.36 | Read-only SQLite query worker threads (1–16) |
UV_THREADPOOL_SIZE=16 is baked into the image, so it applies whether or not
your compose file passes it.
Changed:
| Variable | Change |
|---|---|
DOMAIN |
Now accepts a comma-separated list of origins. Same-origin requests are always allowed, so a standard single-image install needs no value at all. Default ports are normalized: http://host:80 and http://host are treated as the same origin. |
IMAGE_TAG |
Selects the tag of darkraise/flashpoint-web instead of the two old images. |
OTEL_SERVICE_NAME |
Default changed from flashpoint-web-backend to flashpoint-web. Update dashboards and alert queries that filter on the old name. |
LOGS_PATH |
Dev compose mounts it at /app/logs directly; it previously mounted ${LOGS_PATH}/backend. |
Newly passed through compose (these already existed in the backend, but the
shipped compose files now forward them with documented defaults):
JWT_EXPIRES_IN, BCRYPT_SALT_ROUNDS, RATE_LIMIT_WINDOW_MS,
RATE_LIMIT_MAX_REQUESTS, HOME_RECENT_HOURS, ENABLE_CGI.
FLASHPOINT_PATH=/data/flashpoint is now set explicitly in the dev compose file.
The backend's fallback only points there when NODE_ENV=production, so a
development container previously looked at the wrong path.
Rolling back
Pin the old images (darkraise/flashpoint-backend:1.0.31 and
darkraise/flashpoint-frontend:1.0.31) and restore the two-service compose file
and the .env entries removed in step 3. Application data written by 1.0.32+ is
readable by 1.0.31. Downloaded state is recorded in Flashpoint's own
presentOnDisk and path columns, which the Launcher already understands;
1.0.31 simply does not surface it.
[1.0.36] — 2026-08-12
Fixed
- Flashpoint directory is mounted read-write by default. The shipped compose
files mounted it
:ro, which silently failed every write the app makes: downloaded-state flags inflashpoint.sqlite, downloaded game data underData/Games, and metadata sync. If you copied an earlier compose file, drop the:rosuffix. - Image preloads are cancelled when a request is abandoned, so scrolling a large library no longer queues work for images that left the viewport.
Added
- A metadata sync can optionally download game images afterwards.
Performance
- Heavy read-only queries run in SQLite worker threads (
DB_WORKER_COUNT, default 4).better-sqlite3is synchronous, and a filter-options query over a slow mount was measured blocking the entire server for 167 seconds —/healthtimed out along with everything else. UV_THREADPOOL_SIZEis set to 16 in the image. libuv's default of 4 throttled every image and ZIP read in the process, which dominates on network storage.
[1.0.35] — 2026-08-12
Added
- Admins can choose the metadata source used for syncs.
Fixed
- Ruffle installs in the background and into the directory that is actually
served (
frontend/dist/ruffle). Startup previously awaited the download, so the port stayed closed for minutes on slow storage — indefinitely if the download stalled — and a fresh container re-downloaded the Ruffle it already shipped. - Locally served images are cached and no longer block on
stat. npm testruns the backend suite once instead of entering watch mode.
[1.0.34] — 2026-08-11
Fixed
- Auth cookies are marked
Secureper connection, not perNODE_ENV. Production builds previously always setSecure, and browsers discard such a cookie when it arrives over plain HTTP — logging LAN users straight back out after login. The new default,COOKIE_SECURE=auto, decides per request based on TLS (readingX-Forwarded-Protowhen behind a proxy), so one deployment can serve HTTP on a LAN and HTTPS through a proxy at once. SetCOOKIE_SECURE=trueif your TLS-terminating proxy does not send that header.
Documentation
- README carries a minimal working
.envexample and refreshed sections.
[1.0.33] — 2026-08-11
Fixed
- CORS origins are normalized and same-origin requests are always allowed.
With the UI and API on one origin, most deployments no longer need
DOMAINat all.DOMAINalso accepts a comma-separated list, and explicit default ports (:80,:443) match the port-less origin a browser actually sends. - The dev compose file passes
FLASHPOINT_PATH=/data/flashpointexplicitly.
Performance
- Downloaded filter options are cached indefinitely.
[1.0.32] — 2026-08-11
Breaking
- Single image deployment. The backend and frontend images were collapsed
into
darkraise/flashpoint-web, which serves the API, game content, and the built UI from one Express process on port 3100. Thefrontendservice, its nginx config and entrypoint, and the per-service Dockerfiles are gone; the release workflow builds one image instead of a two-service matrix. See Upgrading from 1.0.31. API_PORT,BACKEND_HOST, andBACKEND_PORTwere removed. Map a host port withWEB_PORTinstead.
Added
- Downloaded games page, filter, and settings: browse games whose data is already on disk, with the filter encoded in the URL and downloaded state reconciled from disk at startup.
- 5-star game rating system.
- Setting to toggle the "I'm Feeling Lucky" button.
Security
- The SPA-oriented CSP was ported from nginx into Helmet and hardened, dropping
unsafe-inlineandunsafe-eval. The strict API-only policy still applies whenSERVE_FRONTENDis off.
Fixed
- Guest browsing survives auth-only 401s instead of falling into a redirect loop (thanks @MaxfieldKassel).
- Invalid
SQLITE_CACHE_SIZEandSQLITE_MMAP_SIZEvalues fall back to their defaults instead of becomingNaN.