voodu apply, no git pushSelf-hosted PaaS.
Commitless deploys.
Voodu is a Heroku-shaped, Kubernetes-honest deploy tool you run on your own boxes. One HCL file. One voodu apply. No git push, no bare repo, no plugin sprawl — apps, ingress with TLS, and stateful services that actually back themselves up.
One file describes the running system.
HCL out-of-the-box. No YAML to coerce, no Compose tricks, no chart-of-charts. Apps, ingress, and stateful services share the same shape — and the same blast radius.
// Ship a web app with TLS + 3 replicas behind a load balancer.
app "myapp" "web" {
image = "ghcr.io/myorg/myapp:latest"
replicas = 3
env = {
PORT = "8080"
NODE_ENV = "production"
}
health_check = "/healthz"
host = "myapp.example.com"
tls {
email = "ops@example.com"
}
}
// HA Redis: primary + sentinel cluster, declared, not orchestrated.
redis "clowk-lp" "redis" {
replicas = 3
}
redis "clowk-lp" "redis-ha" {
sentinel {
monitor = "clowk-lp/redis"
}
}scope + name, every kind
Every resource is keyed by (scope, name). Scope groups apps, envs or teams; name is unique inside it. The same key flows through diff, apply, and prune.
TLS, health, ingress — no plugins
Add tls{} and Voodu cuts a Let's Encrypt cert via Caddy. Add host and routing reconciles automatically. No Helm, no sidecars, no YAML blast radius.
Postgres, Mongo, Redis declared like apps
HA Redis with a sentinel cluster is six lines. Postgres and Mongo plugins ship backup, replicas, and test-restore — the parts every PaaS leaves to you.
No accidental deletions
apply only creates and updates. Resources missing from the file stay put. Want to clean up? --prune is the explicit opt-in, scoped per (scope, kind)so siblings of other types aren't touched.
Laptop talks. Server reconciles.
The CLI streams your build context over SSH. The controller diffs it against embedded etcd, builds, swaps, and reroutes. It's k8s-shaped reconciliation without the k8s-shaped operations bill.
your laptop your server ─────────── ─────────── $ voodu apply -f voodu.hcl ──ssh──▶ voodu-controller │ │ │ └─ reconcile ingress / services (etcd) │ (build mode only: stream tarball) └─ tar -czf - <path> ──ssh──▶ voodu receive-pack └─ extract → build image → swap `current` symlink → run post_deploy hooks → recreate container
Write the manifest
One HCL file, or many. Apps, ingresses, databases, jobs — pick what you need, ignore the rest.
# voodu.hcl app "prod" "api" { ... } ingress "prod" "api" { ... }
See the plan first
voodu diff dry-runs the apply: what's new, changed, pruned. Wire --detailed-exitcode in CI to gate deploys.
$ voodu diff -f voodu.hcl
~ deployment/prod/api
~ replicas 1 → 3
+ redis/clowk-lp/redis-haShip over SSH
Same flags, no surprises. Tarball is content-addressed — identical trees skip the rebuild and just repoint current.
$ voodu apply -f voodu.hcl -r prod-1
✓ apply complete in 11.8s
✓ 3/3 healthyA small, k8s-shaped command surface.
Six verbs cover ~95% of day-to-day. Everything else is a plugin discovered from /opt/voodu/plugins.
$voodu remote setup prod-1 ubuntu@hostSSH preflight + install + server-mode setup. Idempotent.
$voodu apps create prodSeeds /opt/voodu/apps/prod with a fresh .env.
$voodu apply -f voodu.hcl -r prod-1Streams context over SSH, reconciles, swaps containers.
$voodu diff -f voodu.hcl --detailed-exitcodePlan-style output. Exit 2 means changes pending.
$voodu config set DATABASE_URL=… -a prodOut-of-band secrets. Always wins over manifest env blocks.
$voodu plugins:install thadeu/voodu-postgresDrops a binary into /opt/voodu/plugins. Voodu wires it up.
Built on boring, well-loved parts.
Voodu is opinionated where it counts and pluggable where you'd want it to be. Postgres, Mongo, Redis, ingress — independent binaries, not a rewritten universe.
Go controller
Single static binary, embedded etcd, HTTP API on 127.0.0.1:8686.
Caddy ingress
Replaces NGINX. Caddy Admin API, ACME, on-demand wildcard TLS.
Docker builds
Bring a Dockerfile or let voodu auto-detect Go, Ruby, Rails, Python, Node.
SSH transport
Tarball over SSH. No daemons listening on the public internet.
voodu-postgres
Postgres with backup, replica and test-restore. Declared like an app.
voodu-mongo
MongoDB service with the same reliability primitives.
voodu-caddy
Reference plugin. Read it to write your own.
Build your own
Independent binaries discovered from /opt/voodu/plugins. Install via GitHub repo.
Questions devs actually ask.
Why HCL and not YAML?+
kind/scope/name. Voodu is HCL-only — no YAML coercion, no indentation traps.How is this different from Dokku, Coolify, CapRover?+
diff shows the plan, apply reconciles. Stateful services are first-class, not bolted on as plugins-of-plugins.Is it really commitless?+
voodu apply tars whatever directory you're in and streams it over SSH. No bare repo, no git push, no commit required. Edit, save, apply.What about K8s?+
Does it scale beyond one host?+
voodu apply -f voodu.hcl -r $r. Same manifest, different SSH targets. The controller is per-host and stateless about its peers — keep it boring.How do secrets work?+
voodu config set stores env vars per-app, out-of-band from the manifest. config:set always wins over envblocks, so a runaway apply can't reset a production secret.