Plugin-framework provider covering projects, environments, applications, Compose stacks, managed databases, domains, mounts, ports, redirects, basic auth, registries, SSH keys, certificates and backup destinations, over Dokploy's tRPC-over-REST API. The shim package exposes the provider to other Go modules, which is how pulumi-dokploy bridges it.
201 lines
4.7 KiB
HCL
201 lines
4.7 KiB
HCL
# A complete Dokploy environment: a project, a staging environment, a public
|
|
# web service with a database and a cache behind it, and a Compose stack.
|
|
#
|
|
# export DOKPLOY_HOST=https://dokploy.example.com
|
|
# export DOKPLOY_API_KEY=...
|
|
# terraform init && terraform apply
|
|
|
|
terraform {
|
|
required_version = ">= 1.5"
|
|
required_providers {
|
|
dokploy = {
|
|
source = "maxvojtkov/dokploy"
|
|
version = ">= 0.1"
|
|
}
|
|
random = {
|
|
source = "hashicorp/random"
|
|
version = ">= 3.6"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "dokploy" {
|
|
# host and api_key are read from DOKPLOY_HOST and DOKPLOY_API_KEY.
|
|
}
|
|
|
|
# ------------------------------------------------------------------- structure
|
|
|
|
resource "dokploy_project" "shop" {
|
|
name = "shop"
|
|
description = "Storefront and its backing services"
|
|
|
|
# Shared by every service in the project.
|
|
env = "TZ=Europe/Bucharest"
|
|
}
|
|
|
|
# Dokploy creates a default "production" environment with the project; add a
|
|
# second one for staging.
|
|
resource "dokploy_environment" "staging" {
|
|
name = "staging"
|
|
description = "Pre-production"
|
|
project_id = dokploy_project.shop.id
|
|
|
|
env = "LOG_LEVEL=debug"
|
|
}
|
|
|
|
# -------------------------------------------------------------------- secrets
|
|
|
|
resource "random_password" "postgres" {
|
|
length = 32
|
|
special = false
|
|
}
|
|
|
|
resource "random_password" "redis" {
|
|
length = 32
|
|
special = false
|
|
}
|
|
|
|
# ------------------------------------------------------------------- datastores
|
|
|
|
resource "dokploy_postgres" "shop" {
|
|
name = "shop-db"
|
|
environment_id = dokploy_project.shop.default_environment_id
|
|
|
|
docker_image = "postgres:16-alpine"
|
|
database_name = "shop"
|
|
database_user = "shop"
|
|
database_password = random_password.postgres.result
|
|
|
|
memory_limit = "1g"
|
|
cpu_limit = "1"
|
|
memory_reservation = "256m"
|
|
}
|
|
|
|
resource "dokploy_redis" "sessions" {
|
|
name = "shop-cache"
|
|
environment_id = dokploy_project.shop.default_environment_id
|
|
|
|
docker_image = "redis:7-alpine"
|
|
database_password = random_password.redis.result
|
|
|
|
memory_limit = "256m"
|
|
}
|
|
|
|
# --------------------------------------------------------------- the web service
|
|
|
|
module "storefront" {
|
|
source = "../../modules/web-service"
|
|
|
|
name = "storefront"
|
|
description = "Public storefront"
|
|
environment_id = dokploy_project.shop.default_environment_id
|
|
|
|
service_source = {
|
|
type = "github"
|
|
github_id = var.github_provider_id
|
|
owner = "acme"
|
|
repository = "storefront"
|
|
branch = "main"
|
|
}
|
|
|
|
build_type = "nixpacks"
|
|
auto_deploy = true
|
|
replicas = 2
|
|
|
|
# Dokploy resolves service names on the shared Docker network, so the
|
|
# database is reachable by its generated app_name.
|
|
env = join("\n", [
|
|
"DATABASE_URL=postgresql://shop:${random_password.postgres.result}@${dokploy_postgres.shop.app_name}:5432/shop",
|
|
"REDIS_URL=redis://:${random_password.redis.result}@${dokploy_redis.sessions.app_name}:6379",
|
|
"NODE_ENV=production",
|
|
])
|
|
|
|
resources = {
|
|
memory_limit = "1g"
|
|
cpu_limit = "1"
|
|
}
|
|
|
|
domains = [
|
|
{
|
|
host = "shop.example.com"
|
|
port = 3000
|
|
},
|
|
]
|
|
|
|
redirects = [
|
|
{
|
|
regex = "^https://www\\.shop\\.example\\.com/(.*)"
|
|
replacement = "https://shop.example.com/$${1}"
|
|
permanent = true
|
|
},
|
|
]
|
|
|
|
mounts = [
|
|
{
|
|
mount_path = "/app/uploads"
|
|
type = "volume"
|
|
volume_name = "storefront-uploads"
|
|
},
|
|
]
|
|
}
|
|
|
|
# -------------------------------------------- an internal tool behind basic auth
|
|
|
|
module "admin" {
|
|
source = "../../modules/web-service"
|
|
|
|
name = "admin"
|
|
environment_id = dokploy_environment.staging.id
|
|
|
|
service_source = {
|
|
type = "docker"
|
|
image = "traefik/whoami:latest"
|
|
}
|
|
|
|
domains = [
|
|
{
|
|
host = "admin.staging.example.com"
|
|
port = 80
|
|
},
|
|
]
|
|
|
|
basic_auth = {
|
|
username = "ops"
|
|
password = var.admin_password
|
|
}
|
|
}
|
|
|
|
# --------------------------------------------------------------- a compose stack
|
|
|
|
resource "dokploy_compose" "observability" {
|
|
name = "observability"
|
|
environment_id = dokploy_project.shop.default_environment_id
|
|
compose_type = "docker-compose"
|
|
source_type = "raw"
|
|
|
|
# Preserve volumes if this stack is ever destroyed.
|
|
delete_volumes = false
|
|
|
|
compose_file = <<-YAML
|
|
services:
|
|
uptime:
|
|
image: louislam/uptime-kuma:1
|
|
volumes:
|
|
- uptime-data:/app/data
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
uptime-data:
|
|
YAML
|
|
}
|
|
|
|
resource "dokploy_domain" "observability" {
|
|
compose_id = dokploy_compose.observability.id
|
|
domain_type = "compose"
|
|
service_name = "uptime"
|
|
host = "status.example.com"
|
|
port = 3001
|
|
https = true
|
|
certificate_type = "letsencrypt"
|
|
}
|