diff --git a/Dockerfile b/Dockerfile index 173506971e..5e7eea9c95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,23 @@ FROM nginx:1.25.3-alpine -WORKDIR /var/www/codesandbox -COPY www ./ +# Nginx config: serves /usr/share/nginx/html and denies dotfiles (e.g. /.env). +COPY .github/nginx/default.conf /etc/nginx/conf.d/default.conf + +# Static assets go under the document root. +COPY www /usr/share/nginx/html + +# Runtime env template + generator live OUTSIDE the document root so they are +# never reachable over HTTP. `env.sh` reads `.env` (and any overriding real +# environment variables) and writes `env-config.js` into the served static dir. +COPY .env /app/.env +COPY env.sh /app/env.sh +RUN chmod +x /app/env.sh + +# Defense-in-depth: make absolutely sure no stale copy of .env slipped into +# the web root from a previous build. +RUN rm -f /usr/share/nginx/html/.env /usr/share/nginx/html/env.sh + +WORKDIR /app + +# Generate env-config.js at container start, then hand off to nginx (PID 1). +CMD ["/bin/sh", "-c", "/app/env.sh /usr/share/nginx/html/static/js/env-config.js && exec nginx -g 'daemon off;'"] diff --git a/packages/app/scripts/copy-assets.js b/packages/app/scripts/copy-assets.js index ad1c58e2cd..e86031339c 100644 --- a/packages/app/scripts/copy-assets.js +++ b/packages/app/scripts/copy-assets.js @@ -24,14 +24,13 @@ const assets = [ from: 'packages/app/public', to: '', }, - { - from: '.env', - to: '.env', - }, - { - from: 'env.sh', - to: 'env.sh', - }, + // NOTE: `.env` and `env.sh` are intentionally NOT copied into `www/`. + // `www/` is served publicly by nginx, so anything placed here is reachable + // from the internet (e.g. GET /.env would leak secrets). `env.sh` reads + // `.env` at container startup to generate `static/js/env-config.js`, which + // is the only file the browser needs. The Dockerfile places `.env` and + // `env.sh` under `/app` (outside the document root) and runs `env.sh` from + // there on container start. ].filter(Boolean); const rootPath = path.resolve(__dirname, '../../..');