dokploy-template-toml
Generate template.toml configuration for Dokploy templates with variables, domains, environment mappings, and file mounts. Use when finalizing Dokploy templates.
When & Why to Use This Skill
This Claude skill automates the generation of template.toml configurations for Dokploy, streamlining the deployment of self-hosted applications. It simplifies complex infrastructure tasks such as dynamic variable generation (passwords, secrets, UUIDs), Traefik domain routing, environment variable mapping, and persistent file mounts to ensure secure and consistent deployments following infrastructure-as-code best practices.
Use Cases
- Standardizing deployment templates for new services within a Dokploy-managed infrastructure to ensure consistency.
- Automating the creation of secure, randomized credentials and encryption keys for database and API security during setup.
- Configuring multi-service domain routing and subdomain management for complex application stacks using Traefik.
- Managing persistent application configurations through automated file mounts and dynamic content injection for JSON, YAML, or INI files.
- Converting standard Docker Compose files into production-ready Dokploy templates with environment-specific variable mappings.
| name | dokploy-template-toml |
|---|---|
| description | "Generate template.toml configuration for Dokploy templates with variables, domains, environment mappings, and file mounts. Use when finalizing Dokploy templates." |
| version | 1.0.0 |
| author | Home Lab Infrastructure Team |
Dokploy Template TOML
When to Use This Skill
- When creating template.toml for a new Dokploy template
- When configuring Dokploy variable generation (passwords, secrets)
- When setting up domain configuration for services
- When adding file mounts for configuration files
- When user asks about "dokploy variables" or "template configuration"
When NOT to Use This Skill
- When working with docker-compose only (no Dokploy)
- For runtime configuration changes (modify environment vars instead)
Prerequisites
- Completed docker-compose.yml file
- List of required/optional environment variables
- Domain configuration requirements
- Knowledge of secret generation needs
Template.toml Structure
# Header comment with application info
# Application Name - Description
# https://github.com/example/application
[variables]
# User-provided and auto-generated variables
domain = "${domain}"
secret_key = "${base64:64}"
password = "${password:32}"
# Domain configuration for Traefik
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
# Environment variables for all services
[config.env]
APP_DOMAIN = "${domain}"
APP_SECRET = "${secret_key}"
# Optional file mounts
[[config.mounts]]
serviceName = "app"
mountPath = "/app/config.json"
content = """
{
"setting": "${variable}"
}
"""
Core Patterns
Pattern 1: Variable Definitions
[variables]
# User-provided domain (required)
domain = "${domain}"
# Random password generation
db_password = "${password:32}" # 32-char alphanumeric
api_key = "${password:48}" # 48-char alphanumeric
# Base64 secret generation
secret_key = "${base64:64}" # 64-char base64 encoded
jwt_secret = "${base64:32}" # 32-char base64 encoded
# UUID generation
instance_id = "${uuid}" # Random UUID v4
# User inputs
admin_email = "${email}" # User-provided email
username = "${username}" # User-provided username
# Derived variables (string concatenation)
app_url = "https://${domain}"
db_url = "postgresql://user:${db_password}@postgres:5432/db"
Supported Variable Types:
| Syntax | Description | Example Output |
|---|---|---|
${domain} |
User-provided domain | example.com |
${password:N} |
N-char random password | aB3kL9mN... |
${base64:N} |
N-char base64 secret | dGhpcyBpcyBh... |
${uuid} |
Random UUID v4 | 550e8400-e29b-41d4-a716-446655440000 |
${username} |
User-provided username | admin |
${email} |
User-provided email | user@example.com |
Pattern 2: Domain Configuration
# Single domain
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
# Multiple domains (different services)
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
[[config.domains]]
serviceName = "api"
port = 8080
host = "api.${domain}"
# Admin subdomain
[[config.domains]]
serviceName = "admin"
port = 9000
host = "admin.${domain}"
Important: serviceName must match the service name in docker-compose.yml
Pattern 3: Environment Variables
[config.env]
# Required variables (error if not set in compose)
APP_DOMAIN = "${domain}"
APP_SECRET = "${secret_key}"
DATABASE_PASSWORD = "${db_password}"
# Categories with comments
# ===========================================
# Database Configuration
# ===========================================
POSTGRES_DB = "appdb"
POSTGRES_USER = "appuser"
POSTGRES_PASSWORD = "${db_password}"
# ===========================================
# Application Settings
# ===========================================
APP_URL = "https://${domain}"
DEBUG = "false"
# ===========================================
# External Services (Cloudflare R2)
# ===========================================
S3_ENDPOINT = ""
S3_ACCESS_KEY_ID = ""
S3_SECRET_ACCESS_KEY = ""
S3_BUCKET = ""
S3_REGION = "auto"
Pattern 4: File Mounts
# JSON configuration file
[[config.mounts]]
serviceName = "app"
mountPath = "/app/config.json"
content = """
{
"domain": "${domain}",
"secret": "${secret_key}",
"database": {
"host": "postgres",
"port": 5432,
"name": "appdb"
}
}
"""
# INI/conf file
[[config.mounts]]
serviceName = "app"
mountPath = "/etc/app/settings.conf"
content = """
[general]
domain = ${domain}
debug = false
[database]
host = postgres
port = 5432
password = ${db_password}
"""
# YAML configuration
[[config.mounts]]
serviceName = "app"
mountPath = "/app/config.yaml"
content = """
server:
host: 0.0.0.0
port: 3000
domain: ${domain}
security:
secret_key: ${secret_key}
"""
Complete Examples
Example 1: Simple Web App (Paaster)
# Paaster - End-to-end encrypted pastebin
# https://github.com/WardPearce/paaster
[variables]
domain = "${domain}"
cookie_secret = "${base64:64}"
[[config.domains]]
serviceName = "paaster"
port = 3000
host = "${domain}"
[config.env]
# ===========================================
# Application Domain
# ===========================================
PAASTER_DOMAIN = "${domain}"
# ===========================================
# Security
# ===========================================
COOKIE_SECRET = "${cookie_secret}"
# ===========================================
# MongoDB Configuration
# ===========================================
MONGO_DB = "paasterv3"
# ===========================================
# Cloudflare R2 Storage
# Get from: Cloudflare Dashboard > R2 > Manage R2 API Tokens
# Endpoint format: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
# ===========================================
S3_ENDPOINT = ""
S3_ACCESS_KEY_ID = ""
S3_SECRET_ACCESS_KEY = ""
S3_BUCKET = ""
S3_REGION = "auto"
Example 2: Git Service with Database (Forgejo)
# Forgejo - Self-hosted Git forge
# https://forgejo.org/
[variables]
domain = "${domain}"
postgres_password = "${password:32}"
secret_key = "${base64:64}"
internal_token = "${base64:48}"
jwt_secret = "${base64:48}"
[[config.domains]]
serviceName = "forgejo"
port = 3000
host = "${domain}"
[config.env]
# ===========================================
# Domain Configuration
# ===========================================
FORGEJO__server__DOMAIN = "${domain}"
FORGEJO__server__ROOT_URL = "https://${domain}/"
# ===========================================
# Database Configuration
# ===========================================
FORGEJO__database__DB_TYPE = "postgres"
FORGEJO__database__HOST = "postgres:5432"
FORGEJO__database__NAME = "forgejo"
FORGEJO__database__USER = "forgejo"
FORGEJO__database__PASSWD = "${postgres_password}"
# PostgreSQL credentials
POSTGRES_USER = "forgejo"
POSTGRES_DB = "forgejo"
POSTGRES_PASSWORD = "${postgres_password}"
# ===========================================
# Security Keys
# ===========================================
FORGEJO__security__SECRET_KEY = "${secret_key}"
FORGEJO__security__INTERNAL_TOKEN = "${internal_token}"
FORGEJO__oauth2__JWT_SECRET = "${jwt_secret}"
# ===========================================
# Optional: SSH Configuration
# ===========================================
SSH_PORT = "2222"
Example 3: Complex Stack (Paperless-ngx)
# Paperless-ngx - Document management system
# https://docs.paperless-ngx.com/
[variables]
domain = "${domain}"
postgres_password = "${password:32}"
secret_key = "${base64:64}"
admin_user = "${username}"
admin_password = "${password:16}"
admin_email = "${email}"
[[config.domains]]
serviceName = "paperless"
port = 8000
host = "${domain}"
[config.env]
# ===========================================
# Database Configuration
# ===========================================
POSTGRES_DB = "paperless"
POSTGRES_USER = "paperless"
POSTGRES_PASSWORD = "${postgres_password}"
# Paperless database settings
PAPERLESS_DBHOST = "postgres"
PAPERLESS_DBNAME = "paperless"
PAPERLESS_DBUSER = "paperless"
PAPERLESS_DBPASS = "${postgres_password}"
# ===========================================
# Application Settings
# ===========================================
PAPERLESS_SECRET_KEY = "${secret_key}"
PAPERLESS_URL = "https://${domain}"
PAPERLESS_ALLOWED_HOSTS = "${domain}"
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${domain}"
# ===========================================
# Admin User (created on first run)
# ===========================================
PAPERLESS_ADMIN_USER = "${admin_user}"
PAPERLESS_ADMIN_PASSWORD = "${admin_password}"
PAPERLESS_ADMIN_MAIL = "${admin_email}"
# ===========================================
# Document Processing
# ===========================================
PAPERLESS_OCR_LANGUAGE = "eng"
PAPERLESS_TIKA_ENABLED = "1"
PAPERLESS_TIKA_ENDPOINT = "http://tika:9998"
PAPERLESS_TIKA_GOTENBERG_ENDPOINT = "http://gotenberg:3000"
# ===========================================
# Redis
# ===========================================
PAPERLESS_REDIS = "redis://redis:6379"
Example 4: Service with Config File Mount
# ANyONe Protocol Relay
# https://github.com/anyone-protocol/ator-protocol
[variables]
relay_nickname = "${username}"
relay_contact = "${email}"
control_password = "${password:24}"
orport = "9001"
dirport = "9030"
controlport = "9051"
wallet_address = ""
[config.env]
ACCEPT_TOS = "1"
ANON_NICKNAME = "${relay_nickname}"
ANON_CONTACT = "${relay_contact}"
ANON_ORPORT = "${orport}"
ANON_DIRPORT = "${dirport}"
ANON_CONTROLPORT = "${controlport}"
[[config.mounts]]
serviceName = "anon-relay"
mountPath = "/etc/anon/anonrc"
content = """
# ANyONe Protocol Relay Configuration
# Auto-generated by Dokploy
# Relay Identity
Nickname ${relay_nickname}
ContactInfo ${relay_contact}
# Network Ports
ORPort ${orport}
DirPort ${dirport}
ControlPort ${controlport}
# Control Authentication
HashedControlPassword ${control_password}
# Relay Type (exit disabled by default)
ExitRelay 0
# Bandwidth Limits (optional)
# RelayBandwidthRate 1 MB
# RelayBandwidthBurst 2 MB
"""
Quality Standards
Mandatory Requirements
- All required variables defined in
[variables] - Domain configuration matches docker-compose service names
- Environment variables organized with category comments
- Sensitive values use auto-generation (password, base64)
- User-facing values use appropriate prompts (domain, email)
Documentation Standards
- Add header comment with app name and link
- Comment each category in
[config.env] - Document where to get external credentials (R2, etc.)
Security Standards
- Never hardcode passwords or secrets
- Use
${password:N}for database passwords - Use
${base64:N}for encryption keys - Leave external API keys blank for user input
Common Pitfalls
Pitfall 1: serviceName mismatch
Issue: Domain config doesn't work
Solution: serviceName must exactly match docker-compose service name
Pitfall 2: Missing variable definitions
Issue: Variables referenced but not defined
Solution: Define all ${var} references in [variables] section
Pitfall 3: Password in plain text
Issue: Secrets visible in Dokploy UI
Solution: Use ${password:N} or ${base64:N} for auto-generation
Pitfall 4: Wrong mount serviceName
Issue: Config file not mounted Solution: Match serviceName to exact docker-compose service
Integration
Skills-First Approach (v2.0+)
This skill is part of the skills-first architecture - loaded progressively during the Generation phase as the final step before validation.
Related Skills
dokploy-compose-structure: Service names for domain configdokploy-environment-config: Environment variable patternsdokploy-cloudflare-integration: R2 configuration
Invoked By
/dokploy-createcommand: Phase 3 (Generation) - Step 6 (Final)
Order in Workflow (Progressive Loading)
dokploy-compose-structure: Create compose filedokploy-traefik-routing: Add routingdokploy-health-patterns: Add health checksdokploy-cloudflare-integration: Add CF config (if applicable)dokploy-environment-config: Plan environment vars- This skill: Create template.toml (final generation step)
See: .claude/commands/dokploy-create.md for full workflow