Skip to content

Configuration

All configuration is done via environment variables.

Server

VariableDefaultDescription
RUNGU_LISTEN0.0.0.0:3000HTTP listen address
RUNGU_DBrungu.dbSQLite database path
DATABASE_URL(unset)Override the database connection. When set, takes precedence over RUNGU_DB. Format: sqlite:path.db or postgres://user:pass@host/db.
RUNGU_CORS_ORIGINS(APP_URL only)Comma-separated CORS origins. Default: only APP_URL. Set to * to allow all (dev only).
RUNGU_RATE_LIMIT_PER_MIN300Max /api/* requests per minute per client IP (fixed window). 0 disables the limiter. Client IP is taken from X-Forwarded-For (first hop) when present, else the socket address.
RUNGU_AUTH_RATE_LIMIT_PER_MIN30Max /auth/* requests per minute per client IP. Stricter than the API limiter to blunt OAuth/login abuse. 0 disables it.
RUNGU_TRUST_PROXYfalseHonor X-Forwarded-For when resolving rate-limit client IPs. Enable only behind a trusted reverse proxy that overwrites the header; otherwise clients can spoof it. When false, the socket address is used.
RUNGU_SECURE_COOKIEtrueSet false for HTTP (no Secure flag on cookies). Accepts (case-insensitive): true|1|yes|on, false|0|no|off. Any other value exits with a fatal error — see Security.
RUST_LOGrungu=infoLog level (trace, debug, info, warn, error). Supports tracing_subscriber's EnvFilter syntax.

Auth (Session)

VariableDefaultDescription
APP_URLhttp://localhost:3000Base URL. Used to construct OAuth redirect URIs as {APP_URL}/auth/{provider}/callback.
APP_SECRET(required)JWT signing secret. Must be set — generate with openssl rand -hex 32. Process exits if not set.
ADMIN_EMAILS(empty)Comma-separated email allowlist that receives the admin role. Without this, no users are admins (status/project management is read-only). Example: ADMIN_EMAILS=owner@example.com,teammate@example.com.

Google OAuth

Set these to enable Google login:

VariableDescription
GOOGLE_CLIENT_IDGoogle OAuth client ID
GOOGLE_CLIENT_SECRETGoogle OAuth client secret

Redirect URI is constructed automatically as {APP_URL}/auth/google/callback — register that exact URL in the Google Cloud Console. There is no *_REDIRECT_URI override.

GitHub OAuth

Set these to enable GitHub login:

VariableDescription
GITHUB_CLIENT_IDGitHub OAuth App client ID
GITHUB_CLIENT_SECRETGitHub OAuth App client secret

The user:email scope is requested automatically. Redirect URI is constructed automatically as {APP_URL}/auth/github/callback — register that in your GitHub OAuth App settings.

Keycloak OAuth

Set these to enable Keycloak login:

VariableDescription
KEYCLOAK_URLKeycloak base URL (e.g., https://auth.example.com)
KEYCLOAK_REALMKeycloak realm name
KEYCLOAK_CLIENT_IDClient ID for Rungu in Keycloak
KEYCLOAK_CLIENT_SECRETClient secret for Rungu in Keycloak

Redirect URI is constructed automatically as {APP_URL}/auth/keycloak/callback. Realm administrators must enforce email verification upstream for email-based account linking to work.

Example .env

env
# Server
RUNGU_LISTEN=0.0.0.0:3000
RUNGU_DB=/data/rungu.db
RUST_LOG=rungu=info

# Auth
APP_URL=https://feedback.example.com
APP_SECRET=a1b2c3d4e5f6...   # generate with: openssl rand -hex 32
ADMIN_EMAILS=owner@example.com

# Google
GOOGLE_CLIENT_ID=123.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-abc

# GitHub
GITHUB_CLIENT_ID=Iv1.abc
GITHUB_CLIENT_SECRET=def123

# Keycloak (optional — only if you have Keycloak)
# KEYCLOAK_URL=https://auth.example.com
# KEYCLOAK_REALM=myorg
# KEYCLOAK_CLIENT_ID=rungu
# KEYCLOAK_CLIENT_SECRET=xyz789

# CORS — comma-separated, default = APP_URL only. Set to * for dev.
# RUNGU_CORS_ORIGINS=https://feedback.example.com,https://staging.example.com

# Set to false only for local HTTP development. Default true.
# RUNGU_SECURE_COOKIE=false

See .env.example for the canonical reference.

Provider Behavior

  • Empty/unset provider ENV = that provider is disabled.
  • Multiple providers can be active simultaneously.
  • Users are identified by email — same verified email across providers links to the same account.
  • The first login for an email creates the user (role member unless the email is in ADMIN_EMAILS). Subsequent logins from any provider reuse the existing account.
  • The user role is re-evaluated on every login: add an email to ADMIN_EMAILS and the user is auto-promoted on their next login.

Security

  • Verified-email gate. Accounts are linked by email only when the provider asserts email_verified: true. Google and Keycloak expose this via the standard email_verified userinfo claim; GitHub's verification is determined from the /user/emails endpoint (primary + verified). Logins with an unverified email are rejected with HTTP 403 before any DB write — this prevents cross-provider takeover via untrusted IdPs.
  • RUNGU_SECURE_COOKIE is strict. A typo like RUNGU_SECURE_COOKIE=False (capital F) will exit at startup with an actionable error rather than silently enabling secure cookies and breaking local HTTP login.
  • APP_SECRET is required and must be unique. It signs JWT session tokens — never reuse across deployments, never commit a real value.

See Auth Overview for the full identity model.

File Storage (Attachments)

VariableDefaultDescription
STORAGE_DRIVERfsStorage backend: fs (filesystem) or s3 (S3-compatible, planned)
RUNGU_STORAGE_DIR./uploadsDirectory for uploaded files (filesystem driver only)

Docker: Set RUNGU_STORAGE_DIR=/data/uploads to use the persisted volume.

S3-compatible (MinIO, R2, AWS S3): The s3 driver is accepted but not yet implemented. It will be available in v0.3.

See Attachments for format support and security details.