Deploy SteamOS.Club as a hardened OCI container

This adapter packages the reviewed xyd static output in an unprivileged NGINX runtime. It is suitable for a local preview, an OCI registry handoff, or a private origin behind a selected ingress. It does not change DNS, obtain certificates, publish an image, or expose a public service.

Do not deploy an image built from an uncommitted or unreviewed working tree. Record the source revision, static artifact digest, image ID or registry digest, approver, and rollback image before changing production traffic.

Deployment boundary

LayerResponsibility
xyd build
content, routes, native cosmo UI, search, SEO files, canonical and locale links
OCI image
exact static bytes, non-root NGINX, health endpoint, compression and cache policy
Container runtime
read-only root, /tmp tmpfs, no capabilities, process and restart policy
TLS ingress or CDN
certificates, HTTP redirect, HSTS, public rate limits and edge observability
Release engineering
immutable identity, approval, smoke tests, backup, restore and rollback evidence

HSTS is intentionally absent from the HTTP-only container. Sending it before a reviewed HTTPS ingress exists can create an incorrect security claim and complicate recovery.

rollback

Reader

TLS ingress or CDN

Restricted container runtime

Non-root NGINX

Immutable xyd static build

Bilingual routes, search, and SEO files

Health probe

Reviewed source and release gates

Digest-addressed OCI image

Recorded prior image digest

Artifact contract

Run the complete source and production gates first. The Docker build context admits only deploy/ and .xyd/build/client/; it excludes source files, dependency trees, Git data, generated manifests under .vite, and local secrets.

The runtime base is pinned by a multi-platform digest. org.opencontainers.image.revision records the reviewed source identifier, while the image ID or registry digest identifies the packaged bytes. A tag is only a movable human label.

Local build and smoke test

The project test discovers either direct Docker access or passwordless sudo docker. It builds the image, starts it on a random loopback port, exercises both locales, validates headers and unknown-route behavior, checks the runtime restrictions, saves and reloads the image, then starts the restored copy.

The test uses a unique temporary tag and container names. Its cleanup trap removes only those Phase 9 resources; it does not prune shared images, volumes, networks, or build caches.

Production runtime contract

The checked-in Compose adapter binds to 127.0.0.1 by default. It runs as UID/GID 101, drops every Linux capability, enables no-new-privileges, caps PIDs, makes the root filesystem read-only, and provides only a 16 MiB /tmp tmpfs required by unprivileged NGINX.

Do not change the bind address to 0.0.0.0 until firewall, TLS ingress, forwarded-header trust, monitoring, and incident ownership are reviewed.

Header and route verification

Check the private origin before attaching production traffic. HTML and route data require revalidation; fingerprinted /assets/ receive a one-year immutable policy. Dynamic gzip adds Vary: Accept-Encoding. Unknown paths return 404 rather than the SPA fallback with HTTP 200.

Required observations include HTTP 200 for both locale routes and health, HTTP 404 for the absent route, hidden NGINX version, nosniff, SAMEORIGIN, a restrictive referrer policy, a limited permissions policy, and the expected cache/compression headers.

Rollback

  1. Retain the reviewed static artifact and its SHA-256 digest from CI.
  2. Build once with the reviewed source revision; record the image ID and, after registry upload, its immutable digest.
  3. Deploy by digest or a release ID locked to that digest. Never rebuild an old tag with current dependencies.
  4. Keep at least one previously healthy image and its evidence during the retention window.
  5. On rollback, switch the ingress/runtime atomically, then repeat health, locale, discovery-file, and high-risk-page checks.

The Phase 9 workflow deliberately does not push to a registry. Registry authentication, signing, provenance attestations, retention, and vulnerability policy must be added for the selected platform rather than guessed here.

Backup and restore exercise

For an isolated local exercise, export the immutable image, record the archive digest, remove the test tag, load the archive, compare image IDs, and start the restored image. pnpm test:container automates this disposable path.

The source repository, lockfile, package patches, content snapshots, configuration, and workflows remain the primary backup. An exported runtime image is deployment/rollback evidence, not a substitute for source recovery.

TLS ingress checklist

  • Serve only https://steamos.club; redirect plain HTTP at the ingress.
  • Request and renew certificates through the selected provider's supported mechanism.
  • Add HSTS only after HTTPS and rollback behavior are proven on the real domain.
  • Preserve the original Host and client scheme; do not trust forwarded headers from arbitrary networks.
  • Retain request/error logs according to a documented privacy and deletion policy.
  • Verify Brotli or gzip, Vary, cache behavior, canonical URLs, both locales, sitemap.xml, robots.txt, and llms.txt from the public edge.

Frequently asked questions

Does this container terminate TLS for steamos.club?
Does this container terminate TLS for steamos.club?
No. It listens on unprivileged HTTP port 8080. A reviewed ingress or CDN must terminate TLS, redirect HTTP, set HSTS, preserve the Host header, and forward only to the container's private listener.
Why does the image copy an existing build instead of rebuilding xyd?
Why does the image copy an existing build instead of rebuilding xyd?
The release gates already reviewed .xyd/build/client. Packaging those exact bytes keeps dependency installation, browser tests, and content validation outside the small runtime image and prevents a second unreviewed build.

Sources

Version history

  • 2026-07-15: Phase 9 provider-neutral OCI deployment, verification, backup, restore, and rollback guide published with a deployment-boundary architecture diagram.