Environment Variables

Complete reference for all GritCMS environment variables.

Overview

GritCMS is configured through a single .env file in the monorepo root. Copy the example file to get started:

cp .env.example .env

All variables are loaded at startup by the Go backend. The frontend apps read their configuration from next.config files that reference the API URL.

Application Settings

Core settings that control the API server behavior.

VariableDefaultDescription
APP_NAMEmyappApplication name used in logs and email headers
APP_ENVdevelopmentEnvironment mode: development, staging, or production
APP_PORT8080Port the API server listens on
APP_URLhttp://localhost:8080Full base URL of the API (used for OAuth callbacks and links)
APP_NAME=gritcms
APP_ENV=development
APP_PORT=8080
APP_URL=http://localhost:8080

Database

GritCMS uses PostgreSQL as its primary database, connected via a standard connection string.

VariableDefaultDescription
DATABASE_URL--PostgreSQL connection string
# Local development (via Docker Compose)
DATABASE_URL=postgres://grit:grit@localhost:5432/gritcms?sslmode=disable
 
# Production (e.g., Neon, Supabase, or self-hosted)
DATABASE_URL=postgres://user:password@host:5432/dbname?sslmode=require

See the Database Configuration guide for detailed setup instructions.

Authentication (JWT)

JSON Web Tokens are used for API authentication. Access tokens are short-lived; refresh tokens provide seamless re-authentication.

VariableDefaultDescription
JWT_SECRETchange-me-in-productionSecret key for signing JWT tokens. Must be changed in production.
JWT_ACCESS_EXPIRY15mAccess token lifetime (e.g., 15m, 1h)
JWT_REFRESH_EXPIRY168hRefresh token lifetime (default: 7 days)
JWT_SECRET=a-long-random-string-at-least-32-characters
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=168h

OAuth2 Social Login

Optional social login via Google and GitHub. Leave blank to disable.

VariableDefaultDescription
GOOGLE_CLIENT_ID--Google OAuth 2.0 Client ID
GOOGLE_CLIENT_SECRET--Google OAuth 2.0 Client Secret
GITHUB_CLIENT_ID--GitHub OAuth App Client ID
GITHUB_CLIENT_SECRET--GitHub OAuth App Client Secret
OAUTH_FRONTEND_URLhttp://localhost:3001URL to redirect to after successful OAuth login

Get Google credentials at Google Cloud Console. Get GitHub credentials at GitHub Developer Settings.

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
OAUTH_FRONTEND_URL=http://localhost:3001

Redis

Redis powers caching, background job processing (Asynq), and cron scheduling. It is optional for development -- if not configured, caching and background jobs are disabled.

VariableDefaultDescription
REDIS_URLredis://localhost:6379Redis connection URL
REDIS_URL=redis://localhost:6379

File Storage

GritCMS supports three S3-compatible storage backends. Set STORAGE_DRIVER to choose which one to use.

VariableDefaultDescription
STORAGE_DRIVERminioActive storage driver: minio, r2, or b2

MinIO (Local Development)

VariableDefaultDescription
MINIO_ENDPOINThttp://localhost:9000MinIO server URL
MINIO_ACCESS_KEYminioadminAccess key
MINIO_SECRET_KEYminioadminSecret key
MINIO_BUCKETmyapp-uploadsBucket name for uploads
MINIO_REGIONus-east-1Region
MINIO_USE_SSLfalseEnable SSL for MinIO connection

Cloudflare R2

VariableDefaultDescription
R2_ENDPOINT--R2 S3-compatible endpoint URL
R2_ACCESS_KEY--R2 Access Key ID
R2_SECRET_KEY--R2 Secret Access Key
R2_BUCKETmyapp-uploadsBucket name
R2_REGIONautoAlways auto for R2

Backblaze B2

VariableDefaultDescription
B2_ENDPOINT--B2 S3-compatible endpoint URL
B2_ACCESS_KEY--B2 keyID
B2_SECRET_KEY--B2 applicationKey
B2_BUCKETmyapp-uploadsBucket name
B2_REGIONus-west-004Must match your bucket region

See the File Storage guide for detailed provider setup.

Email

GritCMS uses the Resend API for sending transactional and marketing emails.

VariableDefaultDescription
RESEND_API_KEYre_your_api_keyResend API key (starts with re_)
MAIL_FROMnoreply@myapp.devDefault sender email address
RESEND_API_KEY=re_your_actual_api_key
MAIL_FROM=hello@yourdomain.com

See the Email Configuration guide for provider setup details.

CORS

Controls which frontend origins can access the API. Required for the admin and web apps to communicate with the backend.

VariableDefaultDescription
CORS_ORIGINShttp://localhost:3000,http://localhost:3001Comma-separated list of allowed origins
CORS_ORIGINS=http://localhost:3000,http://localhost:3001

In production, set this to your actual domain(s): https://admin.yourdomain.com,https://yourdomain.com.

GORM Studio

A built-in visual database browser available at /studio on the API server.

VariableDefaultDescription
GORM_STUDIO_ENABLEDtrueEnable or disable GORM Studio
GORM_STUDIO_USERNAMEadminLogin username
GORM_STUDIO_PASSWORDstudioLogin password

AI Integration

Optional AI-powered text generation using Claude, OpenAI, or Gemini.

VariableDefaultDescription
AI_PROVIDERclaudeAI provider: claude, openai, or gemini
AI_API_KEY--API key for the chosen provider
AI_MODELclaude-sonnet-4-5-20250929Model identifier

Observability -- Pulse

Performance monitoring, request tracing, and error tracking dashboard at /pulse/ui/.

VariableDefaultDescription
PULSE_ENABLEDtrueEnable or disable the Pulse dashboard
PULSE_USERNAMEadminDashboard login username
PULSE_PASSWORDpulseDashboard login password

Security -- Sentinel

Web Application Firewall (WAF), rate limiting, and threat detection dashboard at /sentinel/ui.

VariableDefaultDescription
SENTINEL_ENABLEDtrueEnable or disable Sentinel
SENTINEL_USERNAMEadminDashboard login username
SENTINEL_PASSWORDsentinelDashboard login password
SENTINEL_SECRET_KEYchange-meSecret key for Sentinel JWT sessions

Production Checklist

Before deploying to production, ensure you have:

  • Changed JWT_SECRET to a strong random string (32+ characters)
  • Set APP_ENV=production
  • Configured a production DATABASE_URL with SSL enabled
  • Set CORS_ORIGINS to your actual domains
  • Changed all default passwords (GORM_STUDIO_PASSWORD, PULSE_PASSWORD, SENTINEL_PASSWORD, SENTINEL_SECRET_KEY)
  • Configured a real RESEND_API_KEY for email delivery
  • Set up a production storage driver (r2 or b2) instead of local MinIO