Pass the whole .env to the container, and refuse the default session secret (#147) #160
No reviewers
Labels
No labels
area/ai
area/backend
area/frontend
area/infra
area/scheduler
area/wled
good-first-issue
priority/high
priority/low
priority/medium
security
type/bug
type/chore
type/ci-cd
type/docs
type/feature
type/qa
v1.0.0
v1.1.0
v1.2.0
v2.0.0
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/Iris-WLED!160
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/147-compose-env-file"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #147.
What was wrong
docker-compose.ymlpassed config through a hand-maintainedenvironment:list that stopped growing after v1.0.0. The app's own.envloading resolves to/app/.envinside the container, which is never mounted. So 19 settings in.env.examplesilently did nothing underdocker compose up, and ten of them are env-only, which made them impossible to turn on:METRICS_ENABLEDBACKUP_REMOTE_PATHBACKUP_S3_*settingsAURORA_ENABLEDandAURORA_MIN_KPChanges
docker-compose.yml:env_file: .envreplaces the list, so there is no second copy to drift.SESSION_SECRETguard moves into the app (app/config.pyassert_session_secret_is_safe, called at import inapp/main.py).:?was the only real guard; the app only logged CRITICAL and started anyway.env_ignore_empty, so it is caught too.startup.sh's uvicorn is the only non-test importer ofapp.main. Tests are unaffected becauseconftest.pysetsDISABLE_AUTH=truebefore import.test_env_example.py: every.env.examplename must be aSettingsfield. The allowlist isHOST_PORT,IRIS_UIDandIRIS_GID, which are compose-interpolation only.test_config_guard.py: four cases, including the empty-env-var path.docker-e2erendersdocker compose configagainst a sentinel.envand asserts five values reach.services.iris.environment. This matters because the E2E container is started withdocker run, so nothing else crosses this boundary. It was verified locally in both directions: it passes with the fix and fails with a reverted list.Verification
Behaviour change to note
A missing or default
SESSION_SECRETnow shows up as a container that exits at startup, with the fix in its log, instead ofdocker compose uprefusing to run.TZloses its compose-levelUTCdefault, butSettings.TZalso defaults toUTC, so nothing changes there.Next: release as v1.1.1, so Rhoving/iac-repo#527 can pin a tag with this fix.
🤖 Generated with Claude Code
docker-compose.yml maintained its own copy of every setting in .env.example as an `environment:` list, and nothing kept the two in sync: 19 settings added since -- METRICS_ENABLED, the BACKUP_S3_* family, AURORA_ENABLED/AURORA_MIN_KP, RAMP_ON/OFF_MINUTES, DAILY_BACKUP_RETAIN_COUNT, and the morning-window block -- were never added to compose, so setting them in .env silently did nothing to a container started with `docker compose up`. Switch to `env_file: .env` so there is no second list to drift, and add a CI step that starts a sentinel .env through `docker compose config` and asserts it reaches the container's environment. The same drift had removed the only thing stopping Iris from starting with the insecure default SESSION_SECRET: compose's `${SESSION_SECRET:?...}` was the sole guard, and it only worked when running the image through this exact compose file. The app now refuses to start with the default secret while authentication is enabled instead of only logging a CRITICAL line, so the guard holds regardless of how the container is run. Add tests for both the .env.example/Settings agreement and the new startup guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>