Files
pulumi-dokploy/sdk/dotnet/README.md
Max Vojtkov a44ebd4432
Some checks failed
build / build (push) Has been cancelled
release / plugin (push) Failing after 3m46s
release / sdks (push) Has been skipped
Resolve the plugin and SDKs from Gitea
PluginDownloadURL moves off github:// to a templated Gitea release URL.
Pulumi interpolates ${VERSION}, then appends
pulumi-resource-dokploy-v<version>-<os>-<arch>.tar.gz -- which is what
the GoReleaser archive template already produces. Schema, bridge
metadata and all four SDKs regenerated to carry it.

Releases publish to this instance's npm, PyPI, NuGet and Go registries
using the GITEA_TOKEN that Gitea injects, so no secrets need
configuring.

The Go SDK keeps its github.com module path, which is exactly why it
goes to Gitea's Go registry: pointing GOPROXY there is what makes that
path resolve at all. Verified locally by serving the module zip from a
file proxy and building a consumer against it -- note zip -D, without
which go get rejects the archive's directory entries.
2026-08-09 12:37:19 +03:00

276 lines
10 KiB
Markdown
Generated

# 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://gitea.coolify.vojtkov.dev/usr_unknown/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)
- [Deploying from CI](#deploying-from-ci)
- [Differences from the Terraform provider](#differences-from-the-terraform-provider)
- [Examples](#examples)
- [Development](#development)
- [Releasing](#releasing)
## Installing
The SDKs live in this Gitea instance's package registries, and the plugin
binary is resolved automatically from this repository's Gitea releases — the
download URL is baked into the schema, so `pulumi up` fetches it without any
configuration.
The SDKs do need one-time registry configuration, because none of these
package managers know about a private host by default.
**TypeScript / JavaScript**
```bash
npm config set @maxvojtkov:registry \
https://gitea.coolify.vojtkov.dev/api/packages/usr_unknown/npm/
npm install @maxvojtkov/pulumi-dokploy
```
**Python**
```bash
pip install pulumi_dokploy \
--index-url https://gitea.coolify.vojtkov.dev/api/packages/usr_unknown/pypi/simple
```
**.NET**
```bash
dotnet nuget add source \
https://gitea.coolify.vojtkov.dev/api/packages/usr_unknown/nuget/index.json \
--name gitea-dokploy
dotnet add package Maxvojtkov.Dokploy
```
**Go** — the module path stays `github.com/maxvojtkov/...` even though nothing
is hosted on GitHub, so point the proxy at Gitea and skip the public checksum
database for that path:
```bash
export GOPROXY=https://gitea.coolify.vojtkov.dev/api/packages/usr_unknown/go,direct
export GONOSUMDB='github.com/maxvojtkov/*'
go get github.com/maxvojtkov/pulumi-dokploy/sdk/go/dokploy
```
If the registries are private, add credentials the usual way for each tool —
an `_authToken` in `.npmrc`, `--extra-index-url` with basic auth for pip, and
`--username`/`--password` on the `dotnet nuget add source`.
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`.
## Deploying from CI
Like the Terraform provider, this one manages *configuration*, not *rollouts*.
Creating an `Application` writes its definition; it does not build or start
anything.
[`dokploy-deploy-action`](https://gitea.coolify.vojtkov.dev/usr_unknown/dokploy-deploy-action)
covers the other half on GitHub Actions and Gitea Actions: it triggers a
deployment, waits for the build, and fails the job when the deployment fails.
Export the application id from your stack and hand it over.
```ts
export const apiApplicationId = api.id;
```
```yaml
- uses: https://gitea.coolify.vojtkov.dev/usr_unknown/dokploy-deploy-action@v1
with:
host: ${{ secrets.DOKPLOY_HOST }}
api-key: ${{ secrets.DOKPLOY_API_KEY }}
application-id: ${{ steps.stack.outputs.apiApplicationId }}
docker-image: ghcr.io/acme/api:${{ github.sha }}
```
## 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://gitea.coolify.vojtkov.dev/usr_unknown/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.
The `replace` is load-bearing here, not just a convenience: the module path
says `github.com`, but the code lives on Gitea, and Go has no way to discover
that on its own. It can go away once the upstream provider is published to
Gitea's Go registry, at which point the module resolves through `GOPROXY`:
```bash
export GOPROXY=https://gitea.coolify.vojtkov.dev/api/packages/usr_unknown/go,direct
export GONOSUMDB='github.com/maxvojtkov/*'
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
```
GoReleaser publishes the plugin binaries to a Gitea release first — Pulumi
resolves the plugin from there, so it has to exist before anyone installs an
SDK — and then the four SDKs go to this instance's npm, PyPI, NuGet and Go
registries.
**No secrets to configure.** Every step authenticates with `secrets.GITEA_TOKEN`,
which Gitea injects into each run automatically.
Two things the workflow depends on:
- A registered `act_runner` with an `ubuntu-latest` label, and enough of a
toolchain for Go, Node, Python and .NET.
- The upstream `terraform-provider-dokploy` repository being readable by that
token, since the `replace` directive needs it checked out as a sibling.
## License
[MPL-2.0](LICENSE).