Skip to content

Configuration

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.
config.settings.dev manage.py and config/celery.py default DEBUG=True, HTTP cookies, relaxed hosts.
config.settings.prod config/wsgi.py and config/asgi.py default DEBUG=False, HSTS + SSL redirect, WhiteNoise compressed/manifest static, Prometheus multiprocess notes.
config.settings.test pyproject.toml (pytest) 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.
DJANGO_TIME_ZONE UTC Keep UTC.

3. Database & cache

Variable Default Notes
DATABASE_URL postgres://advisoryhub:advisoryhub@localhost:5432/advisoryhub 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.
OIDC_RP_SIGN_ALGO RS256 ID-token signature algorithm (dev Kanidm uses ES256).
OIDC_VERIFY_SSL True 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).

8. Publication Git repository

See integrations.md §2.

Variable Default Notes
PUB_REPO_URL (empty) Required to publish. SSH (git@…) or HTTPS URL.
PUB_REPO_BRANCH main Branch to push to.
PUB_REPO_AUTH ssh ssh or token.
PUB_REPO_SSH_KEY_PATH (empty) Secret. Required if ssh. Path to the deploy private key, e.g. /run/secrets/pub_repo_ssh_key.
PUB_REPO_TOKEN (empty) Secret. Required if token. PAT/access token (stripped from every error, audit, and notification surface).
PUB_COMMIT_AUTHOR_NAME AdvisoryHub Bot Commit author name.
PUB_COMMIT_AUTHOR_EMAIL advisoryhub-bot@example.org Commit author email.
PUB_OSV_PATH_TEMPLATE osv/{year}/{advisory_id}.json OSV output path; placeholders {year}, {advisory_id}.
PUB_CSAF_PATH_TEMPLATE csaf/{year}/{advisory_id}.json CSAF output path.
PUB_CVE_PATH_TEMPLATE cves/{year}/{bucket}/{cve_id}.json CVE-record path (mirrors the cvelistV5 layout); placeholders {year}, {bucket}, {cve_id}.
PUB_CVE_ASSIGNER_ORG_ID (empty) Required to publish a CVE-assigned advisory. The EF CNA's v4 UUID — publishing fails loudly while empty.
PUB_CVE_ASSIGNER_SHORT_NAME eclipse CNA short name written into the CVE record.

9. GHSA / GitHub App & PMI

Off by default. See integrations.md §3.

Variable Default Notes
GHSA_FEATURE_ENABLED False Master switch for the GitHub Security Advisory integration.
GITHUB_APP_ID 0 Required if enabled. Numeric GitHub App id.
GITHUB_APP_PRIVATE_KEY_PATH (empty) Secret. Preferred. File path to the App private key, e.g. /run/secrets/github_app_private_key.
GITHUB_APP_PRIVATE_KEY (empty) Secret. Inline key — dev fallback only; leave empty in prod.
GITHUB_APP_WEBHOOK_SECRET (empty) Secret. HMAC key verifying inbound webhooks.
GITHUB_APP_API_BASE_URL https://api.github.com Override for GitHub Enterprise.
PMI_API_BASE_URL https://projects.eclipse.org/api Eclipse PMI (project↔repo) API.
PMI_API_TOKEN (empty) Secret (if set). Usually blank — PMI is public.
PMI_SYNC_INTERVAL_HOURS 6 Beat cadence for the repo-mirror refresh.

10. Security-team roster sync

Off by default. See integrations.md §4.

Variable Default Notes
PMI_ROSTER_SYNC_ENABLED False Pre-provision notification-only shadow users for security-team members.
PMI_ROSTER_SYNC_INTERVAL_HOURS 24 Beat cadence for roster refresh.
ECLIPSE_API_BASE_URL https://api.eclipse.org Authenticated Eclipse API base.
ECLIPSE_API_TOKEN_URL https://auth.eclipse.org/auth/realms/eclipse/protocol/openid-connect/token OAuth2 client-credentials token endpoint.
ECLIPSE_API_CLIENT_ID (empty) Secret. Required if enabled.
ECLIPSE_API_CLIENT_SECRET (empty) Secret. Required if enabled.
ECLIPSE_API_SCOPE (empty) Optional space-separated scope(s).

11. LLM duplicate detection (similarity)

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.

14. Observability

See observability.md.

Variable Default Notes
SENTRY_DSN (empty) Secret. Empty disables Sentry.
SENTRY_ENVIRONMENT (unset) Environment tag, e.g. production.
SENTRY_TRACES_SAMPLE_RATE 0 Tracing sample rate (0.0–1.0).
SENTRY_RELEASE (unset) 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.