Declare the service account DN before the OU loop and print the LDAP result code and server message when the password-change check fails. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
Self-Service Portal
A Django 5.2 LTS container for a user self-service portal. This repository holds the project scaffold: configuration, health check, logging, security headers and the container definition.
Configuration
All configuration comes from environment variables, validated at startup. If any variable is missing or invalid, the process prints one message that lists every problem (never the values) and exits with a non-zero code. Copy .env.example to .env and edit it.
| Variable | Required | Default | Meaning |
|---|---|---|---|
SECRET_KEY |
yes | Django secret, at least 32 characters | |
ALLOWED_HOSTS |
yes | Comma-separated host names | |
DATA_DIR |
no | /data |
Existing directory for the SQLite database |
DEBUG |
no | false |
true or false |
TRUSTED_PROXIES |
no | empty | Comma-separated IP addresses or networks. Reserved for the client-IP rule in a later entry; currently has no effect |
LOG_LEVEL |
no | INFO |
DEBUG, INFO, WARNING, ERROR, CRITICAL |
DEFAULT_TIMEZONE |
no | Europe/Berlin |
IANA zone used for display; storage is UTC |
Run in a container
The image is built and run on a Linux host from a checkout of this repository.
cp .env.example .env # then set SECRET_KEY and ALLOWED_HOSTS
docker compose up --build
curl -H "Host: <first ALLOWED_HOSTS entry>" http://localhost:8000/healthz # {"status":"ok"}
The container runs as a non-root user with a read-only root file system. Only the /data and /backups volumes are writable. It starts one gunicorn worker with threads after applying migrations. Session and CSRF cookies are marked secure, so use the portal through an HTTPS reverse proxy that sets X-Forwarded-Proto.
/healthz checks the database only. It returns 200 {"status":"ok"} or 503 {"status":"unavailable"}.
Develop
Requires Python 3.13 and uv.
uv sync
uv run pytest
uv run ruff check .
pytest sets its own test environment (see pyproject.toml).