diff --git a/.dockerignore b/.dockerignore index 43e87f2..d87ca66 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,10 @@ openspec tools/node_modules tools/test +# never bake local env files or the private keys into the image +.env +.env.local +.env.keys Dockerfile .dockerignore README.md diff --git a/Dockerfile b/Dockerfile index 9977bed..831fcab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,19 +3,29 @@ # on the field laptop (the wizard reaches it at http://127.0.0.1:9000 from the # browser, so the container location does not matter). # +# The encrypted .env.production is baked in; the private key is supplied at +# runtime and never stored in the image: +# # docker build -t yreka-tools . -# docker run -d -p 4173:4173 --name yreka-tools yreka-tools +# docker run -d -p 4173:4173 --name yreka-tools \ +# --env DOTENV_PRIVATE_KEY_PRODUCTION="$(grep -oP '^DOTENV_PRIVATE_KEY_PRODUCTION=\K.*' .env.keys)" \ +# yreka-tools FROM node:22-alpine WORKDIR /app +RUN npm install -g @dotenvx/dotenvx@1.51.4 + COPY tools/package.json tools/package-lock.json ./ RUN npm ci --omit=dev && npm cache clean --force COPY tools/server.js tools/yrka-auth.js tools/permit.js tools/cropper.js ./ COPY tools/public ./public +COPY --chown=node:node .env.production ./ USER node EXPOSE 4173 HEALTHCHECK --interval=30s --timeout=5s --start-period=5s \ CMD wget -qO- http://127.0.0.1:4173/ >/dev/null || exit 1 -CMD ["node", "server.js"] +# --strict: fail fast when the private key is missing or decryption fails, +# instead of starting with unusable credentials. +CMD ["dotenvx", "run", "-f", ".env.production", "--strict", "--", "node", "server.js"] diff --git a/README.md b/README.md index 7786a40..f56c53c 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,20 @@ dotenvx run -f .env -- node tools/server.js # local, from the repo root dotenvx set MINIO_SECRET_KEY "" -f .env # add/rotate a value ``` -Deploying with Docker: `--env-file` cannot read encrypted values, so either -decrypt at deploy time (`dotenvx decrypt -f .env.production --stdout` into a -runtime env file) or pass `DOTENV_PRIVATE_KEY_PRODUCTION` into the container -and run through `dotenvx` inside the image (ask if you want the Dockerfile -wired for that). +The Docker image contains the encrypted `.env.production` and runs through +`dotenvx`; only the private key is supplied at runtime (never baked in): + +```sh +docker build -t yreka-tools . +docker run -d -p 4173:4173 --name yreka-tools \ + --env DOTENV_PRIVATE_KEY_PRODUCTION="$(grep -oP '^DOTENV_PRIVATE_KEY_PRODUCTION=\K.*' .env.keys)" \ + yreka-tools +``` + +`dotenvx run --strict` makes the container exit rather than start with +undecryptable credentials. Note that `--env` values are visible to +`docker inspect`; on a shared host prefer an env file with restrictive +permissions (`--env-file deploy.keys`) or your platform's secret store. ## Tests