SECRET_KEY, APP_URL, and DEBUG were hardcoded/missing in the compose
environment block, so passing SECRET_KEY from the host env had no effect
and the container always raised ImproperlyConfigured in production mode.
All three are now forwarded via ${VAR} substitution, consistent with
the other configurable values.
Introduce timetracker/config.py with a single config() helper that resolves
settings from a fixed priority chain: NAME__FILE (opt-in secret) -> env var
-> .env -> settings.ini -> in-code default. Supports type casting
(bool/list/int/Path), file-based secrets with .strip(), and required_in_prod
validation.
Migrate settings.py off the previous ad-hoc idioms:
- DEBUG via config() (PROD kept as deprecated alias)
- SECRET_KEY required in prod, supports SECRET_KEY__FILE
- APP_URL derives ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS (kept separate,
each independently overridable); ALLOWED_HOSTS is now configurable
- TZ and DATA_DIR via config()
Fix DATA_DIR inconsistency: entrypoint.sh now reads DATA_DIR (was hardcoded)
so the bash bootstrap and Django agree on the database directory.
Document the container/entrypoint-only flags (PUID/PGID/
CREATE_DEFAULT_SUPERUSER/STAGING/LOAD_SAMPLE_DATA) as bash concerns.
Update deployment configs to set APP_URL (and DEBUG), add docs/configuration.md,
settings.ini.example, regrouped .env.example, CLAUDE.md, and tests.
https://claude.ai/code/session_01FFn8BiGrQpEJarC8xGse8s
Reviewed-on: #95
12 files changed (+149, -66)
Key changes:
1. Monolithic container — Replaced the two-service compose setup (backend + frontend/caddy) with a single timetracker container. Caddy is now built into the image rather than running as a separate container.
2. Supervisord process manager — Added supervisor.conf and installed supervisor in the Dockerfile. entrypoint.sh now delegates to supervisord to manage three processes: Caddy, Gunicorn, and Qcluster — replacing manual trap/signaling logic.
3. Bundled Caddy — The Dockerfile now downloads and installs Caddy v2.9.1 directly into the image (/usr/local/bin/caddy). The Caddyfile was updated to use reverse_proxy localhost:8001 and serves static files from /home/timetracker/app/static.
4. Configurable deployment — Added .env.example with configurable environment variables: TZ, PUID/PGID, TIMETRACKER_EXTERNAL_PORT, DATA_DIR, CSRF_TRUSTED_ORIGINS. docker-compose.yml now references these with sensible defaults.
5. UID/GID flexibility — entrypoint.sh uses usermod/groupmod at startup to remap the timetracker user to the host-specified PUID/PGID, avoiding permission issues with mounted volumes.
6. Database & static files — settings.py now respects DATA_DIR env var for the SQLite database path. STATIC_ROOT changed to BASE_DIR / "static".
7. Dev improvements — New Caddyfile.dev (with browse enabled for static files) and updated Makefile dev-prod target runs Caddy alongside Django in development.
8. Tests — Re-enabled the test step in the Docker build GitHub Actions workflow.