plonk is a tiny control-plane API for Docker hosts. It lets a remote caller (for example GitHub Actions over Tailscale) trigger:
docker compose pulldocker compose up -d
This is useful when your CI pipeline pushes a fresh image to GHCR and then asks each node to redeploy using its local compose stack.
- Minimal REST API with token auth
- Serialized deploy requests (one deploy at a time)
- Optional pull control (
pullon/off) - Per-request command output returned in the API response
No auth required.
Example response:
{"status":"ok","time":"2026-08-14T12:34:56Z"}Requires a Bearer token in Authorization.
Body:
{
"pull": true,
"services": ["api", "worker"]
}pull(optional): defaults to server setting (PLONK_ALLOW_PULL)services(optional): if omitted, compose applies to all services
Environment variables:
PLONK_BIND_ADDR(default:8080)PLONK_SHARED_SECRET(required)PLONK_COMPOSE_FILE(default/compose/docker-compose.yml)PLONK_PROJECT_DIR(default/compose)PLONK_ALLOW_PULL(defaulttrue)PLONK_COMMAND_TIMEOUT(default10m, Go duration format)
export PLONK_SHARED_SECRET='replace-me'
export PLONK_COMPOSE_FILE='/absolute/path/to/docker-compose.yml'
export PLONK_PROJECT_DIR='/absolute/path/to/compose/folder'
go run .plonk needs:
- Docker CLI + compose plugin in the container
- Access to the host Docker socket
- Mounted compose project files
Example:
docker run -d \
--name plonk \
--restart unless-stopped \
-p 8080:8080 \
-e PLONK_SHARED_SECRET='replace-me' \
-e PLONK_COMPOSE_FILE='/compose/docker-compose.yml' \
-e PLONK_PROJECT_DIR='/compose' \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/myapp:/compose \
ghcr.io/nirima/plonk:0.1.0Call a node over Tailscale after pushing an image:
curl -sS -X POST "http://100.x.y.z:8080/v1/redeploy" \
-H "Authorization: Bearer ${PLONK_TOKEN}" \
-H "Content-Type: application/json" \
--data '{"pull":true}'/.github/workflows/container.ymlbuilds on PR/main and pushes on non-PR runs./.github/workflows/release.ymlbuilds and pushes on version tags (v*.*.*).- Both workflows publish multi-arch images:
linux/amd64andlinux/arm64.
GHCR packages can default to private on first publish. To auto-switch visibility to public, set a repository secret:
GHCR_ADMIN_TOKEN: a PAT with package admin permissions for the publishing account.
If this secret is not set, image publish still succeeds but visibility may need to be changed once in GitHub UI.
- Protect network access (for example: Tailscale ACLs/firewall rules).
- Keep
PLONK_SHARED_SECRETin a secret manager. - Mounting
/var/run/docker.sockgives broad host control; run only on trusted nodes.