Skip to content

Instantly share code, notes, and snippets.

@SyNeto
Created November 21, 2025 22:44
Show Gist options
  • Select an option

  • Save SyNeto/5b4ad0788de0e81aeac35b90c2fc41ee to your computer and use it in GitHub Desktop.

Select an option

Save SyNeto/5b4ad0788de0e81aeac35b90c2fc41ee to your computer and use it in GitHub Desktop.
Splenda CMS - Complete Environment Variables Reference (Build Time vs Runtime)

Splenda CMS - Environment Variables Report

Project: Splenda CMS (Strapi v5) Date: 2025-11-21 Purpose: Complete reference for infrastructure deployment configuration


Table of Contents

  1. Quick Reference
  2. Build Time vs Runtime
  3. Variables by Priority
  4. Variables by Category
  5. Environment-Specific Configurations

Quick Reference

Total Variables Count

  • Indispensable: 11 variables (app won't start without these)
  • Necessary: 9 variables (prevents security warnings, enables core features)
  • Optional: 15 variables (fine-tuning and optional features)
  • Total: 35 variables

When Variables Are Needed

  • Build Time: 0 variables (all TypeScript compilation happens at build time, but doesn't require env vars)
  • Runtime: All 35 variables (read when application starts)

Build Time vs Runtime

Build Time Variables

None required.

The application uses TypeScript configs that are compiled during Docker build (tsconfig.config.json), but these don't depend on environment variables. The compilation step (npm run compile:config) happens in Dockerfile.prod using static source files.

Runtime Variables

All variables are runtime variables. They are read when:

  1. Strapi server starts (npm run start)
  2. Configuration files are loaded (config/*.ts or compiled config-dist/*.js)
  3. Application bootstraps and connects to services

Variables by Priority

Indispensable (Required)

Application will not start without these variables.

Variable Build/Runtime Type Example Description
APP_KEYS Runtime String (CSV) key1,key2,key3,key4 Required. 4 comma-separated base64 keys for session encryption. Generate with openssl rand -base64 32 (4 times).
JWT_SECRET Runtime String abc123... Required. Secret for JWT token signing (user authentication). Generate with openssl rand -base64 32.
ADMIN_JWT_SECRET Runtime String xyz789... Required. Secret for admin panel JWT tokens. Generate with openssl rand -base64 32.
API_TOKEN_SALT Runtime String def456... Required. Salt for API token hashing. Generate with openssl rand -base64 32.
TRANSFER_TOKEN_SALT Runtime String ghi789... Required. Salt for data transfer tokens. Generate with openssl rand -base64 32.
ENCRYPTION_KEY Runtime String jkl012... Required. Encryption key for API tokens visibility in admin panel. Generate with openssl rand -base64 32.
DATABASE_HOST Runtime String postgres or xxx.db.ondigitalocean.com Required. PostgreSQL server hostname.
DATABASE_PORT Runtime Integer 5432 or 25060 Required. PostgreSQL server port.
DATABASE_NAME Runtime String strapi or staging_main Required. PostgreSQL database name.
DATABASE_USERNAME Runtime String strapi or doadmin Required. PostgreSQL username.
DATABASE_PASSWORD Runtime String secure-password Required. PostgreSQL password.

Generation Command:

# Generate all secrets at once
for i in {1..6}; do openssl rand -base64 32; done

# First 4 outputs → APP_KEYS (join with commas, no spaces)
# Output 5 → JWT_SECRET
# Output 6 → ADMIN_JWT_SECRET
# Run again for remaining secrets (API_TOKEN_SALT, TRANSFER_TOKEN_SALT, ENCRYPTION_KEY)

Necessary (Highly Recommended)

Application will start but with warnings or limited functionality.

Variable Build/Runtime Type Example Description
NODE_ENV Runtime String production Necessary. Environment mode. Use production for staging/prod, development for local. Default: development.
STRAPI_TELEMETRY_DISABLED Runtime Boolean true Necessary. Disable Strapi analytics. Recommended true for production to avoid data leaks.
VERIFICATION_CODE_CHARSET Runtime String alphanumeric-safe Necessary. Charset for verification codes. Without this, shows security warning. Options: numeric | alphanumeric-safe. Recommended: alphanumeric-safe.
VERIFICATION_CODE_LENGTH Runtime Integer 6 Necessary. Code length. Without this, shows security warning. Recommended: 6 or 8.
SMTP_HOST Runtime String smtp.sendgrid.net or mailpit Necessary for email. SMTP server hostname. Falls back to Mailpit if not configured.
SMTP_PORT Runtime Integer 587 or 1025 Necessary for email. SMTP port. 587 for SendGrid, 1025 for Mailpit.
SMTP_FROM Runtime String [email protected] Necessary for email. Sender email address. Must be verified in SendGrid for production.
SMTP_REPLY_TO Runtime String [email protected] Necessary for email. Reply-to email address.
DATABASE_SSL Runtime Boolean true Necessary for managed DBs. Enable SSL for PostgreSQL connection. Required for DigitalOcean managed databases.

Optional (Feature-specific)

Application works fully without these, but they enable specific features or fine-tuning.

Email Authentication (SendGrid)

Variable Build/Runtime Type Example Description
SMTP_USERNAME Runtime String apikey Optional. SMTP auth username. For SendGrid, use literal string "apikey". Omit for Mailpit.
SMTP_PASSWORD Runtime String SG.xxx... Optional. SMTP auth password. For SendGrid, use API key. Omit for Mailpit.

SMS Verification (Twilio)

Variable Build/Runtime Type Example Description
TWILIO_ACCOUNT_SID Runtime String ACxxxxxxxx... Optional. Twilio Account SID. Required only if using SMS verification.
TWILIO_AUTH_TOKEN Runtime String your_token... Optional. Twilio Auth Token. Required only if using SMS verification.
TWILIO_PHONE_NUMBER Runtime String +1234567890 Optional. Twilio phone number in E.164 format. Required only if using SMS verification.

File Storage (DigitalOcean Spaces)

Variable Build/Runtime Type Example Description
SPACES_BUCKET Runtime String splenda-uploads Optional. S3 bucket name. If not set, uses local filesystem for uploads.
SPACES_REGION Runtime String nyc3 Optional. DigitalOcean Spaces region. Default: nyc3.
SPACES_ACCESS_KEY Runtime String DO00XXXXX... Optional. Spaces access key. Required if SPACES_BUCKET is set.
SPACES_SECRET_KEY Runtime String xxxxx... Optional. Spaces secret key. Required if SPACES_BUCKET is set.
SPACES_PREFIX Runtime String staging/ or pr-123/ Optional. Prefix for uploaded files. Enables environment isolation in shared bucket.

Server Configuration

Variable Build/Runtime Type Example Description
HOST Runtime String 0.0.0.0 Optional. Server bind address. Default: 0.0.0.0 (all interfaces).
PORT Runtime Integer 1337 Optional. Server listen port. Default: 1337.

Database Fine-tuning

Variable Build/Runtime Type Example Description
DATABASE_SSL_REJECT_UNAUTHORIZED Runtime Boolean false Optional. Verify SSL certificate. Use false for DigitalOcean managed DBs. Default: false.
DATABASE_POOL_MIN Runtime Integer 2 Optional. Minimum database connection pool size. Default: 2.
DATABASE_POOL_MAX Runtime Integer 10 Optional. Maximum database connection pool size. Default: 10.
DATABASE_CONNECTION_TIMEOUT Runtime Integer 60000 Optional. Database connection timeout (ms). Default: 60000.

Admin Panel Session Configuration (Strapi v6 Compatibility)

Variable Build/Runtime Type Example Description
ADMIN_ACCESS_TOKEN_LIFESPAN Runtime Integer 1800 Optional. Admin access token lifespan (seconds). Default: 1800 (30 min).
ADMIN_MAX_REFRESH_TOKEN_LIFESPAN Runtime Integer 2592000 Optional. Max refresh token lifespan (seconds). Default: 2592000 (30 days).
ADMIN_IDLE_REFRESH_TOKEN_LIFESPAN Runtime Integer 604800 Optional. Idle refresh token lifespan (seconds). Default: 604800 (7 days).
ADMIN_MAX_SESSION_LIFESPAN Runtime Integer 2592000 Optional. Max session lifespan (seconds). Default: 2592000 (30 days).
ADMIN_IDLE_SESSION_LIFESPAN Runtime Integer 3600 Optional. Idle session lifespan (seconds). Default: 3600 (1 hour).

Verification Code Configuration

Variable Build/Runtime Type Example Description
VERIFICATION_CODE_EXPIRATION_MINUTES Runtime Integer 10 Optional. Code expiration time (minutes). Default: 10. Does not trigger warning.

Feature Flags

Variable Build/Runtime Type Example Description
FLAG_NPS Runtime Boolean true Optional. Enable NPS survey in admin panel. Default: true.
FLAG_PROMOTE_EE Runtime Boolean true Optional. Promote Enterprise Edition features. Default: true.
WEBHOOKS_POPULATE_RELATIONS Runtime Boolean false Optional. Populate relations in webhook payloads. Default: false.

Metadata

Variable Build/Runtime Type Example Description
ENVIRONMENT_TYPE Runtime String staging or production Optional. Environment identifier for logging/monitoring. No functional impact.

Variables by Category

1. Strapi Core (6 variables - Indispensable)

  • APP_KEYS ⚠️ Required
  • JWT_SECRET ⚠️ Required
  • ADMIN_JWT_SECRET ⚠️ Required
  • API_TOKEN_SALT ⚠️ Required
  • TRANSFER_TOKEN_SALT ⚠️ Required
  • ENCRYPTION_KEY ⚠️ Required

2. Database (8 variables - 5 Indispensable + 3 Optional)

Indispensable:

  • DATABASE_HOST ⚠️ Required
  • DATABASE_PORT ⚠️ Required
  • DATABASE_NAME ⚠️ Required
  • DATABASE_USERNAME ⚠️ Required
  • DATABASE_PASSWORD ⚠️ Required

Optional:

  • DATABASE_SSL (Necessary for managed DBs)
  • DATABASE_SSL_REJECT_UNAUTHORIZED
  • DATABASE_POOL_MIN
  • DATABASE_POOL_MAX
  • DATABASE_CONNECTION_TIMEOUT

3. Email (6 variables - 4 Necessary + 2 Optional)

Necessary:

  • SMTP_HOST (Falls back to Mailpit)
  • SMTP_PORT (Falls back to Mailpit)
  • SMTP_FROM (Falls back to default)
  • SMTP_REPLY_TO (Falls back to default)

Optional:

  • SMTP_USERNAME (Required only for SendGrid)
  • SMTP_PASSWORD (Required only for SendGrid)

4. SMS Verification (3 variables - All Optional)

  • TWILIO_ACCOUNT_SID (Required only if using SMS)
  • TWILIO_AUTH_TOKEN (Required only if using SMS)
  • TWILIO_PHONE_NUMBER (Required only if using SMS)

5. Verification Codes (3 variables - 2 Necessary + 1 Optional)

Necessary:

  • VERIFICATION_CODE_CHARSET (Prevents security warning)
  • VERIFICATION_CODE_LENGTH (Prevents security warning)

Optional:

  • VERIFICATION_CODE_EXPIRATION_MINUTES

6. File Storage (5 variables - All Optional)

  • SPACES_BUCKET (Enables cloud storage)
  • SPACES_REGION
  • SPACES_ACCESS_KEY (Required if SPACES_BUCKET set)
  • SPACES_SECRET_KEY (Required if SPACES_BUCKET set)
  • SPACES_PREFIX

7. Server Configuration (2 variables - All Optional)

  • HOST
  • PORT

8. Admin Panel (5 variables - All Optional)

  • ADMIN_ACCESS_TOKEN_LIFESPAN
  • ADMIN_MAX_REFRESH_TOKEN_LIFESPAN
  • ADMIN_IDLE_REFRESH_TOKEN_LIFESPAN
  • ADMIN_MAX_SESSION_LIFESPAN
  • ADMIN_IDLE_SESSION_LIFESPAN

9. Environment & Flags (5 variables - 1 Necessary + 4 Optional)

Necessary:

  • NODE_ENV
  • STRAPI_TELEMETRY_DISABLED

Optional:

  • ENVIRONMENT_TYPE
  • FLAG_NPS
  • FLAG_PROMOTE_EE
  • WEBHOOKS_POPULATE_RELATIONS

Environment-Specific Configurations

Local Development (Docker)

Minimal configuration (11 indispensable variables):

# Secrets (generate with: for i in {1..6}; do openssl rand -base64 32; done)
APP_KEYS=key1,key2,key3,key4
JWT_SECRET=<generated>
ADMIN_JWT_SECRET=<generated>
API_TOKEN_SALT=<generated>
TRANSFER_TOKEN_SALT=<generated>
ENCRYPTION_KEY=<generated>

# Database (Docker Compose)
DATABASE_HOST=postgres
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=strapi

Recommended configuration (+9 necessary variables):

# Add to minimal config above:
NODE_ENV=development
STRAPI_TELEMETRY_DISABLED=true

# Email (Mailpit - no auth)
SMTP_HOST=mailpit
SMTP_PORT=1025
[email protected]
[email protected]

# Verification
VERIFICATION_CODE_CHARSET=alphanumeric-safe
VERIFICATION_CODE_LENGTH=6
VERIFICATION_CODE_EXPIRATION_MINUTES=10

# Database
DATABASE_SSL=false

Total: 20 variables (11 indispensable + 9 necessary)


Staging (DigitalOcean - Testing with Real Services)

Required for staging (20 core variables + SendGrid + Spaces):

# Secrets (same as production, generated once)
APP_KEYS=key1,key2,key3,key4
JWT_SECRET=<generated>
ADMIN_JWT_SECRET=<generated>
API_TOKEN_SALT=<generated>
TRANSFER_TOKEN_SALT=<generated>
ENCRYPTION_KEY=<generated>

# Environment
NODE_ENV=production
STRAPI_TELEMETRY_DISABLED=true
ENVIRONMENT_TYPE=staging

# Database (Managed PostgreSQL)
DATABASE_HOST=xxx.db.ondigitalocean.com
DATABASE_PORT=25060
DATABASE_NAME=staging_main
DATABASE_USERNAME=doadmin
DATABASE_PASSWORD=<from-terraform>
DATABASE_SSL=true
DATABASE_SSL_REJECT_UNAUTHORIZED=false

# Email (SendGrid for real delivery)
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USERNAME=apikey
SMTP_PASSWORD=SG.xxx...
[email protected]
[email protected]

# Verification
VERIFICATION_CODE_CHARSET=alphanumeric-safe
VERIFICATION_CODE_LENGTH=6
VERIFICATION_CODE_EXPIRATION_MINUTES=10

# File Storage (DigitalOcean Spaces)
SPACES_BUCKET=splenda-uploads
SPACES_REGION=nyc3
SPACES_ACCESS_KEY=DO00XXXXX...
SPACES_SECRET_KEY=<from-terraform>
SPACES_PREFIX=staging/

Optional for staging (SMS testing):

# SMS (Twilio - if testing SMS verification)
TWILIO_ACCOUNT_SID=ACxxxxxxxx...
TWILIO_AUTH_TOKEN=<from-twilio>
TWILIO_PHONE_NUMBER=+1234567890

Total: 30-33 variables (with/without SMS)


Ephemeral Environments (PR Previews)

Same as staging, but with environment-specific values:

# All variables same as staging, except:

DATABASE_NAME=pr_123              # PR-specific database
SPACES_PREFIX=pr-123/             # PR-specific file prefix
ENVIRONMENT_TYPE=pr-preview       # Metadata

# Email: Use Mailpit (not SendGrid) to avoid costs
SMTP_HOST=mailpit
SMTP_PORT=1025
[email protected]
[email protected]
# Omit SMTP_USERNAME and SMTP_PASSWORD

Total: 27-30 variables (Mailpit instead of SendGrid)


Production

All recommended variables (staging config + SMS + fine-tuning):

# Same as staging, plus:

# Environment
ENVIRONMENT_TYPE=production
NODE_ENV=production

# SMS (Real Twilio account, not trial)
TWILIO_ACCOUNT_SID=ACxxxxxxxx...
TWILIO_AUTH_TOKEN=<production-token>
TWILIO_PHONE_NUMBER=+1234567890

# Email (Production SendGrid with verified domain)
[email protected]
[email protected]

# File Storage
SPACES_PREFIX=production/

# Database
DATABASE_NAME=production

# Security hardening
VERIFICATION_CODE_LENGTH=8        # Longer codes for production
VERIFICATION_CODE_EXPIRATION_MINUTES=10

# Session configuration (optional fine-tuning)
ADMIN_IDLE_SESSION_LIFESPAN=1800  # 30 min instead of 1 hour

Total: 33-35 variables (all features enabled)


Security Best Practices

Secret Generation

Generate ALL secrets before deployment:

# Generate 6 secrets for core Strapi configuration
for i in {1..6}; do openssl rand -base64 32; done

# Use first 4 for APP_KEYS (comma-separated, no spaces):
# APP_KEYS=secret1,secret2,secret3,secret4

# Use output 5 for JWT_SECRET
# Use output 6 for ADMIN_JWT_SECRET

# Run again for remaining secrets:
for i in {1..3}; do openssl rand -base64 32; done
# Output 1 → API_TOKEN_SALT
# Output 2 → TRANSFER_TOKEN_SALT
# Output 3 → ENCRYPTION_KEY

Secret Management

  1. Never commit secrets to git - .env is in .gitignore
  2. Use environment-specific secrets - Different secrets for dev/staging/production
  3. Rotate secrets periodically - Especially after team member departures
  4. Use secret management tools - DigitalOcean App Platform's encrypted environment variables
  5. Restrict access - Only infrastructure admins should see production secrets

SendGrid Configuration

  1. Verify sender before deploying:

    • Settings → Sender Authentication → Single Sender Verification
    • Verify [email protected]
  2. Use restricted API keys:

    • SendGrid Dashboard → API Keys → Create API Key
    • Permissions: Mail Send only (not full access)
    • Never use the same API key for dev/staging/production
  3. Test before production:

    • Use staging environment to test real email delivery
    • Verify emails arrive in inbox (not spam)
    • Test email templates render correctly

Database Security

  1. Enable SSL for managed databases: DATABASE_SSL=true
  2. Use strong passwords: Generate with openssl rand -base64 32
  3. Restrict database access: Firewall rules to allow only App Platform IPs
  4. Separate databases per environment: staging_main, production, etc.

Validation Checklist

Before Deployment

  • All 11 indispensable variables are set
  • All secrets generated with openssl rand -base64 32
  • APP_KEYS has exactly 4 comma-separated keys (no spaces)
  • NODE_ENV=production for staging/production
  • STRAPI_TELEMETRY_DISABLED=true for staging/production
  • Database credentials tested (can connect)
  • SendGrid API key verified (test email sent successfully)
  • SendGrid sender email verified in SendGrid dashboard
  • Spaces credentials tested (can upload file)
  • VERIFICATION_CODE_CHARSET and VERIFICATION_CODE_LENGTH set (no warning)
  • SSL enabled for managed database (DATABASE_SSL=true)

After Deployment

  • Application starts without errors
  • No security warnings in logs
  • Admin panel accessible at /admin
  • Database connection successful
  • Email delivery works (registration, password reset)
  • File uploads work (if Spaces configured)
  • API tokens visible in admin panel (verifies ENCRYPTION_KEY)
  • User registration → verification → login flow works

Troubleshooting

Application Won't Start

Check indispensable variables:

# Verify all 11 required variables are set:
echo "APP_KEYS: ${APP_KEYS:0:10}..." # Should show first 10 chars
echo "JWT_SECRET: ${JWT_SECRET:0:10}..."
echo "ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET:0:10}..."
echo "API_TOKEN_SALT: ${API_TOKEN_SALT:0:10}..."
echo "TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT:0:10}..."
echo "ENCRYPTION_KEY: ${ENCRYPTION_KEY:0:10}..."
echo "DATABASE_HOST: $DATABASE_HOST"
echo "DATABASE_PORT: $DATABASE_PORT"
echo "DATABASE_NAME: $DATABASE_NAME"
echo "DATABASE_USERNAME: $DATABASE_USERNAME"
echo "DATABASE_PASSWORD: ${DATABASE_PASSWORD:0:5}..." # First 5 chars only

Security Warning: Insecure Configuration

Set verification code variables:

VERIFICATION_CODE_CHARSET=alphanumeric-safe
VERIFICATION_CODE_LENGTH=6

Emails Not Sending

Check SMTP configuration:

echo "SMTP_HOST: $SMTP_HOST"
echo "SMTP_PORT: $SMTP_PORT"
echo "SMTP_USERNAME: $SMTP_USERNAME"
echo "SMTP_PASSWORD: ${SMTP_PASSWORD:0:5}..." # First 5 chars
echo "SMTP_FROM: $SMTP_FROM"

For SendGrid:

  • Verify sender email in SendGrid dashboard
  • Check API key is valid and has "Mail Send" permission
  • Ensure SMTP_USERNAME=apikey (literal string)
  • Ensure SMTP_PASSWORD starts with SG.

Database Connection Failed

Check database variables and SSL:

echo "DATABASE_HOST: $DATABASE_HOST"
echo "DATABASE_PORT: $DATABASE_PORT"
echo "DATABASE_SSL: $DATABASE_SSL"
echo "DATABASE_SSL_REJECT_UNAUTHORIZED: $DATABASE_SSL_REJECT_UNAUTHORIZED"

# Test connection manually:
psql -h $DATABASE_HOST -p $DATABASE_PORT -U $DATABASE_USERNAME -d $DATABASE_NAME

For DigitalOcean managed databases:

  • Must use DATABASE_SSL=true
  • Must use DATABASE_SSL_REJECT_UNAUTHORIZED=false
  • Port is usually 25060, not 5432

File Uploads Failing

Check Spaces configuration:

echo "SPACES_BUCKET: $SPACES_BUCKET"
echo "SPACES_REGION: $SPACES_REGION"
echo "SPACES_ACCESS_KEY: ${SPACES_ACCESS_KEY:0:10}..."
echo "SPACES_PREFIX: $SPACES_PREFIX"

# Test Spaces access with AWS CLI:
aws s3 ls s3://$SPACES_BUCKET \
  --endpoint-url https://${SPACES_REGION}.digitaloceanspaces.com \
  --profile digitalocean

Additional Resources

  • .env.example: Template with all variables and comments
  • docs/environment-variables.md: Detailed documentation for admin session configuration
  • docs/EMAIL_CONFIGURATION.md: Complete email setup guide
  • ADR-002: TypeScript config compilation strategy
  • ADR-005: Email configuration architecture
  • ADR-006: SMS and Email verification strategy

Change Log

  • 2025-11-21: Initial report created for staging deployment
  • Variables verified against codebase: config/*.ts
  • Total: 35 environment variables documented
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment