Skip to content

Configuration

Every Repro setting is a single environment variable. The bundled compose.yaml reads them from .env in the same directory. This page is the exhaustive reference; grab .env.example for a well-commented template.

Required

You need exactly four values to boot:

VariableDescriptionGenerate with
POSTGRES_PASSWORDPostgres password. Kept internal to the Docker network.openssl rand -hex 32
BETTER_AUTH_URLBase URL your dashboard is served at. Must match the origin visitors use (session cookies).
BETTER_AUTH_SECRETSession-cookie signing secret.openssl rand -hex 32
ATTACHMENT_URL_SECRETSigning key for time-limited attachment download URLs.openssl rand -hex 32

Without these four the stack refuses to start (compose refuses interpolation; the dashboard refuses to boot).

Compose overrides

Optional knobs the bundled compose reads:

VariableDefaultDescription
REPRO_VERSIONlatestPin the image tag. Recommended in prod so you control when you upgrade.
PORT3000Host port the dashboard binds to. Container internal port is always 3000.
POSTGRES_USERreproPostgres user name.
POSTGRES_DBreproPostgres database name.

The compose file wires DATABASE_URL internally to the postgres service — don't set it yourself when using compose.

Storage

See Storage for per-provider endpoints.

VariableDefaultDescription
STORAGE_DRIVERlocallocal (Docker volume) or s3 (any S3-compatible endpoint).
STORAGE_LOCAL_ROOT/data/attachmentsPath inside the container. Compose mounts the volume here.
S3_BUCKETBucket name (s3 only).
S3_REGIONRegion (s3 only). auto for R2; any string for MinIO.
S3_ACCESS_KEY_IDAccess key (s3 only).
S3_SECRET_ACCESS_KEYSecret (s3 only).
S3_ENDPOINTLeave empty for AWS; per-provider URL otherwise.
S3_VIRTUAL_HOSTEDfalsetrue for AWS S3 (virtual-hosted addressing); false elsewhere.

Email

Magic-link sign-in + invite delivery.

VariableDefaultDescription
MAIL_PROVIDERconsoleconsole (logs the link to stdout), smtp (real email), ethereal (nodemailer preview).
SMTP_HOSTSMTP server hostname (when MAIL_PROVIDER=smtp).
SMTP_PORT587SMTP port.
SMTP_USERSMTP auth user.
SMTP_PASSSMTP auth password.
SMTP_FROMRepro <no-reply@localhost>From: header on sent mail.

console is the right default for the first boot — grab the magic-link URL from docker compose logs dashboard | grep link: and paste it into your browser. Switch to smtp once you want real users to receive email.

OAuth sign-in

Buttons are hidden on the sign-in page when the secrets are blank. Leave the fields empty to disable a provider.

VariableDescription
GITHUB_CLIENT_IDGitHub OAuth App client id.
GITHUB_CLIENT_SECRETGitHub OAuth App client secret.
GOOGLE_CLIENT_IDGoogle OAuth client id.
GOOGLE_CLIENT_SECRETGoogle OAuth client secret.

Callback URLs you'll need in the OAuth app configuration:

  • <BETTER_AUTH_URL>/api/auth/callback/github
  • <BETTER_AUTH_URL>/api/auth/callback/google

GitHub Issues sync

Uses a GitHub App (not OAuth). See Integrations → GitHub for the walkthrough.

VariableDefaultDescription
GITHUB_APP_IDNumeric App ID from the App's settings page.
GITHUB_APP_PRIVATE_KEYLiteral PEM contents (newlines as \n) or an absolute path to a .pem.
GITHUB_APP_WEBHOOK_SECRETWhatever you pasted into the App's Webhook secret field.
GITHUB_APP_SLUGreproSlug from the App's public URL (e.g. https://github.com/apps/<slug>).
GITHUB_WEBHOOK_MAX_BYTES1048576Max webhook body before HMAC validation. Keep at the default.

Database connection + pool

DATABASE_URL is set by the compose file to the internal postgres service. If you're running the dashboard outside compose (pointing at a managed Postgres), set it yourself to postgres://user:pass@host:5432/dbname.

VariableDefaultDescription
DATABASE_URLPostgres connection string. Required if not using the bundled compose.
DB_POOL_MAX10Max concurrent connections per dashboard worker.
DB_STATEMENT_TIMEOUT_MS30000Kills any single query exceeding this many ms.
DB_IDLE_TX_TIMEOUT_MS10000Kills connections held open by a leaked BEGIN.

Intake limits

Tune the SDK intake path. Defaults are safe — only change if you have a specific reason.

VariableDefaultDescription
INTAKE_RATE_PER_KEY60Reports / minute / project.
INTAKE_RATE_PER_IP20Reports / minute / IP.
INTAKE_RATE_PER_KEY_ANON10Stricter bucket for anonymous submissions (no reporter.userId).
INTAKE_MAX_BYTES5242880Max total multipart payload (5 MB).
INTAKE_REQUIRE_DWELLtrueReject submissions that omit _dwellMs. Set false during a rolling SDK upgrade only.
INTAKE_MIN_DWELL_MS1500Minimum ms between widget-open and submit (anti-bot).
INTAKE_REPLAY_MAX_BYTES1048576Max gzipped bytes per replay attachment.
REPLAY_FEATURE_ENABLEDtrueKill-switch for session replay across the whole install.
TRUST_XFFfalseTrust X-Forwarded-For. Only set true when behind a trusted reverse proxy — spoofable.

Auth rate limits

Protects /api/auth/sign-in and /api/auth/magic-link/verify from credential-stuffing / enumeration.

VariableDefaultDescription
AUTH_RATE_PER_IP_PER_15MIN5Max attempts per IP per 15-minute window.
AUTH_RATE_LIMIT_ENABLEDon in prod; off in dev/testExplicit override: true force-on, false force-off.
RATE_LIMIT_STOREmemorymemory (per-worker, fine for single replica) or postgres (shared across replicas).

Invites

VariableDefaultDescription
INVITE_RATE_PER_ADMIN5Invite emails / minute / admin. Catches runaway loops before SMTP quota does.

Runtime

VariableDefaultDescription
NODE_ENVproductionSet by the image. Don't override in .env.
NITRO_HOST0.0.0.0Bind address. Don't override.
NITRO_PORT3000Container internal port.

Validating your config

Compose can dry-run interpolation without starting anything:

bash
docker compose config

Anything missing or malformed surfaces immediately.

Released under the MIT License.