Skip to content

Configuration

All settings come from environment variables. In Docker, put them in .env next to the compose file; .env.example lists every one. In development all of them are optional. Production reads everything from the environment; see Deploying for the ones a first deploy needs.

Core

Variable Default What it does
DJANGO_SETTINGS_MODULE core.settings.development core.settings.production on a server
SECRET_KEY Django's secret key; required in production
DEBUG false Never on in production
DATABASE_URL postgres://postgres:postgres@localhost:5432/postgres PostgreSQL 17
REDIS_URL redis://localhost:6379/0 Celery's broker and the cache
CACHE_URL REDIS_URL A separate cache, if wanted
LOG_LEVEL INFO

Feeds and articles

Variable Default What it does
FEED_BACKOFF_BASE_MINUTES 30 First retry delay for a failing feed, doubling each time
FEED_MAX_BACKOFF_HOURS 24 Longest retry delay
FEED_STALE_DAYS 60 A feed with nothing new for this long is shown as stale
ARTICLE_REFETCH_DAYS 7 Refetch undated articles daily while this young; 0 turns it off
ARTICLE_TEXT_DAYS 0 Drop older articles' text (not bookmarked ones); 0 keeps it

Site and accounts

Variable Default What it does
SITE_NAME Curated Search Initial site name (then edited in the admin); error email subjects
SIGNUP_OPEN false Initial signup switch, read by the first migrate only
INVITATION_EXPIRY_DAYS 7 How long an invitation link works
STAFF_REQUIRE_2FA true Staff must use an authenticator app or passkey
SITE_OWNER Shown on the privacy page
CONTACT_EMAIL Privacy page and footer
SITE_URL https://DOMAIN Links in emails

Production

Variable Default What it does
DOMAIN The site's domain; also the default for the next two
ALLOWED_HOSTS DOMAIN Comma-separated
CSRF_TRUSTED_ORIGINS https://DOMAIN Comma-separated
POSTGRES_PASSWORD The database superuser: backups and admin work only
APP_DB_PASSWORD The app's own database role (deploy/initdb.sh)
REDIS_PASSWORD openssl rand -hex 32; REDIS_URL is built from it
ADMIN_URL The admin's path; keep it secret
IMAGE :latest Pin an image version, e.g. ghcr.io/joeriksson/curated-search-next:sha-abc1234
TRUSTED_PROXY_COUNT 1 Reverse proxies in front of the app; 0 if none
SECURE_SSL_REDIRECT true The app redirects http to https itself
SECURE_HSTS_SECONDS 3600 Raise (e.g. 31536000) once HTTPS works well
CSP_REPORT_ONLY false true: the Content-Security-Policy only reports
BACKUP_HOUR_UTC 3 Daily database dump into ./backups
BACKUP_KEEP 14 Dumps kept

Email

Without EMAIL_HOST, emails are only logged.

Variable Default What it does
EMAIL_HOST SMTP server, e.g. smtp.protonmail.ch
EMAIL_PORT 587 587 = STARTTLS, 465 = implicit TLS
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD Proton: an SMTP token
EMAIL_USE_TLS true on 587 STARTTLS
EMAIL_USE_SSL true on 465 Implicit TLS
EMAIL_TIMEOUT 15 Seconds
DEFAULT_FROM_EMAIL Sender of the site's emails
ADMINS Who gets error reports and monitoring alerts
SERVER_EMAIL DEFAULT_FROM_EMAIL Sender of error reports

Limits, statistics and monitoring

Variable Default What it does
RATE_LIMIT_SEARCH 120/m Per IP (or account); empty means no limit
RATE_LIMIT_SEARCH_FEED 30/m Search Atom feeds
RATE_LIMIT_SUGGEST 10/h Feed suggestions
SEARCH_STATS true Daily search counts for the insights page
SEARCH_STATS_DAYS 90 How long they are kept
SECURITY_LOG_DAYS 90 Security events kept in the database
MONITOR_REFRESH_LATE_MINUTES 3 x the refresh interval Alert ADMINS when feeds haven't refreshed for this long
MONITOR_FEED_FAILURES 5 ...or a feed has failed this many times in a row