Environment variable patterns for Dokploy templates including required vs optional syntax, secrets, connection strings, and configuration organization.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
npx agent-skills-cli listSkill Instructions
name: dokploy-environment-config description: "Environment variable patterns for Dokploy templates including required vs optional syntax, secrets, connection strings, and configuration organization." version: 1.0.0 author: Home Lab Infrastructure Team
Dokploy Environment Configuration
When to Use This Skill
- When defining environment variables for Dokploy templates
- When deciding between required and optional variables
- When configuring database connection strings
- When organizing environment sections
- When user asks about "environment variables" or "secrets"
When NOT to Use This Skill
- For template.toml variables (use dokploy-template-toml)
- For Traefik configuration (use dokploy-traefik-routing)
Prerequisites
- Application documentation (required env vars)
- Understanding of docker-compose variable syntax
- Knowledge of sensitive vs non-sensitive data
Core Patterns
Pattern 1: Required Variables (:? syntax)
Variables that MUST be set - deployment fails without them:
environment:
DOMAIN: ${DOMAIN:?Set your domain (e.g., example.com)}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:?Set a secure database password}
SECRET_KEY: ${SECRET_KEY:?Set a secret key for session encryption}
Syntax: ${VAR_NAME:?Error message}
- If VAR_NAME is unset or empty, shows error message and fails
- Use for: domains, passwords, API keys, secrets
Pattern 2: Optional Variables (:- syntax)
Variables with sensible defaults:
environment:
LOG_LEVEL: ${LOG_LEVEL:-info}
WORKERS: ${WORKERS:-4}
CACHE_TTL: ${CACHE_TTL:-3600}
DEBUG: ${DEBUG:-false}
Syntax: ${VAR_NAME:-default_value}
- If VAR_NAME is unset or empty, uses default_value
- Use for: tuning parameters, feature flags, optional settings
Pattern 3: Internal Constants
Values that shouldn't change:
environment:
# Database host is always the service name
PGHOST: postgres
REDIS_HOST: redis
# Ports are fixed in the container
PGPORT: "5432"
REDIS_PORT: "6379"
Pattern 4: Computed Values
Variables derived from other variables:
environment:
APP_URL: https://${DOMAIN}
DATABASE_URL: postgresql://${DB_USER}:${DB_PASS}@postgres:5432/${DB_NAME}
MONGO_URL: mongodb://mongodb:27017/${MONGO_DB:-appdb}
Environment Variable Categories
Category 1: Domain & URLs
environment:
# Primary domain (required)
DOMAIN: ${DOMAIN:?Set your domain}
# Derived URLs
APP_URL: https://${DOMAIN}
PUBLIC_URL: https://${DOMAIN}
CORS_ORIGIN: https://${DOMAIN}
ALLOWED_HOSTS: ${DOMAIN}
Category 2: Database Configuration
PostgreSQL:
environment:
POSTGRES_DB: ${POSTGRES_DB:-appdb}
POSTGRES_USER: ${POSTGRES_USER:-appuser}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set database password}
# For app service connecting to postgres
DATABASE_URL: postgresql://${POSTGRES_USER:-appuser}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-appdb}
# OR individual variables
DB_HOST: postgres
DB_PORT: "5432"
DB_NAME: ${POSTGRES_DB:-appdb}
DB_USER: ${POSTGRES_USER:-appuser}
DB_PASS: ${POSTGRES_PASSWORD}
MongoDB:
environment:
MONGO_INITDB_DATABASE: ${MONGO_DB:-appdb}
# For app service
MONGO_URL: mongodb://mongodb:27017/${MONGO_DB:-appdb}
MONGO_DB: ${MONGO_DB:-appdb}
Redis:
environment:
# For app service
REDIS_URL: redis://redis:6379
REDIS_HOST: redis
REDIS_PORT: "6379"
Category 3: Security & Secrets
environment:
# Session/cookie security
SECRET_KEY: ${SECRET_KEY:?Set a secret key}
COOKIE_SECRET: ${COOKIE_SECRET:?Set cookie secret}
# JWT/Auth
JWT_SECRET: ${JWT_SECRET:?Set JWT secret}
# API keys (user-provided)
API_KEY: ${API_KEY:?Set API key}
Category 4: External Services (Cloudflare R2)
environment:
# S3-compatible storage (Cloudflare R2)
S3_ENDPOINT: ${S3_ENDPOINT:?Set Cloudflare R2 endpoint}
S3_REGION: ${S3_REGION:-auto}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?Set R2 access key ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?Set R2 secret access key}
S3_BUCKET: ${S3_BUCKET:?Set R2 bucket name}
S3_FORCE_PATH_STYLE: "false"
Category 5: Application Settings
environment:
# Feature flags
DEBUG: ${DEBUG:-false}
ENABLE_FEATURE_X: ${ENABLE_FEATURE_X:-true}
# Performance tuning
WORKERS: ${WORKERS:-4}
MAX_CONNECTIONS: ${MAX_CONNECTIONS:-100}
CACHE_TTL: ${CACHE_TTL:-3600}
# Logging
LOG_LEVEL: ${LOG_LEVEL:-info}
LOG_FORMAT: ${LOG_FORMAT:-json}
Category 6: Admin User (First Run)
environment:
ADMIN_USER: ${ADMIN_USER:-admin}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?Set admin password}
ADMIN_EMAIL: ${ADMIN_EMAIL:?Set admin email}
Complete Examples
Example 1: Simple Web App (Paaster)
services:
paaster:
environment:
# ===========================================
# Domain Configuration
# ===========================================
PAASTER_DOMAIN: ${PAASTER_DOMAIN:?Set your domain}
# ===========================================
# Session Security
# ===========================================
COOKIE_SECRET: ${COOKIE_SECRET:?Set a secure random cookie secret}
# ===========================================
# MongoDB Connection
# ===========================================
MONGO_DB: ${MONGO_DB:-paasterv3}
MONGO_URL: mongodb://mongodb:27017/${MONGO_DB:-paasterv3}
# ===========================================
# S3 Storage (Cloudflare R2)
# Get from: Cloudflare Dashboard > R2 > Manage R2 API Tokens
# Endpoint format: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
# ===========================================
S3_ENDPOINT: ${S3_ENDPOINT:?Set Cloudflare R2 endpoint}
S3_REGION: ${S3_REGION:-auto}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?Set R2 access key ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?Set R2 secret access key}
S3_BUCKET: ${S3_BUCKET:?Set R2 bucket name}
S3_FORCE_PATH_STYLE: "false"
mongodb:
environment:
MONGO_INITDB_DATABASE: ${MONGO_DB:-paasterv3}
Example 2: Complex Stack (Paperless-ngx)
services:
paperless:
environment:
# ===========================================
# Application Settings
# ===========================================
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY:?Set secret key}
PAPERLESS_URL: https://${PAPERLESS_DOMAIN}
PAPERLESS_ALLOWED_HOSTS: ${PAPERLESS_DOMAIN}
PAPERLESS_CORS_ALLOWED_HOSTS: https://${PAPERLESS_DOMAIN}
# ===========================================
# Database (PostgreSQL)
# ===========================================
PAPERLESS_DBHOST: postgres
PAPERLESS_DBPORT: "5432"
PAPERLESS_DBNAME: ${POSTGRES_DB:-paperless}
PAPERLESS_DBUSER: ${POSTGRES_USER:-paperless}
PAPERLESS_DBPASS: ${POSTGRES_PASSWORD:?Set database password}
# ===========================================
# Cache (Redis)
# ===========================================
PAPERLESS_REDIS: redis://redis:6379
# ===========================================
# Document Processing
# ===========================================
PAPERLESS_OCR_LANGUAGE: ${OCR_LANGUAGE:-eng}
PAPERLESS_TIKA_ENABLED: "1"
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
# ===========================================
# Admin User (created on first run)
# ===========================================
PAPERLESS_ADMIN_USER: ${ADMIN_USER:-admin}
PAPERLESS_ADMIN_PASSWORD: ${ADMIN_PASSWORD:?Set admin password}
PAPERLESS_ADMIN_MAIL: ${ADMIN_EMAIL:?Set admin email}
postgres:
environment:
POSTGRES_DB: ${POSTGRES_DB:-paperless}
POSTGRES_USER: ${POSTGRES_USER:-paperless}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set database password}
Example 3: Git Service (Forgejo)
services:
forgejo:
environment:
# ===========================================
# Server Configuration
# ===========================================
FORGEJO__server__DOMAIN: ${FORGEJO_DOMAIN}
FORGEJO__server__ROOT_URL: https://${FORGEJO_DOMAIN}/
FORGEJO__server__SSH_DOMAIN: ${FORGEJO_DOMAIN}
FORGEJO__server__SSH_PORT: ${SSH_PORT:-2222}
# ===========================================
# Database (PostgreSQL)
# ===========================================
FORGEJO__database__DB_TYPE: postgres
FORGEJO__database__HOST: postgres:5432
FORGEJO__database__NAME: ${POSTGRES_DB:-forgejo}
FORGEJO__database__USER: ${POSTGRES_USER:-forgejo}
FORGEJO__database__PASSWD: ${POSTGRES_PASSWORD:?Set database password}
# ===========================================
# Security
# ===========================================
FORGEJO__security__SECRET_KEY: ${SECRET_KEY:?Set secret key}
FORGEJO__security__INTERNAL_TOKEN: ${INTERNAL_TOKEN:?Set internal token}
FORGEJO__oauth2__JWT_SECRET: ${JWT_SECRET:?Set JWT secret}
# ===========================================
# Service Settings
# ===========================================
FORGEJO__service__DISABLE_REGISTRATION: ${DISABLE_REGISTRATION:-false}
FORGEJO__service__REQUIRE_SIGNIN_VIEW: ${REQUIRE_SIGNIN:-false}
postgres:
environment:
POSTGRES_DB: ${POSTGRES_DB:-forgejo}
POSTGRES_USER: ${POSTGRES_USER:-forgejo}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set database password}
Sensitive Data Guidelines
Always Required (:?)
- Domain names
- Database passwords
- Secret keys / JWT secrets
- API keys and tokens
- Admin passwords
- S3/R2 credentials
Usually Optional (:-)
- Usernames (with sensible default)
- Database names
- Feature flags
- Tuning parameters
- Log levels
Never in Environment
- Private keys (use mounted secrets)
- Large certificates (use volume mounts)
- Multi-line configurations (use file mounts)
Quality Standards
Mandatory Requirements
- All required vars use
:?with clear error message - All optional vars use
:-with sensible default - Environment sections have category comments
- Database passwords marked as required
- Secret keys marked as required
- Internal service hosts use service names
Organization Standards
- Group variables by category
- Add comment headers for each category
- Document where to obtain external credentials
- Use consistent naming (UPPER_SNAKE_CASE)
Common Pitfalls
Pitfall 1: Missing error message
Issue: ${VAR:?} gives unclear error
Solution: Always add descriptive message: ${VAR:?Set your domain}
Pitfall 2: Using IP addresses
Issue: Service IPs change on restart
Solution: Use service names: postgres, redis, mongodb
Pitfall 3: Hardcoded secrets
Issue: Secrets visible in repository
Solution: Use variables: ${PASSWORD:?Set password}
Pitfall 4: Missing quotes on ports
Issue: YAML interprets as number
Solution: Quote port strings: DB_PORT: "5432"
Integration
Skills-First Approach (v2.0+)
This skill is part of the skills-first architecture - loaded during Generation phase to configure environment variables before creating template.toml.
Related Skills
dokploy-template-toml: Variable generation in template.tomldokploy-security-hardening: Secret managementdokploy-cloudflare-integration: R2 credentials
Invoked By
/dokploy-createcommand: Phase 3 (Generation) - Step 5
Order in Workflow (Progressive Loading)
dokploy-compose-structure: Create base structuredokploy-traefik-routing: Add routing labelsdokploy-health-patterns: Add health checksdokploy-cloudflare-integration: Add CF integration (if applicable)- This skill: Configure environment variables (Step 5)
dokploy-template-toml: Create template.toml
See: .claude/commands/dokploy-create.md for full workflow
More by majiayu000
View allDeploys PostgreSQL on Kubernetes using the CloudNativePG operator with automated failover. Use when setting up PostgreSQL for production workloads, high availability, or local K8s development. Covers operator installation, cluster creation, connection secrets, and backup configuration. NOT when using managed Postgres (Neon, RDS, Cloud SQL) or simple Docker containers.
Use when Codex needs to run CI/CD or cross-service automations through the Composio MCP server.
Clean up git branches by analyzing merged/unmerged status, archiving completed work, and organizing active branches. This skill should be used when the user wants to clean up branches, organize their git repository, or review branch status. Triggered by "/clean-branches", "/branches", "clean branches", "check branches", "check branch", or "branches".
Develop with Nix including packages, flakes, NixOS, and derivations. Activate when working with .nix files, flake.nix, flake.lock, or user mentions Nix, nixpkgs, NixOS, derivations, flakes, nix-shell, nix develop, home-manager, or packaging.
