diff --git a/.env.example b/.env.example index 520c30f..22abc57 100644 --- a/.env.example +++ b/.env.example @@ -56,6 +56,21 @@ DB_ROOT_PASSWORD=change-me-root-password # Auth JWT_SECRET=change-me-to-a-long-random-string +# Encrypts every secret this site stores at rest (AES-256-GCM): OAuth client +# secrets, the Discord bot token, the Gmail refresh token, the uo-link auth +# token. REQUIRED in production — with NODE_ENV=production the app REFUSES TO +# START without it (utils/secretBox.js), so a Compose deployment that leaves it +# blank crash-loops before it ever listens. Development falls back to a key +# derived from JWT_SECRET, with a warning. +# +# Any string; it is hashed to 32 bytes. Generate a long random one and treat it +# like the database password. +# +# Changing it on a live instance does NOT re-encrypt anything: every secret +# already stored becomes unreadable and has to be entered again from the admin +# panel. That is also the reason it is a dedicated key rather than a reuse of +# JWT_SECRET — rotating a session secret must not orphan stored credentials. +SECRET_ENC_KEY=change-me-to-a-different-long-random-string JWT_EXPIRES_IN=1d # auto = Secure cookie only when the request arrives over HTTPS (Pangolin). # Leave as auto so login works both via the LAN IP (HTTP) and the proxy (HTTPS). diff --git a/README.md b/README.md index 5b15305..097b90b 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,12 @@ cp .env.example .env # Edit .env and set at least: # DB_PASSWORD, DB_ROOT_PASSWORD (any strong values) # JWT_SECRET (a long random string) +# SECRET_ENC_KEY (a different long random string) +# BOT_INTERNAL_KEY (a third one, 16+ chars — even with no bot) # ADMIN_USERNAME, ADMIN_PASSWORD (your first admin login) +# +# SECRET_ENC_KEY and BOT_INTERNAL_KEY are not optional in production: the app +# refuses to start without them, so the container crash-loops before it listens. docker compose pull && docker compose up -d # IMAGE_TAG defaults to `latest` # pin a specific build (reproducible deploy / rollback):