wihan/dev

writing / post

Creating a Dokploy Terraform provider

2026-08-22go · terraform · dokploy2 minmarkdown

I wanted terraform apply to be the only deploy button on my personal infrastructure. Dokploy had an API and no living provider, so now there is vanillauys/dokploy: written in Go on the terraform-plugin-framework, at v0.10.0 after ten minor releases.

The shape is the standard one. A thin API client package that knows nothing about Terraform, and a resource layer that maps schema to client calls:

func (r *ProjectResource) Create(ctx context.Context,
	req resource.CreateRequest, resp *resource.CreateResponse) {
	var plan ProjectModel
	resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)

	project, err := r.client.CreateProject(ctx, plan.Name.ValueString())
	// map the response back into state, nothing clever
}

The framework does the heavy lifting: plan diffs, state upgrades, unknown-value propagation. Your job is to be honest about the API you are wrapping.

Test against the real thing

The acceptance suite runs against an actual Dokploy instance in CI on every pull request - a container on the runner’s own Docker, no docker-in-docker. Mocks would have passed builds that failed against the real server, because a young API has opinions the docs do not mention. Every one of these came out of a failing acceptance test, not a bug report:

Releasing is a checklist, not a ceremony

The Terraform registry wants tagged releases with signed artifacts and a manifest; goreleaser produces the matrix and the registry ingests each tag within minutes. After that, releasing often is cheap - six of the ten minors shipped in single-day bursts as the resource surface grew.

v1.0 is deliberately not tagged yet. The rule: the provider must survive one Dokploy minor upgrade without breaking changes first. A 1.0 is a promise about the future, and I want at least one data point before making it.