Self-hosted, commitless-deploy PaaS. One HCL file. One
voodu apply. No git push, no bare repo, no plugin sprawl.
Voodu is a Heroku-shaped, Kubernetes-honest deploy tool you run on your own boxes. HCL manifests describe the running system — apps, ingress with TLS, stateful services with backup. voodu apply builds, ships, routes, swaps. The CLI streams the build context straight to the server over SSH — no commit required, no push, no bare repo.
Full documentation, examples, and architecture at voodu.clowk.in/docs.
curl -fsSL voodu.clowk.in/install | bashAuto-detects mode by OS — server on Linux (CLI + voodu-controller + Docker + systemd unit + default plugins), client on macOS (CLI only, for laptops that deploy to remote servers). Force explicitly:
curl -fsSL voodu.clowk.in/install | bash -s -- --client
curl -fsSL voodu.clowk.in/install | bash -s -- --serverEnv knobs:
| Var | Default | What it does |
|---|---|---|
VERSION |
latest release | pin a tag, e.g. v0.9.6 |
VOODU_ROOT |
/opt/voodu |
server state directory |
VOODU_HTTP_ADDR |
127.0.0.1:8686 |
controller HTTP bind |
VOODU_INSTALL_REPO |
thadeu/clowk-voodu |
source repo (for forks) |
SKIP_DOCKER=1 |
— | skip Docker install (server mode only) |
SKIP_PLUGINS=1 |
— | skip default plugin install |
Re-running the installer upgrades both binaries and restarts the controller — idempotent.
# voodu.hcl
app "prod" "api" {
image = "ghcr.io/me/api:v1.2"
replicas = 2
ports = ["8080"]
env = {
PORT = "8080"
}
host = "api.example.com"
tls {
email = "ops@example.com"
}
}voodu remote add voodu ubuntu@your-host # default remote (alias `voodu`)
voodu apply -f voodu.hclThat's it. TLS auto-provisions via Let's Encrypt, replicas roll in behind the readiness probe, traffic reaches api.example.com. For staging / prod, add more remotes:
voodu remote add staging ubuntu@staging.host
voodu remote add prod ubuntu@prod.host
voodu apply -f voodu.hcl -r staging
voodu apply -f voodu.hcl -r prodFull first-deploy walkthrough: voodu.clowk.in/docs/getting-started/first-deploy.
- Six verbs cover ~95% of day-to-day —
apply,diff,logs,config,remote,plugins. - HCL manifests —
deployment,app,statefulset,ingress,job,cronjob,asset,registry, plus macros forpostgresandredis. - Probes drive ingress — declare a
readinessprobe, Caddy gates upstream membership on it automatically. - Per-pod volumes survive prune — statefulset data is yours until
docker volume rm. - Autoscale — CPU-based hysteresis with asymmetric cooldown.
- Multi-target
on_deploy— Slack + PagerDuty + Datadog in parallel goroutines, independent retry budgets. - Build cache shared — content-addressed tarball hashes; identical source skips the rebuild.
vd diff --detailed-exitcode— terraform-style CI exit codes (0 = no change, 2 = changes pending).- Embedded etcd — single binary, no external dependencies, no operator sprawl.
Full manifest reference: voodu.clowk.in/docs/manifests/overview.
| Repo | Purpose |
|---|---|
thadeu/voodu-caddy |
Ingress — Caddy Admin API, ACME, on-demand wildcard TLS |
thadeu/voodu-postgres |
Postgres — streaming replication, pg_promote, backups with retention |
thadeu/voodu-redis |
Redis — single-instance or sentinel HA |
thadeu/voodu-mongo |
MongoDB |
Install one:
voodu plugins:install thadeu/voodu-postgresDefault install seeds voodu-caddy automatically so a fresh box can serve app blocks immediately.
Production-grade examples in examples/:
fsw-esl/— full telephony stack (redis + rabbitmq + 5 Go services) translated from docker-compose. Per-service file split for independent deploys, multi-targeton_deploy, autoscale tier.stack/— postgres + redis + asset + app with TLS, the canonical "real app" shape.on_deploy/— Slack, PagerDuty, Telegram, multi-target fan-out webhooks.probes/— kubelet-style liveness / readiness / startup on HTTP / TCP / exec.autoscale/— worker + HTTP tier scaling profiles.build/—build {}patterns: auto-detect runtime, custom Dockerfile, Go monorepo, statefulset build-mode.statefulset/— postgres cluster, redis with persistent volumes.multi-env/— one manifest, many remotes (-r staging/-r prod).shared-scope/— multiple repos applying into the same scope with--no-prune.
your laptop server
─────────── ──────
voodu apply -f voodu.hcl ──ssh──▶ voodu-controller
│ │
│ (build-mode: tarball) └─ reconcile → docker
└─ tar -czf - ──ssh──▶ voodu receive-pack
└─ extract → docker build → tag → swap → run
Single binary per host (voodu-controller), embedded etcd, in-process reconciler, plugin subprocesses for macros and CLI verbs. HTTP :8686 on the controller; CLI talks to it via SSH-forwarded local port.
Deep dive: voodu.clowk.in/docs/architecture/overview.
make tidy # download deps
make build # build voodu + voodu-controller into bin/
make vet # go vet
make test # go test -race -coverprofile=coverage.out
./bin/voodu --versionReleases are cut by pushing a v* tag — GoReleaser builds cross-platform binaries and publishes them to the GitHub release. The docs site rebuilds automatically on release via the docs workflow, so voodu.clowk.in/install and the landing-page version pill stay in sync with the latest binary.
MIT — see LICENSE.