Skip to content

chore(frontend): run the nginx image as non-root - #611

Merged
JuliusHenke merged 1 commit into
masterfrom
chore/frontend-nginx-unprivileged
Oct 12, 2026
Merged

JuliusHenke merged 1 commit into
masterfrom
chore/frontend-nginx-unprivileged

Conversation

@JuliusHenke

Copy link
Copy Markdown
Member

What

The frontend container now runs as a non-root user. This matches the backend, which already runs as 1000:1000.

  • Dockerfile: nginx:1.31.3-alpine -> nginxinc/nginx-unprivileged:1.31.3-alpine, pinned by digest. Same nginx version, now running as user 101. EXPOSE 8080.
  • nginx.conf: listen 8080. Ports below 1024 cannot be bound without root.
  • backend/docker-compose.yml: "80:80" -> "80:8080". The host port stays 80, so the example setup works unchanged.
  • frontend/README.md, THREAT_MODEL.md: document the port and the non-root user.

The Firebase deployment does not use this image and is not affected.

Verification

Built the image locally and ran it:

  • / -> 200 text/html, /some/deep/link -> 200 (SPA fallback), a hashed JS asset -> 200 application/javascript
  • id -> uid=101(nginx), and all nginx processes (master included) run as nginx
  • nginx -t passes

Dependencies (base image)

Docker base images are not covered by the OpenSourceMalware check, so this is the only vetting that applies:

  • Source: Docker Hub API for nginxinc/nginx-unprivileged:1.31.3-alpine, digest sha256:f972e532..., multi-arch with linux/amd64 and linux/arm64 (the platforms the workflow builds). The official nginx:1.31.3-alpine digest in Docker Hub matches the one previously pinned, so the tag lineage is consistent.
  • endoflife.date: nginx 1.31 is maintained, not EOL.
  • deps.dev, OpenSourceMalware: not applicable (maven/npm only).
  • Snyk: no maven/npm dependency changes, not run.

Deployment notes

Operators who run the frontend image with their own port mapping must change the container side from 80 to 8080, e.g. -p 80:8080 instead of -p 80:80, and update reverse-proxy upstreams that target container port 80. The example docker-compose.yml is updated and needs no change on the host side.

🤖 Generated with Claude Code

Switch to nginxinc/nginx-unprivileged (digest pinned, same nginx 1.31.3). The container now runs as user 101 and listens on 8080 instead of 80. The example docker-compose.yml maps host port 80 to 8080, so it keeps working unchanged for its users.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JuliusHenke JuliusHenke added enhancement New feature or request frontend deployment Operators must take action when deploying security Fixes a vulnerability and removed security Fixes a vulnerability labels Oct 12, 2026
@github-actions

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 79563bb):

https://tormap-36f44--pr611-chore-frontend-nginx-ur79mgoi.web.app

(expires Wed, 11 Nov 2026 20:21:40 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 0c1f71965de18e60b0e686b0d0356977fec090dc

@JuliusHenke
JuliusHenke marked this pull request as ready for review October 12, 2026 20:27
@JuliusHenke
JuliusHenke merged commit f9664c9 into master Oct 12, 2026
17 checks passed
@JuliusHenke
JuliusHenke deleted the chore/frontend-nginx-unprivileged branch October 12, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deployment Operators must take action when deploying enhancement New feature or request frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant