Bridge terraform-provider-dokploy into a Pulumi provider

18 resources and 5 data sources mapped into the dokploy:index module, with
SDKs generated for TypeScript, Python, Go and .NET.
This commit is contained in:
2026-08-08 15:28:16 +03:00
commit bb3c15135b
175 changed files with 61774 additions and 0 deletions

206
README.md Normal file
View File

@@ -0,0 +1,206 @@
# pulumi-dokploy
A Pulumi provider for [Dokploy](https://dokploy.com): projects, environments,
applications, Compose stacks, managed databases, domains, mounts, ports,
redirects, basic auth, registries, SSH keys, certificates and backup
destinations.
This is a *bridged* provider. All of the behaviour lives in
[`terraform-provider-dokploy`](https://github.com/maxvojtkov/terraform-provider-dokploy);
[`pulumi-terraform-bridge`](https://github.com/pulumi/pulumi-terraform-bridge)
turns it into a Pulumi package with typed SDKs for TypeScript, Python, Go and
.NET. The two providers stay in lockstep — a resource added upstream shows up
here after a `make tfgen`.
```ts
import * as dokploy from "@maxvojtkov/pulumi-dokploy";
const shop = new dokploy.Project("shop", { name: "shop" });
const db = new dokploy.Postgres("db", {
name: "shop-db",
environmentId: shop.defaultEnvironmentId,
dockerImage: "postgres:16-alpine",
databaseName: "shop",
databaseUser: "shop",
databasePassword: dbPassword,
});
const api = new dokploy.Application("api", {
name: "api",
environmentId: shop.defaultEnvironmentId,
sourceType: "docker",
dockerImage: "ghcr.io/acme/api:1.4.0",
env: pulumi.interpolate`DATABASE_URL=postgresql://shop:${dbPassword}@${db.appName}:5432/shop`,
});
new dokploy.Domain("api", {
applicationId: api.id,
domainType: "application",
host: "api.example.com",
port: 3000,
https: true,
certificateType: "letsencrypt",
});
```
## Contents
- [Installing](#installing)
- [Configuration](#configuration)
- [Resources and data sources](#resources-and-data-sources)
- [Differences from the Terraform provider](#differences-from-the-terraform-provider)
- [Examples](#examples)
- [Development](#development)
- [Releasing](#releasing)
## Installing
The SDKs are published per language; the plugin binary is resolved
automatically from this repository's GitHub releases.
```bash
# TypeScript / JavaScript
npm install @maxvojtkov/pulumi-dokploy
# Python
pip install pulumi_dokploy
# Go
go get github.com/maxvojtkov/pulumi-dokploy/sdk/go/dokploy
# .NET
dotnet add package Maxvojtkov.Dokploy
```
Before the first release, build and install it locally instead:
```bash
make install VERSION=0.1.0
```
That drops `pulumi-resource-dokploy` into the local plugin cache, so
`pulumi up` finds it without a network fetch.
### Do I need the static SDK?
Not necessarily. Pulumi can consume the Terraform provider directly, with no
build step and no published SDK:
```bash
pulumi package add terraform-provider maxvojtkov/dokploy
```
That generates a local SDK on the spot and is the fastest way to try things.
Use this repository when you want a *versioned, published* package — stable
tokens across releases, real package-manager installs, and SDKs your teammates
can depend on without a codegen step.
## Configuration
| Setting | Environment variable | Required | Description |
| ---------------------- | ------------------------- | -------- | --------------------------------------------------------------------------- |
| `dokploy:host` | `DOKPLOY_HOST` | yes | Base URL of the instance, e.g. `https://dokploy.example.com`. Trailing `/api` optional. |
| `dokploy:apiKey` | `DOKPLOY_API_KEY` | yes | Token from *Settings → Profile → API/CLI*. Always treated as a secret. |
| `dokploy:timeoutSeconds` | `DOKPLOY_TIMEOUT_SECONDS` | no | Per-request timeout. Defaults to `60`. |
| `dokploy:insecureSkipVerify` | — | no | Skip TLS verification. Only for self-signed certificates. |
```bash
pulumi config set dokploy:host https://dokploy.example.com
pulumi config set --secret dokploy:apiKey "$DOKPLOY_API_KEY"
```
## Resources and data sources
| Group | Resources |
| ------------ | ------------------------------------------------------------------------- |
| Structure | `Project`, `Environment` |
| Services | `Application`, `Compose` |
| Databases | `Postgres`, `MySql`, `MariaDb`, `Mongo`, `Redis` |
| Networking | `Domain`, `Mount`, `Port`, `Redirect`, `Security` |
| Account | `Registry`, `SshKey`, `Certificate`, `Destination` |
Data sources: `getProject`, `getProjects`, `getEnvironment`, `getApplication`,
`getServers`.
## Differences from the Terraform provider
Everything is a mechanical translation of the Terraform provider, with three
Pulumi conventions applied on top:
- **Attribute names are camelCase.** `environment_id``environmentId`,
`default_environment_id``defaultEnvironmentId`, and so on.
- **`name` is auto-generated when you omit it.** Pulumi appends a random
suffix to the logical resource name, the same way the AWS provider does. Pass
`name` explicitly whenever the Dokploy-side name matters to you.
- **The `web-service` Terraform module has no direct equivalent.** Write it as
a [ComponentResource](https://www.pulumi.com/docs/concepts/resources/components/)
instead — see [`examples/typescript/webService.ts`](examples/typescript/webService.ts),
which is a port of that module.
The [known API quirks](https://github.com/maxvojtkov/terraform-provider-dokploy#known-api-quirks)
documented upstream apply here unchanged, because it is the same code doing the
work.
## Examples
- [`examples/typescript`](examples/typescript) — a full environment: project,
staging environment, Postgres, Redis, a GitHub-built web service behind a
domain, a basic-auth-protected internal tool, and a Compose stack.
- [`examples/python`](examples/python) — a small project, database and app.
## Development
Requirements: Go 1.25+, Node 20+, Python 3.9+, .NET 8+, and `pulumi`.
```bash
make tfgen # regenerate schema.json and bridge-metadata.json
make provider # build the plugin binary into bin/
make build_sdks # regenerate all four SDKs
make install # install the plugin into the local Pulumi plugin cache
make lint test
```
`provider/resources.go` is the whole mapping layer: Terraform type names to
Pulumi tokens, and Terraform provider configuration to Pulumi configuration.
Adding an upstream resource means adding one line there and re-running
`make tfgen build_sdks`.
### The upstream dependency
`provider/go.mod` currently carries:
```
replace github.com/maxvojtkov/terraform-provider-dokploy => ../../dokploy-teraform
```
so the two repositories can be developed side by side. CI reproduces that
layout by checking the upstream provider out as a sibling directory. Once
`terraform-provider-dokploy` is tagged on GitHub, drop the `replace` and pin a
real version instead:
```bash
cd provider && go mod edit -dropreplace github.com/maxvojtkov/terraform-provider-dokploy \
&& go get github.com/maxvojtkov/terraform-provider-dokploy@v0.1.0
```
The upstream provider exposes itself through its `shim` package
(`shim.NewProvider(version)`), because `internal/provider` is not importable
from outside that module.
## Releasing
Tag the repository and the `release` workflow does the rest:
```bash
git tag v0.1.0 && git push origin v0.1.0
```
It publishes plugin binaries to a GitHub release via GoReleaser, pushes the
npm / PyPI / NuGet packages, and commits and tags the Go SDK as `sdk/v0.1.0`.
The workflow needs three repository secrets: `NPM_TOKEN`, `PYPI_API_TOKEN` and
`NUGET_PUBLISH_KEY`.
## License
[MPL-2.0](LICENSE).