Configuration
Everything is configured with environment variables. .env.local.example in the repository lists them all with comments; the tables below explain what each one is for.
Core
| Variable | Purpose | |
|---|---|---|
SESSION_SECRET | Required | At least 32 characters; encrypts the session cookie. The app refuses to start in production without it. |
MODE | Optional | standalone (default) or organization. |
NEXT_PUBLIC_APP_URL | Optional | Public URL; used for OAuth redirects, same-origin checks, and the canonical and social-card URLs of public pages. Static pages read it at build time, so pass it to the image build as well when those URLs matter. |
GITDASH_TRUSTED_PROXY_HOPS | Optional | How many proxies in front of GitDash append to X-Forwarded-For: a positive integer, default 1. Rate limits key on the client IP, taken as the X-Forwarded-For entry this many hops from the right, because the left end is whatever the client sent. Set it when more than one proxy appends (for example a CDN in front of an ingress); with too low a value every user shares a proxy's IP, with too high a value clients can choose their own. Ignored on Vercel, which overwrites the header. Helm: config.trustedProxyHops. |
Organization mode and access control
| Variable | Purpose | |
|---|---|---|
GITHUB_CLIENT_ID | Organization | OAuth App client id (Continue with GitHub). |
GITHUB_CLIENT_SECRET | Organization | OAuth App client secret. |
DATABASE_URL | Organization | Postgres connection string: users, groups, grants, audit, alerts, reports, shared cache. |
GITDASH_ADMIN_GITHUB_IDS | Organization | Comma-separated numeric GitHub ids that are always admins. |
GITDASH_ALLOWED_ORGS | Optional | Comma-separated orgs whose active members may sign in; empty means any GitHub account (it lands on /pending). |
GITDASH_RBAC_ENFORCE | Optional | true enforces group permissions; false (default) keeps everyone's access during rollout. |
GITDASH_LANDING_PAGE | Optional | true shows the /welcome product page to signed-out visitors at /, with Sign in leading to /login. For the public product site; leave unset when self-hosting. |
Sync, webhooks and caching
| Variable | Purpose | |
|---|---|---|
GITHUB_TOKEN | Optional | Server token for the nightly sync crons, which run without a user session. |
CRON_SECRET | Optional | Bearer token for /api/cron/*; the routes answer 401 without it. |
GITHUB_WEBHOOK_SECRET | Optional | Verifies /api/webhooks/github signatures; without it every webhook is rejected. |
GITDASH_L2_CACHE | Optional | 0 keeps the API cache in memory only (default: shared Postgres cache when a database is set). |
GITDASH_GH_LOG | Optional | 1 logs every GitHub call with its route and remaining budget. |
| Variable | Purpose | |
|---|---|---|
RESEND_API_KEY, RESEND_FROM | Optional | Email delivery through Resend (preferred). |
SMTP_HOST, SMTP_USER, SMTP_PASS, SMTP_FROM | Optional | Generic SMTP instead of Resend (or SENDGRID_API_KEY). Admins can also set email in Settings → Email and digests. |
AI insights
Optional. Without a key every AI surface is hidden. Providers are tried in this order and any without a key is skipped; in organization mode an admin can also set a provider in Settings → AI provider.
| Variable | Purpose |
|---|---|
BAILIAN_API_KEY, BAILIAN_MODEL, BAILIAN_BASE_URL | Alibaba Cloud Bailian (Anthropic Messages API). |
GEMINI_API_KEY, GEMINI_MODEL | Google Gemini. |
QWEN_API_KEY, QWEN_MODEL | Qwen via DashScope. |
AI_DISABLED | true turns every AI surface off regardless of keys. |
AI_TIMEOUT_MS, AI_TOTAL_BUDGET_MS, AI_DAILY_TOKEN_BUDGET | Per-attempt timeout, per-request time budget and a per-instance daily token cap. |
Signed-in MCP (AI apps)
Off by default. It lets an AI app such as Claude or Cursor read your repositories at /mcp/me, read-only, after signing in through GitHub or with a personal MCP key. It needs a database and NEXT_PUBLIC_APP_URL, which must match the address people use; with it unset or different, the endpoints answer 503 instead of issuing tokens. See MCP server for how people connect.
| Variable | Purpose | |
|---|---|---|
GITDASH_MCP | Optional | true turns on /mcp/me, personal MCP keys and the Connected apps screens, plus, in organization mode, the OAuth endpoints under /oauth. Helm: config.mcp. |
MCP_ALLOW_DCR | Optional | true also accepts Dynamic Client Registration for apps that cannot publish a client metadata document. Default off. |
MCP_NATIVE_SCHEMES | Optional | Comma-separated custom redirect schemes allowed for desktop apps, for example cursor,vscode. Default none; http, https, javascript and similar are always refused. |
MCP_PREVIOUS_SESSION_SECRET | Optional | When you rotate SESSION_SECRET, put the old value here for 30 days, the longest an app token or personal key lives, so connected apps and keys keep working; then remove it. |
Add a second callback URL to the same GitHub OAuth App: <origin>/api/auth/callback/mcp, next to the existing <origin>/api/auth/callback. The web sign-in now names its callback explicitly, so both keep working.
Standalone mode: set GITDASH_MCP=true, DATABASE_URL and NEXT_PUBLIC_APP_URL. There is no OAuth App, so /mcp/me accepts personal MCP keys only and the /oauth endpoints stay off; no callback URL is needed. Without DATABASE_URL, /mcp/me stays off and creating a key answers 409, because a key is only issued when it can be revoked.
Expired and revoked grants are deleted by the retention job. /api/cron/sync runs it, so self-hosted installs that already schedule that cron need nothing more; without the cron, old rows stay until you run it.
Demo data
NEXT_PUBLIC_DEMO_MODE=true (or ?demo=1 on a page) replaces GitHub data with a fictional organization, for screenshots and trials. You still sign in.