#36

Feature request: Dockerfile + docker-compose for self-hosted deployment

OpenRXDCODXopened 13d ago

Summary

Right now the only documented way to run an app is per-folder npm install && npm run dev, and the only documented production path is AWS Amplify (amplify.yml + customHttp.yml at the repo root).

There is no container image, no compose file, and no nginx/Caddy config anywhere in the repo — I walked the full file tree on main (34,886 paths) and found zero matches for Dockerfile, docker-compose, compose.yml or nginx.

That makes self-hosting impractical. Someone who wants these apps on their own VPS/NAS/home lab currently has to clone the repo, install Node 22.12+, run a build in each of the 51 app folders, and then hand-write a static file server that reproduces the caching behaviour the apps actually depend on.

What would make self-hosting work

  1. A Dockerfile per app (or one parameterized Dockerfile plus a build arg) that:
    • builds in node:22 (README requires >= 22.12),
    • runs npm ci && npm run build,
    • serves dist/ from a multi-stage nginx or Caddy runtime image,
    • runs non-root and declares a HEALTHCHECK.
  2. A docker-compose.yml at the repo root that brings up a chosen set of apps behind one reverse proxy on a single port, so a self-hoster gets one URL per app.
  3. A short "Self-hosting" section in README.md with the exact docker compose up -d commands.

The part that's easy to get wrong: customHttp.yml

The Amplify config encodes real application behaviour, not just cosmetics. An nginx image would have to reproduce it, and I'd be happy to help get it right:

  • / and **/*.html → no-cache, max-age=0, s-maxage=0, must-revalidate
  • /assets/* → public, max-age=31536000, immutable (Vite content hashes)
  • /assets/*.wasm → additionally Content-Type: application/wasm (circuits, parametric, music-studio)
  • /sw.js, /worker/*, /manifest.json → no-cache, ... (teamchat, fleet, legal, property-management, help-desk, solitaire, cad, and others)
  • chess, backgammon, checkers additionally ship a full Content-Security-Policy plus X-Content-Type-Options, Referrer-Policy, Permissions-Policy and Strict-Transport-Security

Getting this wrong is not cosmetic: a stale sw.js pins returning users to an old build forever, and a missing application/wasm content type breaks the CAD / circuits / parametric engines outright.

Open questions

  • Where should this live? One Dockerfile + compose file inside each of the 51 app folders is a lot of duplication. A shared deploy/ directory, or a single parameterized Dockerfile driven by a build arg, might be cleaner — I'd like to follow the maintainers' preference here.
  • What about the worker components? documents, spreadsheet, teamchat, help-desk, fleet, legal and property-management have build:worker / deploy:email-worker scripts targeting Cloudflare Workers. Should the compose file run those locally too (workerd / wrangler dev), or is the expectation that they stay external and just get documented?
  • How self-hosted is "self-hosted"? Several apps pull the Puter SDK from https://js.puter.com and talk to api.puter.com, and the shipped CSPs allow those origins. Should there be a documented path to point an app at a self-hosted Puter instance (cf. HeyPuter/puter), and would the baked-in CSPs need to become configurable?

Why it seems worth doing

The project's goal is free, open-source alternatives to proprietary software, and the audience for that is exactly the group that wants to self-host: home labs, small teams, privacy-sensitive organisations, people without an AWS account. docker compose up -d is the interface that audience already knows.

I'm happy to contribute a PR — for example documents and spreadsheet as a reference implementation, including the nginx header rules — if the approach is agreeable. Just wanted to check the direction before writing 51 near-identical Dockerfiles.

Checklist

  • I have searched the existing issues and discussions for this and believe it is new
  • I have read the contributing guidelines / README deployment notes

Activity

3
kamthorn4d ago

Thanks for the detailed write-up. I'd like to help with this, and I'm checking the direction before writing anything. @RXDCODX, you offered a PR too. Are you already working on it? If so I'll stay out of the way, or review.

What I'd propose for a first PR, answering the "where should this live" question:

  • One parameterized Dockerfile in a root deploy/ folder, with ARG APP. It builds src/$APP with Node 22 (npm ci && npm run build) and serves dist/ from a non-root nginx image, with a HEALTHCHECK. This avoids 51 near-identical Dockerfiles.
  • nginx headers generated from customHttp.yml, not copied by hand. That file already holds each app's cache, application/wasm and CSP rules, and Amplify reads it as the source of truth. A small script that turns an app's entry into an nginx config would keep the two deployments from drifting, which matters for sw.js and the wasm content type.
  • A short "Self-hosting" section in the README with the build and run commands for a single app.

I'd leave these out of the first PR and handle them separately:

  • the root docker-compose.yml with a reverse proxy for several apps
  • the Cloudflare worker components
  • pointing apps at a self-hosted Puter instead of js.puter.com / api.puter.com

The CSPs and the Puter SDK origin are probably a bigger discussion.

@jelveh, does this direction work for you (a shared deploy/ folder, generating the config from customHttp.yml), or would you rather have something else? I'll start once I know.

RXDCODX4d ago

Thanks @kamthorn — please go ahead, I'm not working on it.

I can't open a PR at the moment, so feel free to take the lead on the implementation if you're able to. Nothing to add against your proposal: a single parameterized Dockerfile in deploy/ driven by ARG APP, nginx config generated from customHttp.yml instead of hand-copied, and a short self-hosting section in the README all sound right to me, and I agree the root docker-compose.yml, the worker components and the self-hosted-Puter question are better handled separately.

If it's useful, I'm happy to review a PR or answer questions about the header rules I mapped out (the sw.js no-cache and application/wasm ones in particular). Thanks for picking this up.

theworker023d ago

Implementation in progress in https://github.com/HeyPuter/everything/pull/112 (Dockerfile + Compose + nginx profiles).