Cover what Dokploy v0.30 added
build / build (push) Successful in 3m56s
release / release (push) Successful in 15m2s

Six new resources, all backed by endpoints that did not exist before v0.30.0
and verified end-to-end against a live v0.30.2 instance:

  dokploy_network         Docker networks, now first-class. Services attach
                          through network_ids, which is what deprecates
                          Compose's isolated_deployment upstream.
  dokploy_dns_provider    Cloudflare or Route53, so adding a domain creates
                          its DNS record.
  dokploy_vault_provider  Env values resolved from HashiCorp Vault, Infisical,
                          AWS, Doppler, Azure or Scaleway at deploy time, so
                          the secret never lands in Dokploy or in state.
  dokploy_schedule        Cron jobs in a container, a stack, or on a server.
  dokploy_volume_backup   Scheduled backups of a named volume — the companion
                          to a mount that persists.
  dokploy_libsql          The sixth managed database engine.

libsql.create is the strictest endpoint in the API: eleven keys required to
be present, several only meaningfully null, no generated service name, and it
returns `true` rather than the row. CreateDefaults and ListIDs absorb all
three so the resource behaves like every other database.

Also filled the gaps a field-by-field diff against the live schema turned up:
domain gains `enabled` (the v0.30.0 park-a-domain toggle), compose gains
create_env_file, icon and service_networks, application gains icon and
preview_require_collaborator_permissions, and mounts accept libsql.

DNS and vault credentials are masked by Dokploy on read, so `config` is
tagged noread and keeps the configured value, as the basic-auth password
already does.
This commit is contained in:
max-voitcov
2026-08-26 00:40:27 +03:00
parent 3ddce62647
commit 2d1caf6e73
23 changed files with 1297 additions and 12 deletions
+153
View File
@@ -0,0 +1,153 @@
# Features introduced in Dokploy v0.30.0: Docker networks, vault-backed
# environment variables, scheduled jobs, and a volume that actually persists.
terraform {
required_providers {
dokploy = {
source = "maxvojtkov/dokploy"
version = "~> 0.2.0"
}
}
}
provider "dokploy" {
# host and api_key come from DOKPLOY_HOST and DOKPLOY_API_KEY
}
variable "vault_token" {
type = string
sensitive = true
}
resource "dokploy_project" "shop" {
name = "shop"
description = "Storefront and its backing services"
}
# --------------------------------------------------------------- Networking
# A private overlay network. Only the services attached to it can reach each
# other over it — the database never becomes reachable from unrelated
# services that merely share the default dokploy-network.
resource "dokploy_network" "backend" {
name = "shop-backend"
driver = "overlay"
attachable = true
internal = false
}
# ------------------------------------------------------------------ Secrets
# Environment values are resolved from Vault when the deployment runs, so
# rotating a secret takes effect on the next deploy with no Terraform change
# and no secret in Terraform state.
resource "dokploy_vault_provider" "prod" {
name = "production-vault"
config = jsonencode({
providerType = "hashicorp"
url = "https://vault.example.com"
token = var.vault_token
mount = "secret"
})
assignments = jsonencode([])
}
# ---------------------------------------------------------------- Services
resource "dokploy_postgres" "db" {
name = "shop-db"
environment_id = dokploy_project.shop.default_environment_id
docker_image = "postgres:16-alpine"
database_name = "shop"
database_user = "shop"
database_password = "set-me-from-a-variable"
network_ids = [dokploy_network.backend.id]
}
resource "dokploy_application" "api" {
name = "api"
environment_id = dokploy_project.shop.default_environment_id
source_type = "docker"
docker_image = "ghcr.io/acme/api:1.4.0"
network_ids = [dokploy_network.backend.id]
# Resolved from the vault provider above at deploy time.
env = <<-EOT
DATABASE_URL=postgresql://shop:$${{vault.production.db_password}}@${dokploy_postgres.db.app_name}:5432/shop
STRIPE_KEY=$${{vault.production.stripe_key}}
EOT
}
# -------------------------------------------------------- Persistent volume
# volume_name is what makes this persist. Without it Dokploy hands Docker an
# empty source and every deploy gets a fresh anonymous volume — the provider
# rejects that at plan time.
resource "dokploy_mount" "uploads" {
type = "volume"
volume_name = "shop-uploads"
mount_path = "/app/uploads"
service_type = "application"
service_id = dokploy_application.api.id
}
resource "dokploy_destination" "backups" {
name = "s3-backups"
provider_name = "s3"
access_key = "set-me"
secret_access_key = "set-me"
bucket = "shop-backups"
region = "eu-central-1"
endpoint = "https://s3.eu-central-1.amazonaws.com"
}
# The named volume is only durable if it also leaves the host.
resource "dokploy_volume_backup" "uploads" {
name = "uploads-nightly"
volume_name = dokploy_mount.uploads.volume_name
prefix = "shop/uploads/"
cron_expression = "0 4 * * *"
destination_id = dokploy_destination.backups.id
service_type = "application"
application_id = dokploy_application.api.id
keep_latest_count = 14
}
# ---------------------------------------------------------------- Schedules
resource "dokploy_schedule" "prune_sessions" {
name = "prune-sessions"
description = "Drop expired sessions every night"
schedule_type = "application"
application_id = dokploy_application.api.id
cron_expression = "0 2 * * *"
command = "node scripts/prune-sessions.js"
timezone = "Europe/Berlin"
}
# --------------------------------------------------------------------- DNS
resource "dokploy_dns_provider" "cloudflare" {
name = "cloudflare"
config = jsonencode({
providerType = "cloudflare"
apiToken = "set-me-from-a-variable"
})
}
resource "dokploy_domain" "api" {
application_id = dokploy_application.api.id
host = "api.example.com"
port = 3000
https = true
certificate_type = "letsencrypt"
# A domain can be parked without losing its configuration.
enabled = true
}