232 lines
8.4 KiB
Markdown
232 lines
8.4 KiB
Markdown
# 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)
|
|
- [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 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`.
|
|
|
|
## 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://github.com/maxvojtkov/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: maxvojtkov/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://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).
|