P5-03 + P5-07: docker-only release path & reference deployment #17

Merged
steve merged 2 commits from p5-03-docker-release into main 2026-05-05 17:36:09 +01:00
Owner

Summary

  • P5-03 (pivot): drop goreleaser/binary archives. Single deliverable per tag is a multi-arch (linux amd64+arm64) server image with cross-compiled agent binaries (linux amd64+arm64, windows amd64) + install.sh + install.ps1 + the systemd unit baked under `/opt/restic-manager/dist/`. `/agent/binary` and `/install/*` handlers fall back from `/...` to `/...` so a fresh container Just Works.
  • Release workflow (`.gitea/workflows/release.yml`) on `v*..` tag-push (fan-out `:vX.Y.Z` / `:X.Y` / `:X`, plus `:latest` once `MAJOR>=1`) and `workflow_dispatch` (`:snapshot-` only). Pushes to the Gitea container registry on this instance.
  • Version ldflags: both binaries grow `main.commit` + `main.date`. Makefile and Dockerfile fill them.
  • P5-07: `deploy/docker-compose.yml` rewritten as a server-only stack (image-pinned via `RM_VERSION`, named volume, localhost-bound). `docs/reverse-proxy.md` documents the headers, `RM_TRUSTED_PROXY` CIDR rule, and worked snippets for Caddy / nginx / Traefik against an external proxy.

Spec: `docs/superpowers/specs/2026-05-05-p5-03-docker-only-release.md`
Plan: `docs/superpowers/plans/2026-05-05-p5-03-docker-only-release.md`

Test plan

  • `go vet ./...` clean
  • `go test ./internal/server/http/ ./internal/server/config/` clean (6 new tests cover handler dual-path)
  • Local `docker build` succeeds; image ~50 MB
  • Smoke: `/agent/binary?os=linux&arch=amd64` → 200 (real ELF), `?os=windows&arch=amd64` → 200 (real PE), `/install/install.sh` + `/install/restic-manager-agent.service` → 200, `os=darwin` → 400, traversal → 404
  • `-version` end-to-end: server + baked agent both report ldflag-supplied VERSION/COMMIT/DATE
  • Release workflow exercised on first `workflow_dispatch` after merge
## Summary - **P5-03 (pivot):** drop goreleaser/binary archives. Single deliverable per tag is a multi-arch (linux amd64+arm64) server image with cross-compiled agent binaries (linux amd64+arm64, windows amd64) + install.sh + install.ps1 + the systemd unit baked under \`/opt/restic-manager/dist/\`. \`/agent/binary\` and \`/install/*\` handlers fall back from \`<DataDir>/...\` to \`<BundledAssetsDir>/...\` so a fresh container Just Works. - **Release workflow** (\`.gitea/workflows/release.yml\`) on \`v*.*.*\` tag-push (fan-out \`:vX.Y.Z\` / \`:X.Y\` / \`:X\`, plus \`:latest\` once \`MAJOR>=1\`) and \`workflow_dispatch\` (\`:snapshot-<shortsha>\` only). Pushes to the Gitea container registry on this instance. - **Version ldflags:** both binaries grow \`main.commit\` + \`main.date\`. Makefile and Dockerfile fill them. - **P5-07:** \`deploy/docker-compose.yml\` rewritten as a server-only stack (image-pinned via \`RM_VERSION\`, named volume, localhost-bound). \`docs/reverse-proxy.md\` documents the headers, \`RM_TRUSTED_PROXY\` CIDR rule, and worked snippets for Caddy / nginx / Traefik against an external proxy. Spec: \`docs/superpowers/specs/2026-05-05-p5-03-docker-only-release.md\` Plan: \`docs/superpowers/plans/2026-05-05-p5-03-docker-only-release.md\` ## Test plan - [x] \`go vet ./...\` clean - [x] \`go test ./internal/server/http/ ./internal/server/config/\` clean (6 new tests cover handler dual-path) - [x] Local \`docker build\` succeeds; image ~50 MB - [x] Smoke: \`/agent/binary?os=linux&arch=amd64\` → 200 (real ELF), \`?os=windows&arch=amd64\` → 200 (real PE), \`/install/install.sh\` + \`/install/restic-manager-agent.service\` → 200, \`os=darwin\` → 400, traversal → 404 - [x] \`-version\` end-to-end: server + baked agent both report ldflag-supplied VERSION/COMMIT/DATE - [ ] Release workflow exercised on first \`workflow_dispatch\` after merge
steve added 2 commits 2026-05-05 17:28:59 +01:00
Single public deliverable per tag: a multi-arch server image, with
cross-compiled agent binaries + install scripts + the systemd unit
baked under /opt/restic-manager/dist/. The /agent/binary and
/install/* handlers fall back from <DataDir>/... to that read-only
path so a fresh container Just Works without first-run staging;
operators can still drop a custom build into <DataDir>/ to override
per-host.

Architecture rationale: agent distribution already routes through
the running server, so the release surface mirrors that — there's
no second source of truth to keep in sync.

Workflow .gitea/workflows/release.yml triggers on v*.*.* tag-push
(fan-out :vX.Y.Z / :X.Y / :X, plus :latest once MAJOR>=1) and
workflow_dispatch (snapshot tag only). Pushes to the Gitea
container registry on this instance.

Both binaries grow main.commit + main.date ldflag targets. Makefile
and Dockerfile fill them; release workflow forwards from gitea.sha
plus a UTC timestamp.

Spec : docs/superpowers/specs/2026-05-05-p5-03-docker-only-release.md
Plan : docs/superpowers/plans/2026-05-05-p5-03-docker-only-release.md
p5-07: reference deployment (server-only compose + reverse-proxy docs)
CI / Test (store) (pull_request) Successful in 21s
CI / Test (rest) (pull_request) Successful in 38s
CI / Lint (pull_request) Successful in 33s
CI / Build (windows/amd64) (pull_request) Successful in 39s
CI / Test (server-http) (pull_request) Successful in 1m17s
CI / Build (linux/amd64) (pull_request) Successful in 23s
CI / Build (linux/arm64) (pull_request) Successful in 39s
d6f6d19bff
The reverse proxy is assumed to live outside this project (Caddy,
nginx, Traefik, whatever the operator already runs). The reference
compose stands up only the server: image-pinned via RM_VERSION,
named volume for operator state, localhost-bound so the proxy
reaches it on loopback.

docs/reverse-proxy.md covers what the proxy must forward — the
X-Forwarded-* headers, Host, and Connection: upgrade for the agent
WebSocket and live-log streams — plus the RM_TRUSTED_PROXY CIDR
rule that gates header trust. Worked examples for Caddy, nginx
(with the websocket upgrade map + 1h proxy_read_timeout for live
logs), and Traefik.
steve merged commit b91fe56c83 into main 2026-05-05 17:36:09 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/restic-manager#17