Environment Variables
Reference for configuring LaunchKit Pro. Use placeholder values in docs and .env.example only. Store real secrets in your server environment or secrets manager — never in git.
Quoting values with spaces
Quote env values that contain spaces, for example:
APP_NAME="LaunchKit Pro API"Do not manually source .env in shell — parsing breaks. Use systemd EnvironmentFile= or your process manager.
Required before register/login
Set DATABASE_URL, JWT_ACCESS_SECRET, and JWT_REFRESH_SECRET before testing auth. Missing JWT secrets often cause /auth/register HTTP 500.
Backend — App
| Variable | Example | Description |
|---|---|---|
NODE_ENV | development | development, production, or test |
PORT | 4000 | API listen port |
APP_NAME | LaunchKit Pro API | Display name |
APP_URL | http://localhost:4000 | Public backend URL |
FRONTEND_URL | http://localhost:3000 | Allowed CORS origin and auth email links (also called app frontend URL in some guides) |
CORS_ALLOWED_ORIGINS | http://localhost:3000,http://127.0.0.1:3000 | Comma-separated browser origins (FRONTEND_URL and localhost defaults are always merged) |
CORS_ALLOW_PRIVATE_NETWORK_DEV | false | Allow CORS_DEV_LAN_REGEX matches in production (default off) |
CORS_DEV_LAN_REGEX | ^http://192\.168\.0\.\d+:3000$ | Optional LAN origin pattern for local device testing |
Local LAN frontend testing
To open the dashboard from a phone or another machine on your network (e.g. http://192.168.0.101:3000), add your IP to backend .env:
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://192.168.0.101:3000Or rely on the dev LAN regex (active when NODE_ENV=development):
CORS_DEV_LAN_REGEX=^http://192\.168\.0\.\d+:3000$In production, LAN regex is disabled unless you explicitly set CORS_ALLOW_PRIVATE_NETWORK_DEV=true. Never use a wildcard — list only trusted HTTPS origins:
CORS_ALLOWED_ORIGINS=https://app.launchkitlabs.com,https://launchkitlabs.com,https://docs.launchkitlabs.comBackend — AI provider
Default AI_PROVIDER=MOCK — no OpenAI or Gemini keys required for install.
| Variable | Example | Description |
|---|---|---|
AI_PROVIDER | MOCK | Active provider: MOCK, OPENAI, or GEMINI |
AI_DEFAULT_MODEL | (empty) | Optional model override |
AI_OPENAI_MODEL | gpt-4.1-mini | Default OpenAI model when using OpenAI |
AI_GEMINI_MODEL | gemini-2.5-flash | Default Gemini model when using Gemini |
OPENAI_API_KEY | (empty) | Required only when AI_PROVIDER=OPENAI |
GEMINI_API_KEY | (empty) | Required only when AI_PROVIDER=GEMINI |
AI_MONTHLY_GENERATION_LIMIT | 100 | System ceiling combined with plan limits |
AI_TEST_USER_MONTHLY_LIMIT | 5 | Monthly generation cap for test accounts |
AI_TEST_USER_EMAILS | testuser@launchkitlabs.com,test@launchkitlabs.com | Comma-separated test account emails |
AI_DEMO_RESTRICTED_EMAILS | demo@launchkitlabs.com | Demo accounts blocked from real generation |
AI_DEMO_BLOCK_REAL_GENERATION | true | Block AI generate for demo emails |
AI_DEMO_SHOW_SAMPLE_HISTORY | true | Show sample AI history for demo accounts |
Rules:
AI_PROVIDER=MOCKrequires no provider API key.AI_PROVIDER=OPENAIrequires onlyOPENAI_API_KEY— Gemini key can stay empty.AI_PROVIDER=GEMINIrequires onlyGEMINI_API_KEY— OpenAI key can stay empty.- Real AI usage requires buyer-owned keys and may incur OpenAI/Gemini costs.
See AI Module for endpoints, demo behavior, and troubleshooting.
Backend — Billing provider
Default BILLING_PROVIDER=MOCK — no Stripe or Lemon Squeezy keys required for install.
| Variable | Example | Description |
|---|---|---|
BILLING_PROVIDER | MOCK | Active provider: MOCK, STRIPE, or LEMON_SQUEEZY |
BILLING_SUCCESS_URL | http://localhost:3000/dashboard/billing/success | Redirect after successful checkout |
BILLING_CANCEL_URL | http://localhost:3000/dashboard/billing/cancel | Redirect when checkout is canceled |
BILLING_SUPPORT_EMAIL | support@launchkitlabs.com | Billing support contact |
Stripe (when BILLING_PROVIDER=STRIPE)
| Variable | Description |
|---|---|
STRIPE_SECRET_KEY | Stripe secret API key (backend only) |
STRIPE_WEBHOOK_SECRET | Webhook signing secret for /billing/webhooks/stripe |
STRIPE_PRICE_LITE | Stripe Price ID for Lite edition |
STRIPE_PRICE_PRO | Stripe Price ID for Pro edition |
STRIPE_PRICE_ENTERPRISE | Stripe Price ID for Enterprise edition |
STRIPE_CUSTOMER_PORTAL_ENABLED | true to enable customer portal URL foundation |
Lemon Squeezy (when BILLING_PROVIDER=LEMON_SQUEEZY)
| Variable | Description |
|---|---|
LEMON_SQUEEZY_API_KEY | Lemon Squeezy API key (backend only) |
LEMON_SQUEEZY_STORE_ID | Store ID for checkout API |
LEMON_SQUEEZY_WEBHOOK_SECRET | Webhook signing secret for /billing/webhooks/lemon-squeezy |
LEMON_SQUEEZY_VARIANT_LITE | Variant ID for Lite |
LEMON_SQUEEZY_VARIANT_PRO | Variant ID for Pro |
LEMON_SQUEEZY_VARIANT_ENTERPRISE | Variant ID for Enterprise |
Rules:
BILLING_PROVIDER=MOCKrequires no Stripe or Lemon keys.- Stripe config is validated only when creating Stripe checkout or checking provider status.
- Lemon config is validated only when creating Lemon checkout or checking provider status.
- Empty keys for inactive providers do not block app startup.
- Provider secrets are buyer-owned; never put them in frontend env or git.
See Billing and Payment Webhooks.
Backend — Database
| Variable | Example | Description |
|---|---|---|
DATABASE_URL | postgresql://launchkit_user:replace_with_secure_password@127.0.0.1:5432/launchkit_app | Required. PostgreSQL connection string |
Replace replace_with_secure_password locally — do not commit it. See Database Setup for pgAdmin field notes.
Backend — JWT / Auth
| Variable | Example | Description |
|---|---|---|
JWT_ACCESS_SECRET | replace_me_access_secret | Required — access token signing secret |
JWT_REFRESH_SECRET | replace_me_refresh_secret | Required — refresh token signing secret |
JWT_ACCESS_EXPIRES_IN | 15m | Access token TTL |
JWT_REFRESH_EXPIRES_IN | 7d | Refresh token TTL |
PASSWORD_SALT_ROUNDS | 12 | bcrypt cost factor |
PASSWORD_RESET_TOKEN_EXPIRES_MINUTES | 30 | Reset token lifetime |
EMAIL_VERIFICATION_TOKEN_EXPIRES_HOURS | 24 | Verification token lifetime |
Generate strong random secrets for production (32+ characters).
Backend — Email provider
| Variable | Example | Description |
|---|---|---|
EMAIL_PROVIDER | MOCK | Default for install — MOCK, SMTP, RESEND, or GMAIL when you connect real email |
EMAIL_FROM_NAME | LaunchKit Pro | Sender display name |
EMAIL_FROM_ADDRESS | no-reply@yourdomain.com | Sender email |
SUPPORT_EMAIL | support@yourdomain.com | Contact/support recipient |
No SMTP credentials required while EMAIL_PROVIDER=MOCK.
Backend — Storage provider
| Variable | Example | Description |
|---|---|---|
STORAGE_PROVIDER | LOCAL | Default for install — LOCAL, S3, R2, or CLOUDINARY |
STORAGE_PUBLIC_BASE_URL | http://localhost:4000/uploads | Public base URL for local public assets |
STORAGE_UPLOAD_DIR | uploads | Local upload directory |
STORAGE_MAX_FILE_SIZE_MB | 25 | System-wide upload ceiling (MB); align with frontend and Nginx |
STORAGE_ALLOWED_MIME_TYPES | image/jpeg,... | Comma-separated MIME allow-list |
STORAGE_SIGNED_URL_TTL_SECONDS | 900 | Signed URL TTL foundation |
STORAGE_CLEANUP_ENABLED | false | Orphan cleanup stays dry-run/disabled by default |
STORAGE_ORPHAN_MAX_AGE_DAYS | 7 | Age threshold used by cleanup scans |
S3-compatible:
| Variable | Description |
|---|---|
S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY | Backend-only S3 credentials |
S3_REGION / S3_BUCKET / S3_ENDPOINT | Bucket target; endpoint is optional for AWS S3, useful for S3-compatible services |
S3_FORCE_PATH_STYLE | true for MinIO/R2-like endpoints that need path-style URLs |
S3_PUBLIC_BASE_URL | Optional CDN/public bucket base URL |
Cloudflare R2:
| Variable | Description |
|---|---|
R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY | Backend-only R2 credentials |
R2_ACCOUNT_ID / R2_BUCKET / R2_ENDPOINT | R2 target; region defaults safely to auto |
R2_PUBLIC_BASE_URL | Optional public/custom domain base URL |
Cloudinary:
| Variable | Description |
|---|---|
CLOUDINARY_CLOUD_NAME / CLOUDINARY_API_KEY / CLOUDINARY_API_SECRET | Backend-only Cloudinary credentials |
CLOUDINARY_FOLDER | Upload folder prefix, default launchkit-pro |
LOCAL requires no external keys. S3 validates only S3 vars, R2 only R2 vars, and Cloudinary only Cloudinary vars. Empty keys for inactive providers do not block app startup.
Backend — Redis & queues (optional)
| Variable | Example | Description |
|---|---|---|
QUEUES_ENABLED | false | Safe default — set true only with Redis running |
REDIS_URL | redis://127.0.0.1:6379 | Full Redis URL (optional when queues disabled) |
REDIS_HOST | 127.0.0.1 | Redis host — used to build URL when REDIS_URL is omitted |
REDIS_PORT | 6379 | Redis port |
REDIS_PASSWORD | (empty) | Redis password (optional) |
REDIS_DB | 0 | Redis database index |
QUEUE_PREFIX | launchkit | BullMQ key prefix |
QUEUE_DASHBOARD_ENABLED | false | Optional Bull Board dashboard (future) |
QUEUE_WORKER_EMAIL_ENABLED | true | Enable email queue processor |
QUEUE_WORKER_AI_ENABLED | true | Enable AI queue processor |
QUEUE_WORKER_WEBHOOK_ENABLED | true | Enable webhook queue processor |
QUEUE_WORKER_NOTIFICATION_ENABLED | true | Enable notification queue processor |
QUEUE_WORKER_MAINTENANCE_ENABLED | true | Enable maintenance queue processor |
QUEUE_DEFAULT_ATTEMPTS | 3 | Default job retries |
QUEUE_DEFAULT_BACKOFF_MS | 30000 | Backoff delay (ms) |
QUEUE_JOB_REMOVE_ON_COMPLETE | 100 | Keep last N completed jobs |
QUEUE_JOB_REMOVE_ON_FAIL | 500 | Keep last N failed jobs |
MAINTENANCE_SCHEDULER_ENABLED | false | Daily dry-run maintenance jobs (disabled by default) |
MAINTENANCE_CLEANUP_CRON | 0 3 * * * | Cleanup cron expression (foundation) |
MAINTENANCE_DEMO_RESET_CRON | 0 4 * * * | Demo reset cron expression (placeholder) |
MAINTENANCE_STORAGE_CLEANUP_CRON | 0 5 * * * | Storage cleanup cron expression (foundation) |
See Background Queues.
Backend — API docs
| Variable | Example | Description |
|---|---|---|
API_DOCS_ENABLED | true | Enable Swagger UI and OpenAPI JSON |
API_DOCS_PATH | api-docs | Swagger UI path |
API_DOCS_JSON_PATH | api-docs-json | OpenAPI JSON path |
API_DOCS_AUTH_ENABLED | false | Require HTTP basic auth before Swagger (typically enforced at Nginx in production) |
API_DOCS_USERNAME | replace_me_docs_user | Docs basic auth username — placeholder only |
API_DOCS_PASSWORD | replace_me_docs_password | Docs basic auth password — placeholder only |
| Mode | Settings |
|---|---|
| Disabled | API_DOCS_ENABLED=false |
| Public | API_DOCS_ENABLED=true |
| Protected | API_DOCS_ENABLED=true + reverse-proxy basic auth (recommended) or auth middleware when enabled |
Recommendation: enable on local/staging; use protected or disabled on production and public demos.
See API Documentation.
Backend — Security
| Variable | Example | Description |
|---|---|---|
RATE_LIMIT_ENABLED | true | API rate limiting |
RATE_LIMIT_* | see .env.example | Per-tier limits |
CAPTCHA_PROVIDER | MOCK | MOCK, TURNSTILE, or RECAPTCHA |
CAPTCHA_ENABLED | false | Master CAPTCHA toggle |
CAPTCHA_REQUIRED_FOR_* | false | Per-form CAPTCHA flags |
SECURITY_HEADERS_ENABLED | true | Helmet on API |
TRUST_PROXY | true | Use X-Forwarded-For behind Nginx |
CORS_STRICT_MODE | true | Disable dev localhost port bypass |
AUDIT_LOG_ENABLED | true | Append-only audit trail |
AUDIT_LOG_RETENTION_DAYS | 90 | Retention policy (docs) |
See Security Hardening, Rate Limiting, and Audit Logs.
Backend — Monitoring / logging
Local monitoring foundation — no paid error-tracking service required.
| Variable | Example | Description |
|---|---|---|
MONITORING_ENABLED | true | Enable admin monitoring APIs and in-memory store |
LOG_LEVEL | info | NestJS log level |
ERROR_LOGGING_ENABLED | true | Record safe errors to store and server logs |
ERROR_LOG_RETENTION_DAYS | 14 | Retention policy (docs) |
REQUEST_LOGGING_ENABLED | true | Record recent HTTP requests to the in-memory buffer |
REQUEST_LOG_SLOW_MS | 1000 | Slow request threshold in milliseconds |
REQUEST_LOG_RING_BUFFER_SIZE | 300 | Max recent requests kept in memory |
ERROR_LOG_RING_BUFFER_SIZE | 200 | Max recent errors kept in memory |
See Monitoring.
Backend — Analytics
Local usage and demo tracking — no third-party analytics required.
| Variable | Example | Description |
|---|---|---|
ANALYTICS_ENABLED | true | Master switch; false = no-op |
ANALYTICS_PROVIDER | LOCAL | LOCAL or DISABLED |
ANALYTICS_DEMO_TRACKING_ENABLED | true | Track demo-specific events |
ANALYTICS_RETENTION_DAYS | 90 | Retention policy (docs) |
See Analytics.
Backend — Tests
| Variable | Example | Description |
|---|---|---|
TEST_DATABASE_URL | (empty) | Optional isolated DB for integration tests |
TEST_USE_SQLITE | false | Experimental SQLite test mode |
See Testing.
Backend — Search
| Variable | Example | Description |
|---|---|---|
SEARCH_PROVIDER | LOCAL | LOCAL, DISABLED, ALGOLIA, or MEILISEARCH |
SEARCH_ENABLED | true | Master search toggle |
SEARCH_MAX_RESULTS | 20 | Max results per query |
SEARCH_MIN_QUERY_LENGTH | 2 | Minimum query length |
SEARCH_INDEXING_ENABLED | true | Allow admin reindex endpoint |
ALGOLIA_APP_ID / ALGOLIA_SEARCH_API_KEY | (empty) | Algolia foundation — optional |
MEILISEARCH_HOST / MEILISEARCH_API_KEY | (empty) | Meilisearch foundation — optional |
Frontend:
| Variable | Example | Description |
|---|---|---|
NEXT_PUBLIC_DOCS_URL | https://docs.launchkitlabs.com | Docs links from search results |
NEXT_PUBLIC_SEARCH_SHORTCUT_ENABLED | true | Enable ⌘K / Ctrl+K shortcut |
See Dashboard Search.
Backend — Demo mode
| Variable | Example | Description |
|---|---|---|
DEMO_MODE_ENABLED | false | Master demo guards |
DEMO_USER_EMAILS | demo@example.com | Demo user accounts |
DEMO_ADMIN_EMAILS | admin-demo@example.com | Demo admin accounts |
DEMO_READONLY_ADMIN_EMAILS | admin-demo@example.com | Read-only admin (no mutations) |
DEMO_PROTECTED_EMAILS | demo@...,admin-demo@... | Legacy alias — protected emails |
DEMO_PUBLIC_ACCOUNTS_ENABLED | false | Show safe demo labels on login page |
DEMO_RESET_ENABLED | false | Allow destructive demo reset |
DEMO_RESET_DRY_RUN | true | Reset logs only by default |
DEMO_SEED_ENABLED | true | Allow admin seed API |
DEMO_SEED_ON_STARTUP | false | Auto-seed on API boot |
DEMO_UPLOADS_DISABLED / DEMO_BLOCK_UPLOADS | true | Block demo uploads |
DEMO_REAL_AI_DISABLED / DEMO_BLOCK_AI_GENERATION | true | Block real AI for demo |
DEMO_REAL_BILLING_DISABLED / DEMO_BLOCK_REAL_BILLING | true | Block real checkout |
DEMO_REAL_WEBHOOK_DELIVERY_DISABLED / DEMO_BLOCK_WEBHOOK_DELIVERY | true | No outbound webhook calls |
DEMO_API_KEY_CREATION_DISABLED / DEMO_BLOCK_API_KEY_CREATION | false | Block API key create |
DEMO_LICENSE_ACTIVATION_DISABLED / DEMO_BLOCK_LICENSE_ADMIN | false | Block license admin actions |
Do not put demo passwords in documentation or git. Use server env only.
See Demo Mode.
Backend — Developer API keys and outbound webhooks
| Variable | Example | Description |
|---|---|---|
WEBHOOK_DELIVERY_ENABLED | true | Set false to record disabled/dry-run deliveries without external calls |
WEBHOOK_QUEUE_ENABLED | false | Use BullMQ when queues are enabled and ready; direct delivery works without Redis |
WEBHOOK_MAX_RETRIES | 3 | Max attempts per delivery |
WEBHOOK_TIMEOUT_MS | 10000 | HTTP timeout per webhook POST |
WEBHOOK_RETRY_BACKOFF_SECONDS | 30,120,300 | Retry schedule foundation |
WEBHOOK_USER_AGENT | LaunchKit-Pro-Webhooks/1.0 | Outbound User-Agent |
WEBHOOK_DEMO_DELIVERY_DISABLED | true | Demo users record disabled deliveries instead of external calls |
API_KEY_AUTH_ENABLED | true | Enable /public-api/* API-key authentication |
API_KEY_HEADER_NAME | X-API-Key | Header used for API keys |
API_KEY_PREFIX | lk_ | Prefix for newly generated keys |
API_KEY_HASH_SECRET | (empty locally) | Optional local/dev; set a strong value in production for secret encryption context |
API keys are stored hashed and full keys are shown only once. Webhook signing secrets are shown only once and encrypted at rest for outbound signing. | DEMO_READONLY_ADMIN_EMAILS | admin-demo@example.com | Read-only demo admin emails | | DEMO_PUBLIC_ACCOUNTS_ENABLED | false | Show safe demo account labels on login |
Do not put demo passwords in env or git.
License activation (optional foundation)
Default LICENSE_ENFORCEMENT_ENABLED=false — app works without license activation.
| Variable | Default | Description |
|---|---|---|
LICENSE_ENFORCEMENT_ENABLED | false | Block access when no valid license (buyer opt-in) |
LICENSE_PROVIDER | MOCK | MOCK for admin-generated keys; extend for Payhip/Gumroad/Lemon Squeezy |
LICENSE_KEY_PREFIX | LKP | Prefix for generated keys |
LICENSE_MAX_ACTIVATIONS_DEFAULT | 3 | Default max activations per key |
LICENSE_ALLOW_OFFLINE_MODE | true | Reserved for offline verification flows |
LICENSE_SUPPORT_EMAIL | support@launchkitlabs.com | License support contact |
See License Activation for API routes and UI paths.
Product updates (optional foundation)
Default UPDATE_CHECK_ENABLED=true with static release catalog — no database migration.
| Variable | Default | Description |
|---|---|---|
LAUNCHKIT_VERSION | 1.2.0 | Installed product version returned by /updates/status |
UPDATE_CHANNEL | stable | Release channel label |
UPDATE_CHECK_ENABLED | true | Compare installed vs latest catalog version |
UPDATE_PROVIDER | MOCK | Extend for marketplace or storage-backed downloads |
UPDATE_SUPPORT_EMAIL | support@launchkitlabs.com | Support contact on updates UI |
See Product Updates for endpoints, UI paths, and secure download placeholders.
Minimum backend .env for fresh install
DATABASE_URL=postgresql://launchkit_user:replace_with_secure_password@127.0.0.1:5432/launchkit_app
JWT_ACCESS_SECRET=replace_me_access_secret
JWT_REFRESH_SECRET=replace_me_refresh_secret
JWT_ACCESS_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
PASSWORD_SALT_ROUNDS=12
APP_URL=http://localhost:4000
FRONTEND_URL=http://localhost:3000
EMAIL_PROVIDER=MOCK
STORAGE_PROVIDER=LOCAL
LOCAL_UPLOAD_DIR=./uploads
MAX_UPLOAD_SIZE_MB=10
QUEUES_ENABLED=false
API_DOCS_ENABLED=true
DEMO_MODE_ENABLED=false
AI_PROVIDER=MOCK
BILLING_PROVIDER=MOCK
LICENSE_ENFORCEMENT_ENABLED=false
LICENSE_PROVIDER=MOCK
LAUNCHKIT_VERSION=1.2.0
UPDATE_CHANNEL=stable
UPDATE_CHECK_ENABLED=true
UPDATE_PROVIDER=MOCKOptional when enabling queues:
# REDIS_URL=redis://127.0.0.1:6379
# QUEUES_ENABLED=trueFrontend
Copy .env.example to .env.local:
NEXT_PUBLIC_APP_NAME=LaunchKit Pro
NEXT_PUBLIC_API_URL=http://localhost:4000
NEXT_PUBLIC_MAX_UPLOAD_SIZE_MB=10| Variable | Description |
|---|---|
NEXT_PUBLIC_API_URL | Backend API base URL (required for auth) |
NEXT_PUBLIC_APP_NAME | App display name |
NEXT_PUBLIC_MAX_UPLOAD_SIZE_MB | Client pre-validation; backend + Nginx enforce real limit |
NEXT_PUBLIC_MARKETING_URL | Marketing site link (optional) |
NEXT_PUBLIC_DOCS_URL | Documentation link (optional; public docs hosting not required) |
NEXT_PUBLIC_SUPPORT_EMAIL | support@launchkitlabs.com |
NEXT_PUBLIC_SEARCH_SHORTCUT_ENABLED | true |
NEXT_PUBLIC_ANALYTICS_ENABLED | true |
NEXT_PUBLIC_ANALYTICS_PROVIDER | LOCAL |
WARNING
NEXT_PUBLIC_* variables are exposed to the browser. Never put private API keys or secrets in frontend env vars.
Production example (placeholders only)
NODE_ENV=production
APP_URL=https://api.yourdomain.com
FRONTEND_URL=https://app.yourdomain.com
DATABASE_URL=postgresql://launchkit_user:<YOUR_DB_PASSWORD>@127.0.0.1:5432/launchkit_app
JWT_ACCESS_SECRET=<strong-random-secret>
JWT_REFRESH_SECRET=<strong-random-secret>
API_DOCS_ENABLED=false
QUEUES_ENABLED=false
EMAIL_PROVIDER=MOCK
STORAGE_PROVIDER=LOCALReplace placeholders with values from your secrets manager — never commit them.
Mock providers and real adapters
LaunchKit Pro v1.0 intentionally defaults to MOCK billing, AI, and email plus LOCAL storage so you can install without vendor API keys. Billing supports MOCK, Stripe, and Lemon Squeezy provider adapters — switch BILLING_PROVIDER and add buyer-owned keys when going live. The AI module is provider-ready (OpenAI/Gemini adapters). Module boundaries are prepared so you can connect SMTP, S3, and similar providers when you go live.