Backend

Backend configuration#

cp .env.example .env

Required#

VariableWhat it is
DATABASE_URLPostgreSQL connection string
CRYPTO_SECRETSigns sessions — openssl rand -hex 32

CRYPTO_SECRET is generated once and kept. Changing it signs every user out.

Optional#

VariableDefaultWhat it does
PORT3000Port to listen on.
META_NAMEP-Stream: BackendName shown to people who add this backend.
META_DESCRIPTIONa short taglineDescription shown next to the name.
DB_PROVIDERplain postgresSet to supabase to use DATABASE_URL_SUPABASE instead.
DATABASE_URL_SUPABASE—Only read when DB_PROVIDER=supabase.
CAPTCHAfalsetrue puts Cloudflare Turnstile on sign up.
CAPTCHA_CLIENT_KEY—Turnstile site key. Required when CAPTCHA is on.
CAPTCHA_SECRET—Turnstile secret key. Required when CAPTCHA is on.

Metrics#

Counters survive restarts on their own — they are written to a metrics table in the same Postgres database, so there is nothing extra to mount.

/metrics/daily, /metrics/weekly and /metrics/monthly show the same counters as /metrics, counted over the last 24 hours, 7 days or 30 days.

Keep Postgres off the internet#

Docker writes its own iptables rules and goes straight through ufw, so a published 5432 is your database on the public internet regardless of what your firewall says. Use expose rather than ports, and let the backend reach it by service name.