Cover what Dokploy v0.30 added
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:
@@ -51,6 +51,7 @@ resource "dokploy_domain" "api" {
|
||||
- [Deployments are not managed](#deployments-are-not-managed)
|
||||
- [Importing existing infrastructure](#importing-existing-infrastructure)
|
||||
- [Using this from Pulumi](#using-this-from-pulumi)
|
||||
- [Volumes that actually persist](#volumes-that-actually-persist)
|
||||
- [Known API quirks](#known-api-quirks)
|
||||
- [Development](#development)
|
||||
|
||||
@@ -70,7 +71,7 @@ endpoint that can serve the provider protocol `terraform init` speaks.
|
||||
### From a release
|
||||
|
||||
```bash
|
||||
VERSION=0.1.0
|
||||
VERSION=0.2.0
|
||||
OS_ARCH="$(go env GOOS)_$(go env GOARCH)"
|
||||
BASE=https://gitea.coolify.vojtkov.dev/usr_unknown/terraform-provider-dokploy/releases/download
|
||||
|
||||
@@ -92,7 +93,7 @@ make install
|
||||
```
|
||||
|
||||
That writes the binary to
|
||||
`~/.local/share/terraform/plugins/registry.terraform.io/maxvojtkov/dokploy/0.1.0/<os>_<arch>/`
|
||||
`~/.local/share/terraform/plugins/registry.terraform.io/maxvojtkov/dokploy/0.2.0/<os>_<arch>/`
|
||||
and prints the CLI configuration to add to `~/.terraformrc`:
|
||||
|
||||
```hcl
|
||||
@@ -114,7 +115,7 @@ terraform {
|
||||
required_providers {
|
||||
dokploy = {
|
||||
source = "maxvojtkov/dokploy"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +203,7 @@ Full reference documentation lives in [`docs/`](./docs).
|
||||
| [`dokploy_mariadb`](docs/resources/mariadb.md) | Managed MariaDB |
|
||||
| [`dokploy_mongo`](docs/resources/mongo.md) | Managed MongoDB |
|
||||
| [`dokploy_redis`](docs/resources/redis.md) | Managed Redis |
|
||||
| [`dokploy_libsql`](docs/resources/libsql.md) | Managed libSQL (`sqld`) |
|
||||
| [`dokploy_domain`](docs/resources/domain.md) | A hostname routed through Traefik |
|
||||
| [`dokploy_mount`](docs/resources/mount.md) | Volume, bind mount or config file |
|
||||
| [`dokploy_port`](docs/resources/port.md) | A port published straight onto the host |
|
||||
@@ -211,6 +213,11 @@ Full reference documentation lives in [`docs/`](./docs).
|
||||
| [`dokploy_ssh_key`](docs/resources/ssh_key.md) | SSH key pair for private Git and remote servers |
|
||||
| [`dokploy_certificate`](docs/resources/certificate.md) | An uploaded TLS certificate |
|
||||
| [`dokploy_destination`](docs/resources/destination.md) | S3-compatible backup destination |
|
||||
| [`dokploy_network`](docs/resources/network.md) | A Docker network services attach to |
|
||||
| [`dokploy_schedule`](docs/resources/schedule.md) | A cron job run in a container or on a server |
|
||||
| [`dokploy_volume_backup`](docs/resources/volume_backup.md) | A scheduled backup of a Docker volume |
|
||||
| [`dokploy_dns_provider`](docs/resources/dns_provider.md) | Cloudflare or Route53, for automatic DNS records |
|
||||
| [`dokploy_vault_provider`](docs/resources/vault_provider.md) | An external secret manager for deploy-time env |
|
||||
|
||||
### Data sources
|
||||
|
||||
@@ -411,6 +418,56 @@ p := tfshim.NewProvider("0.1.0") // a plugin-framework provider.Provider
|
||||
|
||||
Keep `shim.NewProvider` stable — it is this repository's only public Go API.
|
||||
|
||||
## Volumes that actually persist
|
||||
|
||||
A `dokploy_mount` with `type = "volume"` **must** set `volume_name`:
|
||||
|
||||
```hcl
|
||||
resource "dokploy_mount" "data" {
|
||||
type = "volume"
|
||||
volume_name = "shop-uploads" # required — see below
|
||||
mount_path = "/app/uploads"
|
||||
service_type = "application"
|
||||
service_id = dokploy_application.api.id
|
||||
}
|
||||
```
|
||||
|
||||
Dokploy turns a mount into a Docker mount with
|
||||
`{Source: volumeName || "", Target: mountPath}`. When `volumeName` is null the
|
||||
source is the empty string, and Docker reads an empty source as an *anonymous*
|
||||
volume — a new one on every single deploy, with the previous one left orphaned
|
||||
on disk. Nothing errors: the service starts, the path is writable, and the data
|
||||
is gone again after the next deployment while disk usage climbs.
|
||||
|
||||
Dokploy's API accepts that mount without complaint, so this provider rejects it
|
||||
at plan time instead:
|
||||
|
||||
```
|
||||
Error: Missing volume_name
|
||||
|
||||
with dokploy_mount.data,
|
||||
on main.tf line 1, in resource "dokploy_mount" "data":
|
||||
|
||||
`volume_name` must be set to a non-empty value when `type` is `volume`.
|
||||
|
||||
Dokploy passes an unset `volume_name` to Docker as an empty source, which
|
||||
creates a new anonymous volume on every deploy. The data written to the
|
||||
previous volume is orphaned and never reused, so the mount silently does not
|
||||
persist anything.
|
||||
```
|
||||
|
||||
The same check covers `type = "bind"` without `host_path` and `type = "file"`
|
||||
without `file_path`, and it rejects a field set against the wrong `type` —
|
||||
`volume_name` on a bind mount, say — which Dokploy would otherwise ignore.
|
||||
|
||||
**If you already have such a mount**, adding `volume_name` and redeploying
|
||||
gives you a persistent volume from that point on. The contents of the current
|
||||
anonymous volume are not migrated; copy the data off the host first if you
|
||||
need it.
|
||||
|
||||
Pair a named volume with [`dokploy_volume_backup`](docs/resources/volume_backup.md)
|
||||
to get it off the host on a schedule.
|
||||
|
||||
## Known API quirks
|
||||
|
||||
These are properties of the Dokploy API that the provider works around; they
|
||||
@@ -434,6 +491,23 @@ explain behaviour that would otherwise look surprising.
|
||||
`environment.create`) reject it. The provider tracks this per field.
|
||||
- **Basic auth passwords are never returned.** `dokploy_security.password`
|
||||
keeps whatever you configured; drift in that one field cannot be detected.
|
||||
DNS and vault provider credentials behave the same way: Dokploy masks
|
||||
`config` on read, so `dokploy_dns_provider.config` and
|
||||
`dokploy_vault_provider.config` keep the configured value and are not
|
||||
checked for drift.
|
||||
- **`libsql.create` is the strictest endpoint in the API.** It requires eleven
|
||||
keys to be *present* — several only meaningfully `null` — declines to
|
||||
generate a service name the way every other engine does, and then returns
|
||||
`true` instead of the created row. The provider fills in the nulls, derives
|
||||
an `app_name` from `name`, and finds the new ID by diffing the environment's
|
||||
libSQL list, so `dokploy_libsql` behaves like the other databases.
|
||||
- **A `volume` mount with no name is silently anonymous.** Covered in
|
||||
[Volumes that actually persist](#volumes-that-actually-persist); the provider
|
||||
rejects it at plan time.
|
||||
- **Docker networks cannot be updated.** Dokploy exposes no `network.update`,
|
||||
matching Docker itself, so every attribute of `dokploy_network` forces
|
||||
replacement. Replacing a network detaches the services using it until they
|
||||
are redeployed.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
Reference in New Issue
Block a user