Skip to content

fix: run production images as non-root - #142

Merged
Bccorb merged 1 commit into
mainfrom
fix/non-root-images
Oct 30, 2026
Merged

Bccorb merged 1 commit into
mainfrom
fix/non-root-images

Conversation

@Bccorb

@Bccorb Bccorb commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Closes #133

What changed and why

  • Web templates (react-vite, react-oauth, vue, svelte, angular): the runtime stage moves from nginx:alpine (root) to nginxinc/nginx-unprivileged:alpine, matching the admin dashboard. nginx runs as nginx (uid 101) and listens on 8080. The web root is chowned to nginx because entrypoint.sh writes config.js there at start; the unprivileged image already keeps its pid and temp paths in /tmp. Images stay pinned by tag, as everywhere else in this repo.
  • Next.js: the runtime target runs as node (uid 1000), with /app and the standalone output owned by node so the server can write its .next cache. Both targets move to port 8080 so they keep sharing one port, as the Dockerfile header promises. The dev target still runs as root, like the Express dev target, because the local stack bind-mounts the source over /app.
  • listen, EXPOSE, HEALTHCHECK and the README docker run examples all move from 80 to 8080.

Port change, needs a coordinated seamless-cli change

Every web container now listens on 8080 instead of 80. seamless-cli still maps 80:

  • src/generators/docker/docker.ts: webService() and fullStackWebService() publish 127.0.0.1:5173:80 and health-check http://localhost/health. Both need 5173:8080 and :8080/health (the admin service already uses 8080). Plus the matching assertions in docker.test.ts.
  • verify/docker-compose.verify.yml: the react, angular, vue, svelte, nextjs and nextjs-dev services map 5173:80 and health-check port 80.

Because the conformance workflow runs seamless-cli main's harness against this branch, it is expected to fail here until that harness moves to 8080. The CLI pins a templates tag, so the CLI change should land with the pin bump to the release that carries this.

Checks

  • npm run validate: registry.json and all template manifests are valid, and every template copy matches shared/react-app.
  • npm run format:check: All matched files use Prettier code style!
  • npm run check in each changed template (react-vite, react-oauth, vue, svelte, angular, nextjs): all exit 0.
  • docker build of each changed Dockerfile (Next.js both --target runtime and the default dev), then docker run -p <port>:8080:
Image uid /health / Docker health
react-vite 101 (nginx) 200 200 healthy
react-oauth 101 (nginx) 200 200 healthy
vue 101 (nginx) 200 200 healthy
svelte 101 (nginx) 200 200 healthy
angular 101 (nginx) 200 200 healthy
nextjs runtime 1000 (node) 200 200 healthy
nextjs dev 0 (unchanged) 200 200 healthy

The nginx images serve the config.js written by the entrypoint, and in the Next.js runtime node can create files under /app/.next.

The web templates serve from nginxinc/nginx-unprivileged as the nginx user
on port 8080, and the Next.js runtime target runs as the node user. Both
Next.js targets move to 8080 so they keep sharing one port.
@Bccorb
Bccorb merged commit ba2a329 into main Oct 30, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: run production images as non-root

1 participant