| 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
[variables]
domain = "${domain}"
secret_key = "${base64:64}"
password = "${password:32}"
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
[config.env]
APP_DOMAIN = "${domain}"
APP_SECRET = "${secret_key}"
[[config.mounts]]
serviceName = "app"
mountPath = "/app/config.json"
content = """
{
"setting": "${variable}"
}
"""
Core Patterns
Pattern 1: Variable Definitions
[variables]
domain = "${domain}"
db_password = "${password:32}"
api_key = "${password:48}"
secret_key = "${base64:64}"
jwt_secret = "${base64:32}"
instance_id = "${uuid}"
admin_email = "${email}"
username = "${username}"
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
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
[[config.domains]]
serviceName = "app"
port = 3000
host = "${domain}"
[[config.domains]]
serviceName = "api"
port = 8080
host = "api.${domain}"
[[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]
APP_DOMAIN = "${domain}"
APP_SECRET = "${secret_key}"
DATABASE_PASSWORD = "${db_password}"
POSTGRES_DB = "appdb"
POSTGRES_USER = "appuser"
POSTGRES_PASSWORD = "${db_password}"
APP_URL = "https://${domain}"
DEBUG = "false"
S3_ENDPOINT = ""
S3_ACCESS_KEY_ID = ""
S3_SECRET_ACCESS_KEY = ""
S3_BUCKET = ""
S3_REGION = "auto"
Pattern 4: File Mounts
[[config.mounts]]
serviceName = "app"
mountPath = "/app/config.json"
content = """
{
"domain": "${domain}",
"secret": "${secret_key}",
"database": {
"host": "postgres",
"port": 5432,
"name": "appdb"
}
}
"""
[[config.mounts]]
serviceName = "app"
mountPath = "/etc/app/settings.conf"
content = """
[general]
domain = ${domain}
debug = false
[database]
host = postgres
port = 5432
password = ${db_password}
"""
[[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)
[variables]
domain = "${domain}"
cookie_secret = "${base64:64}"
[[config.domains]]
serviceName = "paaster"
port = 3000
host = "${domain}"
[config.env]
PAASTER_DOMAIN = "${domain}"
COOKIE_SECRET = "${cookie_secret}"
MONGO_DB = "paasterv3"
S3_ENDPOINT = ""
S3_ACCESS_KEY_ID = ""
S3_SECRET_ACCESS_KEY = ""
S3_BUCKET = ""
S3_REGION = "auto"
Example 2: Git Service with Database (Forgejo)
[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]
FORGEJO__server__DOMAIN = "${domain}"
FORGEJO__server__ROOT_URL = "https://${domain}/"
FORGEJO__database__DB_TYPE = "postgres"
FORGEJO__database__HOST = "postgres:5432"
FORGEJO__database__NAME = "forgejo"
FORGEJO__database__USER = "forgejo"
FORGEJO__database__PASSWD = "${postgres_password}"
POSTGRES_USER = "forgejo"
POSTGRES_DB = "forgejo"
POSTGRES_PASSWORD = "${postgres_password}"
FORGEJO__security__SECRET_KEY = "${secret_key}"
FORGEJO__security__INTERNAL_TOKEN = "${internal_token}"
FORGEJO__oauth2__JWT_SECRET = "${jwt_secret}"
SSH_PORT = "2222"
Example 3: Complex Stack (Paperless-ngx)
[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]
POSTGRES_DB = "paperless"
POSTGRES_USER = "paperless"
POSTGRES_PASSWORD = "${postgres_password}"
PAPERLESS_DBHOST = "postgres"
PAPERLESS_DBNAME = "paperless"
PAPERLESS_DBUSER = "paperless"
PAPERLESS_DBPASS = "${postgres_password}"
PAPERLESS_SECRET_KEY = "${secret_key}"
PAPERLESS_URL = "https://${domain}"
PAPERLESS_ALLOWED_HOSTS = "${domain}"
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${domain}"
PAPERLESS_ADMIN_USER = "${admin_user}"
PAPERLESS_ADMIN_PASSWORD = "${admin_password}"
PAPERLESS_ADMIN_MAIL = "${admin_email}"
PAPERLESS_OCR_LANGUAGE = "eng"
PAPERLESS_TIKA_ENABLED = "1"
PAPERLESS_TIKA_ENDPOINT = "http://tika:9998"
PAPERLESS_TIKA_GOTENBERG_ENDPOINT = "http://gotenberg:3000"
PAPERLESS_REDIS = "redis://redis:6379"
Example 4: Service with Config File Mount
[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
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 config
dokploy-environment-config: Environment variable patterns
dokploy-cloudflare-integration: R2 configuration
Invoked By
/dokploy-create command: Phase 3 (Generation) - Step 6 (Final)
Order in Workflow (Progressive Loading)
dokploy-compose-structure: Create compose file
dokploy-traefik-routing: Add routing
dokploy-health-patterns: Add health checks
dokploy-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