You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AdvisoryHub is configured entirely through environment variables, parsed by
django-environ in config/settings/base.py. This page documents the settings
modules and the complete variable catalogue.
Two reference files back this page:
.env.example — an annotated reference of the production knobs, grouped and
marked secret vs config. It is not loaded by docker-compose; it exists to
copy into your platform's secret manager.
config/settings/base.py — the authoritative schema (defaults and types). A
few knobs are read here but omitted from .env.example; those rows are marked
† below.
Legend: Secret = must come from a vault, never a committed manifest.
Required = has no usable production default. † = read by base.py but not
listed in .env.example.
1. Settings modules
config/settings/ holds four modules; the active one is chosen by
DJANGO_SETTINGS_MODULE:
Module
Selected by
Purpose
config.settings.base
(imported by the others)
The full env-driven schema, apps, middleware, security defaults, OIDC, Celery, CSP, the beat schedule.
Eager Celery, rate-limiting and step-up off, fast password hasher.
In production, run the WSGI/ASGI app (which defaults to prod) or set
DJANGO_SETTINGS_MODULE=config.settings.prod explicitly for management commands.
What prod.py changes is detailed in
running-in-production.md.
2. Django core
Variable
Default
Notes
DJANGO_SECRET_KEY
insecure-change-me
Secret. Required. Session/CSRF signing key — a long random string.
DJANGO_DEBUG
False
Never True in production.
DJANGO_ALLOWED_HOSTS
*
Required. Comma-separated hostnames, e.g. advisoryhub.example.org.
Secret. Required. Must be PostgreSQL — append-only triggers and JSONB are Postgres-specific.
CACHE_URL
(empty → in-process LocMem)
Required in prod. Point at the shared Valkey, e.g. redis://valkey:6379/2. Backs rate-limiting and the maintenance-mode flag; LocMem is per-process and won't coordinate across replicas.
Require TLS to Postgres. Append ?sslmode=verify-full (with a pinned
server CA via sslrootcert) to DATABASE_URL so the app rejects an
unencrypted or MITM'd database connection. Advisory content is not encrypted
at the application layer (INV-CONF-1);
confidentiality of content at rest is a deployment-layer control — see the
database hardening checklist.
4. OIDC (authentication)
See integrations.md §1 for the
end-to-end setup. All endpoints come from your provider's discovery document.
Variable
Default
Notes
OIDC_RP_CLIENT_ID
(empty)
Required. Confidential-client id for this environment.
OIDC_RP_CLIENT_SECRET
(empty)
Secret. Required.
OIDC_OP_AUTHORIZATION_ENDPOINT
(empty)
Required. Browser-facing authorize URL.
OIDC_OP_TOKEN_ENDPOINT
(empty)
Required. Server-to-server token exchange.
OIDC_OP_USER_ENDPOINT
(empty)
Required. Userinfo endpoint.
OIDC_OP_JWKS_ENDPOINT
(empty)
Required. Signing-key (JWKS) endpoint.
OIDC_OP_LOGOUT_ENDPOINT
(empty)
Optional. The OP end_session_endpoint for RP-initiated logout; empty falls back to local-only logout.
Keep True in prod; dev sets False for Kanidm's self-signed cert.
OIDC_USE_PKCE †
True
PKCE (S256); most modern providers require it.
OIDC_GROUP_CLAIM
groups
The claim carrying group membership.
OIDC_ADMIN_GROUP
advisoryhub-security
Membership grants global admin + Django is_staff/is_superuser.
5. Step-up authentication
Variable
Default
Notes
STEP_UP_REQUIRED
True
Force a fresh re-login before publishing / GitHub-App changes. Keep True in prod.
STEP_UP_MAX_AGE_SECONDS
300
How recent that re-auth must be.
6. Celery & broker
Variable
Default
Notes
CELERY_BROKER_URL
redis://localhost:6379/0
Secret (if AUTH). Required. In prod prefer rediss://:<pw>@host:6379/0.
CELERY_RESULT_BACKEND
redis://localhost:6379/1
Results are ignored (CELERY_TASK_IGNORE_RESULT=True), so this DB stays empty.
CELERY_TASK_ALWAYS_EAGER
False
Run tasks inline — test-only; never True in prod.
7. Email
Variable
Default
Notes
EMAIL_BACKEND
…console.EmailBackend
Set to django.core.mail.backends.smtp.EmailBackend in prod, then configure the EMAIL_HOST* knobs below.
DEFAULT_FROM_EMAIL
AdvisoryHub <noreply@example.org>
From-address on outbound notifications.
EMAIL_HOST
localhost
SMTP relay host (smtp backend only).
EMAIL_PORT
25
SMTP port — typically 587 with STARTTLS.
EMAIL_HOST_USER
(empty)
SMTP auth username; empty disables auth.
EMAIL_HOST_PASSWORD
(empty)
Secret. SMTP auth password.
EMAIL_USE_TLS
False
STARTTLS on connect (mutually exclusive with EMAIL_USE_SSL).
EMAIL_USE_SSL
False
Implicit TLS (usually port 465).
ADVISORYHUB_BASE_URL
(empty)
Absolute-URL base for links in notification emails, e.g. https://advisoryhub.example.org. Empty keeps links site-relative (they won't resolve from a mail client).
Off by default. See integrations.md §5.
Enabling the switch is the consent for advisory content (potentially embargoed)
to reach the configured LLM provider (INV-SIM-2).
Variable
Default
Notes
SIMILARITY_CHECK_ENABLED
False
Master switch for LLM-assisted duplicate detection.
SIMILARITY_LLM_PROVIDER
anthropic
anthropic or openai (incl. OpenAI-compatible servers).
SIMILARITY_LLM_MODEL
claude-opus-4-8
Model identifier for the selected provider.
SIMILARITY_LLM_API_KEY
(empty)
Secret. Required if enabled — blank only for keyless local servers.
SIMILARITY_LLM_BASE_URL
(empty)
Empty = provider default; point at a local OpenAI-compatible server (e.g. http://ollama:11434) for on-prem inference.
SIMILARITY_LLM_TIMEOUT
120
Per-request read timeout in seconds (connect timeout is fixed at 10).
SIMILARITY_CANDIDATE_LIMIT
60
Max prefiltered candidates sent to the LLM judge call.
SIMILARITY_MIN_CONFIDENCE
20
Store matches at/above this confidence (0–100).
12. Public report intake
Variable
Default
Notes
ALTCHA_HMAC_KEY †
(empty)
Secret. Enables the self-hosted ALTCHA proof-of-work captcha on the public form for anonymous reporters; empty leaves the form captcha-free (honeypot + rate limits still apply). Widget assets are vendored and served same-origin — no CDN or CSP change. Replay protection uses the default cache (set CACHE_URL so it holds across processes).
RATELIMIT_INTAKE_ANON †
5/h
Per-IP limit for anonymous report submission.
RATELIMIT_INTAKE_USER †
20/h
Per-user limit for authenticated submission.
INTAKE_REPORT_RETENTION_DAYS †
365
Horizon after which intake PII is scrubbed (see prune_reports).
INTAKE_DISABLED †
False
Kill switch for the public /report/ form.
13. Logging & reverse proxy
Variable
Default
Notes
LOG_FORMAT
json
json (prod) or plain (dev).
LOG_LEVEL
INFO
Root log level.
TRUSTED_PROXY_COUNT
0
Number of trusted proxies appending to X-Forwarded-For. Set to your real proxy depth (e.g. 1) so per-IP rate limits and audit IPs reflect the true client and can't be spoofed. 0 ignores the header.
USE_X_FORWARDED_PROTO
False
Trust the proxy's X-Forwarded-Proto (sets SECURE_PROXY_SSL_HEADER). Required when TLS terminates at the proxy — without it SECURE_SSL_REDIRECT loops and secure cookies/CSRF never engage. Only enable when all traffic passes a proxy that sets (never forwards) the header.
CSRF_TRUSTED_ORIGINS
(empty)
Comma-separated origins for CSRF origin checking behind a proxy, e.g. https://advisoryhub.example.org. Pair with USE_X_FORWARDED_PROTO.
/healthz, /readyz and /metrics are exempt from the prod SSL redirect
(SECURE_REDIRECT_EXEMPT in base.py) so plain-HTTP kubelet probes and
Prometheus scrapes see real status codes instead of 301s.
Optional release tag on Sentry events. Read straight from the OS env (common/sentry.py).
PROMETHEUS_WORKER_METRICS_PORT
0
Set on the worker only (compose uses 9808); 0 disables its exporter.
PROMETHEUS_MULTIPROC_DIR
(unset)
Required for multi-worker gunicorn. A writable, empty-at-boot tmpfs so the custom advisoryhub_* counters aggregate across workers. Read straight from the OS env.
15. CSP, rate-limiting, health, audit retention
Variable
Default
Notes
CSP_REPORT_ONLY
False
CSP is enforced by default; set True for Report-Only while diagnosing a new violation.
CSP_REPORT_URI
(empty)
Optional collector URL for the report-uri directive.
RATELIMIT_ENABLE
True
Master rate-limit switch (dev/test set False).
READYZ_INCLUDE_BROKER
False
Add a Celery-broker probe to /readyz.
READYZ_INCLUDE_PUB_REPO
False
Add a git ls-remote of the publication repo to /readyz.
AUDIT_ACCESS_LOG_RETENTION_DAYS
90
Drop access-log monthly partitions older than this.
AUDIT_ACCESS_LOG_RETENTION_ENABLED
True
Enable the daily partition-maintenance task.
Security headers (__Host- cookies, HSTS, SSL redirect, X-Frame-Options,
nonce CSP, Permissions-Policy) are set in code (base.py / prod.py), not via
env vars — see running-in-production.md §6.