Skip to content

Configuration

Complete configuration reference for Open Short URL.

Environment Files

  • apps/backend/.env - Backend API configuration
  • apps/frontend/.env.local - Frontend web app configuration

Backend Configuration

Required

These variables must be set for the application to function.

Environment

VariableDescriptionExample
NODE_ENVEnvironment modeproduction
bash
NODE_ENV=production

Database

VariableDescriptionExample
DATABASE_URLPostgreSQL connection stringSee below
bash
# Connection pool parameters:
#   connection_limit: Max connections (dev: 10-15, prod: 20-30)
#   pool_timeout: Pool timeout in seconds (default: 10)
#   connect_timeout: Connection timeout in seconds (default: 5)
DATABASE_URL="postgresql://user:password@localhost:5432/open_short_url?schema=public&connection_limit=20"

URLs & Domains

VariableDescriptionExample
SHORT_URL_DOMAINDomain for short URLshttps://s.yourdomain.com
FRONTEND_URLFrontend application URLhttps://app.yourdomain.com
CORS_ORIGINAllowed CORS originshttps://app.yourdomain.com
bash
SHORT_URL_DOMAIN="https://s.yourdomain.com"
FRONTEND_URL="https://app.yourdomain.com"
# Multiple origins: https://app1.example.com,https://app2.example.com
CORS_ORIGIN="https://app.yourdomain.com"

Authentication

VariableDescriptionExample
JWT_SECRETSecret key for JWT tokens (min 32 chars)Random string
ADMIN_INITIAL_PASSWORDInitial admin account passwordStrong password
bash
# Generate with: openssl rand -base64 32
JWT_SECRET="your-super-secure-random-string-at-least-32-characters"
ADMIN_INITIAL_PASSWORD="your-strong-admin-password"

Security

  • Use a cryptographically secure random string for JWT_SECRET
  • Change ADMIN_INITIAL_PASSWORD immediately after first login

These variables are optional but strongly recommended for production.

Redis Cache

Falls back to in-memory storage if not configured (not recommended for production).

VariableDescriptionDefault
REDIS_HOSTRedis server hostnamelocalhost
REDIS_PORTRedis server port6379
REDIS_PASSWORDRedis password-
REDIS_DBRedis database number0
bash
REDIS_HOST="localhost"
REDIS_PORT="6379"
REDIS_PASSWORD=""
REDIS_DB="0"

Proxy Settings

Enable if behind a reverse proxy (nginx, Cloudflare, etc.).

VariableDescriptionDefault
TRUSTED_PROXYTrust proxy headersfalse
bash
# Reads client IP from X-Forwarded-For and X-Real-IP headers
TRUSTED_PROXY=true

WARNING

Only enable if you trust your proxy. Otherwise attackers can spoof IP addresses.

Cloudflare Turnstile (Anti-Bot)

Protects password-protected URLs from bots.

VariableDescription
TURNSTILE_SECRET_KEYTurnstile secret key
TURNSTILE_SITE_KEYTurnstile site key
bash
# Get keys from: https://dash.cloudflare.com/turnstile
TURNSTILE_SECRET_KEY="0x..."
TURNSTILE_SITE_KEY="0x..."

# Testing keys (always passes):
# Site Key:   1x00000000000000000000AA
# Secret Key: 1x0000000000000000000000000000000AA

Webhooks

VariableDescription
WEBHOOK_SECRET_KEYDefault webhook signing key
bash
# Generate with: openssl rand -hex 32
WEBHOOK_SECRET_KEY="your-webhook-secret"

Optional

These variables have sensible defaults and can be adjusted as needed.

Server

VariableDescriptionDefault
PORTBackend server port4101
HOSTServer host binding0.0.0.0
bash
PORT=4101
HOST=0.0.0.0
VariableDescriptionDefault
COOKIE_DOMAINCookie domain for cross-subdomain authAuto-detected
bash
# Cross-subdomain (api.example.com & app.example.com): .example.com
# Single domain or localhost: leave empty
COOKIE_DOMAIN=.example.com

Authentication Options

VariableDescriptionDefault
JWT_EXPIRES_INJWT token expiration7d
BCRYPT_ROUNDSPassword hashing rounds10
bash
JWT_EXPIRES_IN="7d"
BCRYPT_ROUNDS=10

Rate Limiting

VariableDescriptionDefault
THROTTLE_TTLTime window (seconds)60
THROTTLE_LIMITMax requests per window10
bash
THROTTLE_TTL=60
THROTTLE_LIMIT=10

Slug Generation

Dynamic slug length based on total URL count.

VariableDescriptionDefault
SLUG_LENGTH_THRESHOLDSURL count thresholds1000,50000,500000
SLUG_LENGTHSSlug lengths per threshold4,5,6,7
bash
# count < 1000         -> 4 chars
# 1000 <= count < 50000   -> 5 chars
# 50000 <= count < 500000 -> 6 chars
# count >= 500000         -> 7 chars
SLUG_LENGTH_THRESHOLDS="1000,50000,500000"
SLUG_LENGTHS="4,5,6,7"

Branding

VariableDescriptionDefault
BRAND_NAMEApplication nameOpen Short URL
BRAND_LOGO_URLLogo URL-
bash
BRAND_NAME="My Short URLs"
BRAND_LOGO_URL="https://example.com/logo.png"

API Keys

VariableDescriptionDefault
MAX_API_KEYS_PER_USERMaximum API keys per user10
bash
MAX_API_KEYS_PER_USER=10

Analytics

VariableDescriptionDefault
ANALYTICS_CACHE_TTLCache TTL (seconds)300
ANALYTICS_TOP_URLS_LIMITTop URLs in overview10
ANALYTICS_RECENT_CLICKS_LIMITRecent clicks limit100
ANALYTICS_EXPORT_MAX_RECORDSMax records per export10000
ANALYTICS_EXPORT_BATCH_SIZEExport batch size1000
ANALYTICS_MAX_IN_MEMORY_CLICKSMax in-memory clicks50000
ANALYTICS_AGGREGATION_THRESHOLDDB aggregation threshold10000
bash
ANALYTICS_CACHE_TTL=300
ANALYTICS_EXPORT_MAX_RECORDS=10000

Email (SMTP)

VariableDescriptionDefault
SMTP_HOSTSMTP server host-
SMTP_PORTSMTP server port587
SMTP_USERSMTP username-
SMTP_PASSWORDSMTP password-
SMTP_FROMDefault from address-
bash
SMTP_HOST="smtp.gmail.com"
SMTP_PORT=587
SMTP_USER="your-email@gmail.com"
SMTP_PASSWORD="your-app-password"
SMTP_FROM="noreply@example.com"

Frontend Configuration

Required

Environment

VariableDescriptionExample
NODE_ENVEnvironment modeproduction
bash
NODE_ENV=production

API Connection

VariableDescriptionExample
NEXT_PUBLIC_API_URLBackend API URLhttps://s.yourdomain.com
NEXT_PUBLIC_SHORT_URL_DOMAINShort URL domainhttps://s.yourdomain.com
bash
NEXT_PUBLIC_API_URL="https://s.yourdomain.com"
NEXT_PUBLIC_SHORT_URL_DOMAIN="https://s.yourdomain.com"

Cloudflare Turnstile

VariableDescription
NEXT_PUBLIC_TURNSTILE_SITE_KEYTurnstile site key
bash
NEXT_PUBLIC_TURNSTILE_SITE_KEY="1x00000000000000000000AA"

Branding

VariableDescriptionDefault
NEXT_PUBLIC_BRAND_NAMEApplication nameOpen Short URL
NEXT_PUBLIC_BRAND_ICON_URLBrand icon URL-
NEXT_PUBLIC_BRAND_DESCRIPTIONBrand description-
bash
NEXT_PUBLIC_BRAND_NAME="My Short URLs"
NEXT_PUBLIC_BRAND_ICON_URL="https://example.com/icon.png"
NEXT_PUBLIC_BRAND_DESCRIPTION="URL shortening made simple"

Optional

Internationalization

VariableDescriptionDefault
NEXT_PUBLIC_LOCALEDefault localeen
bash
# Available: en, zh-TW, pt-BR
NEXT_PUBLIC_LOCALE="en"

AI Features

AI is disabled by default. Configure at least one provider API key to enable.

Settings:

VariableDescriptionDefault
AI_PROVIDERAI provider-
AI_MODELAI model name-
AI_TEMPERATUREResponse creativity (0.0-2.0)0.7
AI_MAX_TOKENSMax tokens in response4096
AI_TOP_PTop-p sampling (0.0-1.0)1.0

Provider API Keys:

VariableProvider
OPENAI_API_KEYGPT-4, GPT-3.5
ANTHROPIC_API_KEYClaude
GOOGLE_GENERATIVE_AI_API_KEYGemini
MISTRAL_API_KEYMistral
COHERE_API_KEYCohere
bash
AI_PROVIDER="anthropic"
AI_MODEL="claude-3-5-sonnet-20241022"
ANTHROPIC_API_KEY="sk-ant-..."

Google Vertex AI:

VariableDescription
GOOGLE_VERTEX_PROJECTGCP project ID
GOOGLE_VERTEX_LOCATIONGCP region
GOOGLE_APPLICATION_CREDENTIALSService account path
bash
GOOGLE_VERTEX_PROJECT="your-gcp-project"
GOOGLE_VERTEX_LOCATION="us-central1"
GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json"

Complete Examples

Backend (.env)

bash
# ============================================================
# REQUIRED
# ============================================================
NODE_ENV=production
DATABASE_URL="postgresql://shorturl:password@localhost:5432/open_short_url?schema=public&connection_limit=20"
SHORT_URL_DOMAIN="https://s.yourdomain.com"
FRONTEND_URL="https://app.yourdomain.com"
CORS_ORIGIN="https://app.yourdomain.com"
JWT_SECRET="your-super-secure-random-string-at-least-32-characters"
ADMIN_INITIAL_PASSWORD="your-strong-admin-password"

# ============================================================
# RECOMMENDED
# ============================================================
REDIS_HOST="localhost"
REDIS_PORT="6379"
TRUSTED_PROXY=true
# TURNSTILE_SECRET_KEY=""
# TURNSTILE_SITE_KEY=""
# WEBHOOK_SECRET_KEY=""

# ============================================================
# OPTIONAL
# ============================================================
PORT=4101
JWT_EXPIRES_IN="7d"
THROTTLE_TTL=60
THROTTLE_LIMIT=10
BRAND_NAME="My Short URLs"
MAX_API_KEYS_PER_USER=10
ANALYTICS_CACHE_TTL=300

Frontend (.env.local)

bash
# ============================================================
# REQUIRED
# ============================================================
NODE_ENV=production
NEXT_PUBLIC_API_URL="https://s.yourdomain.com"
NEXT_PUBLIC_SHORT_URL_DOMAIN="https://s.yourdomain.com"

# ============================================================
# RECOMMENDED
# ============================================================
# NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
NEXT_PUBLIC_BRAND_NAME="My Short URLs"

# ============================================================
# OPTIONAL
# ============================================================
NEXT_PUBLIC_LOCALE="en"
# AI_PROVIDER="anthropic"
# AI_MODEL="claude-3-5-sonnet-20241022"
# ANTHROPIC_API_KEY=""

Security Best Practices

  1. JWT Secret - Use a random string of at least 32 characters
  2. Admin Password - Use a strong password, change default immediately
  3. Database - Use strong passwords and restrict access
  4. CORS - Only allow your frontend domain
  5. HTTPS - Always use HTTPS in production
  6. Proxy - Only enable TRUSTED_PROXY behind trusted proxies
  7. Environment Files - Never commit .env files to git
  8. API Keys - Rotate API keys periodically

Next Steps

Released under the MIT License.