project
caddyku
CLI that manages one shared Caddy reverse proxy for all the Docker projects on a VPS.
why this exists
I run several projects on one small VPS — this site, a staging environment for an exam platform, whatever I’m experimenting with that month. Every one of them is a Docker Compose project that needs a domain and HTTPS. The usual answers are either heavy (a separate nginx + certbot setup per app) or fragile: one shared reverse-proxy config you SSH into and hand-edit, where a single typo takes down every site on the box.
Caddy already solves the hard parts — automatic HTTPS via Let’s Encrypt, hot reload. What was missing was the workflow: adding and removing domains across many projects without ever touching the shared file by hand. caddyku is that workflow. Each app declares its domains in its own caddyku.yaml, and one command merges them safely into the shared Caddyfile.
and now it’s one command
before / after
why it’s built this way
- Never break the shared file
caddyku only touches text between its own # BEGIN/END caddyku markers, so anything hand-written is preserved. Every write is validated inside the running Caddy container and rolled back on failure.
- Explain failures, don’t hide them
The common real-world problem is a silent 502, so caddyku status exists specifically to diagnose the container → network → upstream chain.
- Don’t become a framework
Simple things get YAML fields (redirect_www, basic_auth); anything more drops down to raw Caddy directives. Dependencies are kept to two.
- Safe by default
Every mutating command supports --dry-run to preview the exact Caddyfile diff before touching a production server.
live on this site
service: web
container: jufidev-web
domains:
- domain: jufi.dev
upstream: jufidev-web:80
redirect_www: trueIt’s open source (MIT), ships as a single Go binary with a self-update command and GoReleaser builds, and runs CI on every pull request. This site (jufi.dev) is served through it.