Overview
Environment variables provide runtime configuration for your applications. Dokploy supports environment variables at multiple levels with inheritance and secret management.
Variable Hierarchy
Dokploy applies environment variables in this order (later overrides earlier):
Project Variables
Shared across all applications in a project: # Set at project level
COMPANY_NAME = Acme Corp
DEFAULT_REGION = us-east-1
Environment Variables
Specific to an environment (dev, staging, prod): # Set at environment level
ENV_NAME = production
LOG_LEVEL = info
Application Variables
Specific to individual applications: # Set at application level
DATABASE_URL = postgresql://...
API_KEY = abc123
PORT = 3000
Highest priority - overrides project and environment variables.
Configuration
Basic Variables
Set environment variables in the Dokploy UI or via API:
{
"applicationId" : "app-123" ,
"env" : "NODE_ENV=production \n PORT=3000 \n DATABASE_URL=postgresql://user:pass@db:5432/myapp \n API_URL=https://api.example.com"
}
Format:
One variable per line
Use KEY=value format
No quotes needed around values
Empty lines are ignored
Multi-line Values
For values containing newlines:
# Private key example
PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"
# JSON configuration
CONFIG = '{"key":"value","nested":{"data":"here"}}'
Special Characters
Escape special characters in values:
# Quotes in values
MESSAGE = "He said \" Hello \" "
# Dollar signs
PASSWORD = "my \$ ecret \$ pass"
# Equals signs in value
CONNECTION = "host=localhost;port=5432;password=pass=word"
Common Use Cases
Database Connection
Configure database connectivity:
PostgreSQL
MySQL
MongoDB
Redis
DATABASE_URL = postgresql://user:password@postgres:5432/myapp
PGHOST = postgres
PGPORT = 5432
PGDATABASE = myapp
PGUSER = user
PGPASSWORD = password
Use internal Docker network hostnames (e.g., postgres, redis) instead of localhost or IP addresses.
Framework-Specific
Configure popular frameworks:
Next.js
Django
Laravel
Rails
Express
FastAPI
NODE_ENV = production
PORT = 3000
# Public variables (exposed to browser)
NEXT_PUBLIC_API_URL = https://api.example.com
NEXT_PUBLIC_SITE_URL = https://example.com
# Server-only variables
DATABASE_URL = postgresql://...
SECRET_KEY = your-secret-key
API_SECRET = internal-secret
DJANGO_SETTINGS_MODULE = myapp.settings.production
SECRET_KEY = your-django-secret-key
DEBUG = False
ALLOWED_HOSTS = example.com,www.example.com
DATABASE_URL = postgresql://...
REDIS_URL = redis://redis:6379
# Email
EMAIL_HOST = smtp.example.com
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = [email protected]
EMAIL_HOST_PASSWORD = email-password
APP_NAME = MyApp
APP_ENV = production
APP_KEY = base64:your-app-key
APP_DEBUG = false
APP_URL = https://example.com
DB_CONNECTION = mysql
DB_HOST = mysql
DB_PORT = 3306
DB_DATABASE = myapp
DB_USERNAME = user
DB_PASSWORD = password
CACHE_DRIVER = redis
QUEUE_CONNECTION = redis
SESSION_DRIVER = redis
REDIS_HOST = redis
REDIS_PORT = 6379
RAILS_ENV = production
SECRET_KEY_BASE = your-secret-key-base
DATABASE_URL = postgresql://...
REDIS_URL = redis://redis:6379
RAILS_SERVE_STATIC_FILES = true
RAILS_LOG_TO_STDOUT = true
# Action Mailer
SMTP_ADDRESS = smtp.example.com
SMTP_PORT = 587
SMTP_USERNAME = [email protected]
SMTP_PASSWORD = email-password
NODE_ENV = production
PORT = 3000
DATABASE_URL = postgresql://...
REDIS_URL = redis://redis:6379
SESSION_SECRET = your-session-secret
JWT_SECRET = your-jwt-secret
# CORS
CORS_ORIGIN = https://example.com
ENVIRONMENT = production
HOST = 0.0.0.0
PORT = 8000
DATABASE_URL = postgresql://...
REDIS_URL = redis://redis:6379
SECRET_KEY = your-secret-key
ALGORITHM = HS256
# CORS
ALLOWED_ORIGINS = https://example.com,https://www.example.com
Third-Party Services
Configure external service integrations:
# AWS
AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_DEFAULT_REGION = us-east-1
AWS_S3_BUCKET = my-bucket
# Stripe
STRIPE_PUBLIC_KEY = pk_live_xxxxx
STRIPE_SECRET_KEY = sk_live_xxxxx
STRIPE_WEBHOOK_SECRET = whsec_xxxxx
# SendGrid
SENDGRID_API_KEY = SG.xxxxx
SENDGRID_FROM_EMAIL = [email protected]
# Sentry
SENTRY_DSN = https://[email protected] /xxxxx
SENTRY_ENVIRONMENT = production
# Auth0
AUTH0_DOMAIN = myapp.auth0.com
AUTH0_CLIENT_ID = xxxxx
AUTH0_CLIENT_SECRET = xxxxx
Environment File Generation
Dokploy can create a .env file in your application container:
{
"createEnvFile" : true , // Generate .env file
"env" : "NODE_ENV=production \n DATABASE_URL=postgresql://..."
}
When enabled:
Creates /app/.env in the container
Contains all environment variables
Useful for applications that read from .env files
Works alongside environment variables
Disable createEnvFile if your application doesn’t need it. Environment variables are always available regardless of this setting.
Build-Time vs Runtime
Build Arguments
Available during Docker build only:
{
"buildArgs" : "NODE_ENV=production \n API_URL=https://api.example.com"
}
Use for:
Compilation flags
Build-time URLs (Next.js NEXT_PUBLIC_*)
Version numbers
Build optimizations
Example in Dockerfile:
ARG NODE_ENV=production
ARG API_URL
# Available during build
RUN npm run build
# Not available at runtime
Environment Variables
Available at runtime only:
{
"env" : "DATABASE_URL=postgresql://... \n REDIS_URL=redis://..."
}
Use for:
Database connections
API keys
Runtime configuration
Feature flags
Most configuration should use environment variables, not build arguments. Build arguments are baked into the image.
Preview Deployment Variables
Set different variables for preview deployments:
{
// Production variables
"env" : "NODE_ENV=production \n DATABASE_URL=postgresql://prod-db:5432/myapp" ,
// Preview-specific variables
"previewEnv" : "NODE_ENV=preview \n DATABASE_URL=postgresql://preview-db:5432/myapp \n DEBUG=true" ,
// Preview build arguments
"previewBuildArgs" : "BUILD_ENV=preview \n ENABLE_SOURCEMAPS=true"
}
Preview variables override production variables in preview deployments.
Variable Interpolation
Reference other variables in values:
# Base URL
BASE_URL = https://example.com
# Reference in other variables
API_URL = ${ BASE_URL } /api
CDN_URL = ${ BASE_URL } /cdn
Variable interpolation is handled by your application or shell, not by Dokploy.
Secret Management
Marking as Secret
Mark sensitive variables as secrets in the UI:
Add variable in Dokploy dashboard
Click the lock icon next to the variable
Value is encrypted and hidden
Build Secrets
For secrets needed during build:
{
"buildSecrets" : "NPM_TOKEN=npm_xxxxx \n GITHUB_TOKEN=ghp_xxxxx"
}
Use in Dockerfile:
# syntax=docker/dockerfile:1.4
RUN --mount=type=secret,id=NPM_TOKEN \
echo "//registry.npmjs.org/:_authToken=$(cat /run/secrets/NPM_TOKEN)" > ~/.npmrc && \
npm install && \
rm ~/.npmrc
Build secrets are:
Not stored in image layers
Not available at runtime
More secure than build arguments
Best Practices
# .gitignore
.env
.env.local
.env.*.local
config/secrets.yml
* .pem
* .key
Always use environment variables for secrets, never hardcode in source.
# Generate secure random secrets
openssl rand -base64 32
# Example output
SECRET_KEY = 8f7d9c6b5a4e3d2c1b0a9f8e7d6c5b4a3d2c1b0a9f8e7d6c5b4a
Update secrets periodically:
Generate new secret
Update in Dokploy
Redeploy application
Revoke old secret
Frequency: Every 90 days for high-security apps.
Use different secrets for each environment: # Production
API_KEY = prod_xxxxx
DATABASE_URL = postgresql://prod-db/app
# Staging
API_KEY = staging_xxxxx
DATABASE_URL = postgresql://staging-db/app
# Development
API_KEY = dev_xxxxx
DATABASE_URL = postgresql://dev-db/app
Variable Validation
Validate required variables in your application:
// config.js
const requiredEnvVars = [
'DATABASE_URL' ,
'REDIS_URL' ,
'SECRET_KEY'
];
for ( const envVar of requiredEnvVars ) {
if ( ! process . env [ envVar ]) {
throw new Error ( `Missing required environment variable: ${ envVar } ` );
}
}
module . exports = {
databaseUrl: process . env . DATABASE_URL ,
redisUrl: process . env . REDIS_URL ,
secretKey: process . env . SECRET_KEY ,
port: parseInt ( process . env . PORT || '3000' , 10 )
};
Accessing Variables
In Application Code
Node.js
Python
Go
PHP
Ruby
// Access via process.env
const dbUrl = process . env . DATABASE_URL ;
const port = parseInt ( process . env . PORT || '3000' , 10 );
const isProduction = process . env . NODE_ENV === 'production' ;
// Using dotenv package (optional)
require ( 'dotenv' ). config ();
import os
# Access via os.environ
db_url = os.environ[ 'DATABASE_URL' ]
port = int (os.getenv( 'PORT' , '8000' ))
is_production = os.getenv( 'ENVIRONMENT' ) == 'production'
# Using python-dotenv (optional)
from dotenv import load_dotenv
load_dotenv()
import " os "
// Access via os.Getenv
dbURL := os . Getenv ( "DATABASE_URL" )
port := os . Getenv ( "PORT" )
isProduction := os . Getenv ( "ENVIRONMENT" ) == "production"
// With default value
port := os . Getenv ( "PORT" )
if port == "" {
port = "8080"
}
<? php
// Access via $_ENV or getenv()
$dbUrl = $_ENV [ 'DATABASE_URL' ];
$port = getenv ( 'PORT' ) ?: 8000 ;
$isProduction = getenv ( 'APP_ENV' ) === 'production' ;
// Using vlucas/phpdotenv (optional)
$dotenv = Dotenv\ Dotenv :: createImmutable ( __DIR__ );
$dotenv -> load ();
# Access via ENV
db_url = ENV [ 'DATABASE_URL' ]
port = ENV . fetch ( 'PORT' , 3000 ). to_i
is_production = ENV [ 'RAILS_ENV' ] == 'production'
# Using dotenv gem (optional)
require 'dotenv/load'
In Docker Compose
Reference Dokploy environment variables in compose files:
services :
app :
image : myapp:latest
environment :
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- NODE_ENV=production
env_file :
- .env # If using env file generation
Dynamic Configuration
Update variables without redeploying:
# Update variables via API
curl -X POST https://your-domain.com/api/trpc/application.saveEnvironment \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "app-123",
"env": "NODE_ENV=production\nDATABASE_URL=postgresql://...\nNEW_FEATURE=enabled",
"createEnvFile": true
}'
# Redeploy to apply changes
curl -X POST https://your-domain.com/api/trpc/application.redeploy \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "app-123",
"title": "Update environment variables"
}'
Variable changes require a redeploy to take effect. Use the redeploy endpoint (not deploy) to avoid rebuilding from source.
Troubleshooting
Symptoms: Application can’t read environment variableSolutions:
Verify variable is set:
docker exec < container-i d > env | grep VARIABLE_NAME
Check variable format:
# Correct
KEY = value
# Incorrect
export KEY = value # Don't use export
KEY = value # No spaces around =
Ensure application reads from correct source:
// Node.js
console . log ( process . env . VARIABLE_NAME );
Variable Contains Wrong Value
Symptoms: Variable has unexpected valueSolutions:
Check variable hierarchy:
Application variables override environment variables
Environment variables override project variables
Verify no hardcoded values:
// Check source code for hardcoded values
const apiUrl = process . env . API_URL || 'http://localhost:3000' ;
Ensure redeploy after changes:
# Variables only apply after redeploy
curl -X POST .../application.redeploy
Special Characters Causing Issues
Symptoms: Variables with special characters breakSolutions:
Escape special characters:
# Dollar signs
PASSWORD = my \$ ecret
# Quotes
MESSAGE = "He said \" Hello \" "
Use base64 for complex values:
# Encode
echo "complex $value " | base64
# Result: Y29tcGxleCR2YWx1ZQ==
# In environment
ENCODED_VALUE = Y29tcGxleCR2YWx1ZQ = =
# Decode in application
const decoded = Buffer.from ( process.env.ENCODED_VALUE, 'base64' ) .toString ();
Build Arguments Not Working at Runtime
Symptoms: Build args are undefined at runtimeSolutions:
Build arguments are build-time only. Use environment variables:# Build-time (not available at runtime)
ARG API_URL
# Convert to environment variable
ENV API_URL=${API_URL}
# Now available at runtime
Or configure in Dokploy: {
"buildArgs" : "API_URL=https://api.example.com" ,
"env" : "API_URL=https://api.example.com" // For runtime
}
API Reference
Save Environment Variables
curl -X POST https://your-domain.com/api/trpc/application.saveEnvironment \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "app-123",
"env": "NODE_ENV=production\nDATABASE_URL=postgresql://...",
"buildArgs": "NODE_ENV=production",
"buildSecrets": "NPM_TOKEN=npm_xxxxx",
"createEnvFile": true
}'
Update Application
curl -X POST https://your-domain.com/api/trpc/application.update \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"applicationId": "app-123",
"env": "UPDATED_VAR=new-value"
}'
Next Steps
Build Configuration Configure build process and arguments
Git Integration Automate deployments from Git
Security Security best practices
Deployments Overview Learn about deployment workflows