Skip to content
Reference

Environment variables

Every environment variable RedScribe reads, grouped by area, with its purpose and default.

All configuration is via environment variables, normally set in .env (copied from .env.example). This page is the complete, authoritative list. For the reasoning behind the encryption, audit, and backup groups specifically, see Encryption model, Audit log, and Backup & restore. This page is just the “what,” and those are the “why.”

Variable Purpose Default
DJANGO_SETTINGS_MODULE Which settings module to run, config.settings.dev or config.settings.prod. See Configuration. config.settings.dev
DJANGO_SECRET_KEY Secret. Session/CSRF signing key. Generate a random 50-char value; never reuse the placeholder. Under Docker Compose, delivered as a file-based secret by default (secrets/django_secret_key.txt) — see the tip above. change-me-to-a-random-50-char-value
DJANGO_DEBUG Django debug mode: verbose error pages, no static file caching. Never enable in a real deployment. true
DJANGO_ALLOWED_HOSTS Comma-separated hostnames Django will serve; must include whatever NGINX_SERVER_NAME is set to. localhost,127.0.0.1
REDSCRIBE_ALLOW_DEBUG_IN_PROD Explicit opt-in escape hatch: config.settings.prod normally refuses to start at all with DJANGO_DEBUG=true. Set to 1 only for a specific debugging session, never leave it set. See Local development. (unset)
DJANGO_LOG_LEVEL Log level for Django’s root, django, and django.request/django.security loggers (console output). INFO
Variable Purpose Default
NGINX_SERVER_NAME Your domain: the tailnet hostname for Method 1, or your own domain for Method 2. Leave unset for nginx’s _ catch-all default (Method 3). (unset)
GUNICORN_WORKERS Gunicorn worker process count. Leave unset to auto-size to (2 * cpu cores) + 1 at container startup. (auto-sized)

docker-compose.yml caps each service’s memory and CPU. Defaults match the “Solo” tier from Requirements & sizing — the documented floor for “just trying it out”. Docker’s own cpus: refuses to start a container at all if the value exceeds the host’s actual CPU count, so the shipped default has to work unmodified on that floor, not just on a beefier host; raise these for a bigger tier, or set them very high to effectively remove the cap.

Variable Purpose Default
WEB_MEM_LIMIT Memory cap for the web container. Gets the larger share, since report export (WeasyPrint/docxtpl) is the most memory-hungry thing this app does. 5g
WEB_CPUS CPU cap for web, in cores (fractional allowed). 1
DB_MEM_LIMIT Memory cap for the db container. 2g
DB_CPUS CPU cap for db. 0.5
NGINX_MEM_LIMIT Memory cap for nginx. 256m
NGINX_CPUS CPU cap for nginx. 0.5
Variable Purpose Default
POSTGRES_DB Database name. redscribe
POSTGRES_USER Database user. redscribe
POSTGRES_PASSWORD Secret. Database password. Set this to something of your own choosing. Under Docker Compose, delivered as a file-based secret by default (secrets/postgres_password.txt) — see the tip above. change-me
POSTGRES_HOST Database hostname: db under Docker Compose, localhost for Method 4. db
POSTGRES_PORT Database port. 5432
POSTGRES_SSLMODE TLS mode for the Postgres connection (prefer, require, verify-ca, verify-full, …). The shipped default is safe for the same-host Docker Compose topology, where db and web only ever talk over the Docker-internal network, but prefer silently allows a plaintext fallback and never validates the server certificate. Set this to verify-full if POSTGRES_HOST ever points at a separate host. prefer
POSTGRES_SSLROOTCERT Path to a CA certificate file to validate the Postgres server’s certificate against. Only meaningful alongside verify-ca/verify-full. (unset)
Variable Purpose Default
REDSCRIBE_ROOT_KEY Secret. Instance root key wrapping every engagement’s own per-project data key. Generate with python manage.py generate_root_key. Required in production, since config.settings.prod refuses to start without it. Under Docker Compose this is mounted as a Docker secret from secrets/root_key.txt instead, and this var is left unset; only set it directly for a non-Docker/bare-metal run or CI. Never commit the real value. (unset)
Variable Purpose Default
OAUTH_PROVIDER "google", "microsoft", or empty for local-auth-only. (empty)
OAUTH_ALLOWED_DOMAIN The single email domain OAuth sign-in is locked to. Required whenever OAUTH_PROVIDER is set. RedScribe is single-tenant per instance, so anyone authenticating with a valid provider account outside this domain is rejected before an account is created. (unset)
SESSION_IDLE_TIMEOUT_SECONDS Signs a session out after this many seconds of no requests, automatic-logoff behavior, distinct from the session’s fixed 4-hour cap (SESSION_COOKIE_AGE, not separately configurable). 1800 (30 min)
LOCKOUT_THRESHOLD Failed login attempts before an account is locked out. 5
LOCKOUT_DURATION_SECONDS How long a lockout lasts, in seconds. 86400 (24h)
IP_LOCKOUT_THRESHOLD Failed login attempts from one source IP before that address is locked out, independent of which usernames it tried. Higher than LOCKOUT_THRESHOLD so shared/NAT’d networks aren’t locked out too easily. See Per-IP lockout. 20
IP_LOCKOUT_DURATION_SECONDS Base per-IP lockout window. Doubles with each further threshold’s worth of failures from that address, up to the cap below. 3600 (1h)
IP_LOCKOUT_MAX_DURATION_SECONDS Upper bound the escalating per-IP lockout window never exceeds. 86400 (24h)
SUPERADMIN_RATE_LIMIT_WINDOW_SECONDS Rate-limit window for Superadmin-sensitive actions. 60
SUPERADMIN_RATE_LIMIT_MAX_ATTEMPTS Max attempts allowed within that window. 10
MFA_THROTTLE_MAX_ATTEMPTS Wrong TOTP codes allowed within the throttle window, separate from login lockout above. Not listed in .env.example, since the default rarely needs changing. See Authentication & sessions. 5
MFA_THROTTLE_WINDOW_SECONDS Throttle window MFA_THROTTLE_MAX_ATTEMPTS applies within. 30
PWNED_PASSWORD_CHECK_ENABLED Checks new passwords against Have I Been Pwned’s breach corpus (a k-anonymity API, so only a 5-char hash prefix ever leaves the instance). Set to false for air-gapped deployments with no outbound internet access. true

Only required when OAUTH_PROVIDER selects that provider.

Variable Purpose Default
GOOGLE_OAUTH_CLIENT_ID Required only when OAUTH_PROVIDER=google. Create at console.cloud.google.com/apis/credentials: an OAuth 2.0 Client ID of type “Web application,” with an authorized redirect URI of https://<your-domain>/accounts/social/google/login/callback/. (unset)
GOOGLE_OAUTH_CLIENT_SECRET Secret. Paired secret for the above. File-based delivery available (see the tip above); not mounted by default since OAuth is opt-in. (unset)
MICROSOFT_OAUTH_CLIENT_ID Required only when OAUTH_PROVIDER=microsoft. Create at entra.microsoft.com under App registrations, with a redirect URI of https://<your-domain>/accounts/social/microsoft/login/callback/. (unset)
MICROSOFT_OAUTH_CLIENT_SECRET Secret. Paired secret for the above. File-based delivery available (see the tip above); not mounted by default since OAuth is opt-in. (unset)
MICROSOFT_OAUTH_TENANT_ID Leave as organizations unless the consultancy needs a specific Entra ID tenant restricted at the login-screen level too, in which case set it to that tenant’s ID. This is a stricter belt-and-braces measure alongside OAUTH_ALLOWED_DOMAIN, not a replacement for it. organizations

Password reset links and change notifications. Leave EMAIL_HOST blank to use the console backend (emails printed to the app log), which is fine for local/dev, but not for production.

Variable Purpose Default
EMAIL_HOST SMTP host. (empty, console backend)
EMAIL_PORT SMTP port. 587
EMAIL_HOST_USER SMTP username. (empty)
EMAIL_HOST_PASSWORD Secret. SMTP password. File-based delivery available (see the tip above); not mounted by default since SMTP is opt-in (console backend otherwise). (empty)
EMAIL_USE_TLS Use TLS for the SMTP connection. true
DEFAULT_FROM_EMAIL From-address on outgoing mail. RedScribe <no-reply@redscribe.local>
PASSWORD_RESET_TIMEOUT_SECONDS How long a password reset link stays valid. 3600 (1h)
Variable Purpose Default
AUDIT_LOG_RETENTION_DAYS How far back Audit Log entries are kept before eligible for purge. See Audit log for details, including how the default compares to PCI DSS/NIST/CIS. 2190 (6 years, HIPAA’s general documentation-retention rule)
Variable Purpose Default
BACKUP_DIR Where create_backup writes encrypted backups, server-side. /app/backups
BACKUP_ENCRYPTION_PASSPHRASE Encrypts/decrypts backups. Required for create_backup to run unattended (host cron); restore_backup prompts interactively if this isn’t set. Same trust level as this app’s other .env secrets, so never commit the real value. (empty)
BACKUP_RETENTION_DAYS How long create_backup keeps old backups in BACKUP_DIR before pruning them. 30