From 5e2e132a4ba0f5268d3689f6068dd61adb3d0168 Mon Sep 17 00:00:00 2001 From: Onno Date: Sat, 25 Jul 2026 17:21:47 +0200 Subject: [PATCH] fix(docker): create /data/git so the compose volume inherits buzz ownership (#2840) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem A fresh `deploy/compose` install never starts. The relay exits during config validation and crash-loops under `restart: unless-stopped`: ``` Error: Configuration error: invalid config: BUZZ_GIT_PACK_CACHE_PATH=/data/git/.pack-cache could not be created: Permission denied (os error 13) ``` ## Cause The image runs as `buzz:buzz`. Docker seeds a volume's ownership from the image **only when the mount point already exists there** — otherwise it creates the mount point as `root:root`. `compose.yml` mounts `buzz-git-data` at `/data/git`, which the image doesn't create, so the relay can't write the pack cache. `USER buzz:buzz` and `BUZZ_GIT_REPO_PATH=/data/git` arrived in the same commit (426497a), so there was never a working state to regress from. The other deployment paths are unaffected, which is probably why this went unnoticed: the code default (`./repos`, under the `buzz`-owned home) works unmounted, and the Helm chart gets volume ownership from `fsGroup: 65532`. ## Fix Create `/data/git` as `buzz:buzz` in the image, the way the official `postgres` image prepares `$PGDATA`. `compose.yml`, `run.sh` and the volume layout are untouched, so existing deployments need no migration and the `run.sh backup-hint` output stays accurate. ## Testing `ghcr.io/block/buzz@sha256:ec96e029` on arm64 with this change applied as a derived layer, running **unmodified** `deploy/compose/compose.yml` against clean volumes: | Image | `/data/git` owner | Result | |---|---|---| | upstream | `root:root` | `Permission denied` — crash loop | | patched | `buzz:buzz` | relay healthy | ``` relay health: healthy /data/git = buzz:buzz (contains .pack-cache) /_readiness -> 200 WS upgrade -> 101 ``` Relay log shows migrations applied, the A3 git object-store conformance probe passing, and `buzz-relay TCP listening`. I have not run `just ci` / `just test` — this touches no Rust, JS, or mobile code. Happy to run them if you'd like. ## Alternatives - A `git-init` one-shot in `compose.yml` that chowns the volume. Works, but adds a container to every `up` and doesn't help `docker run` or Kubernetes without an `fsGroup`. - Moving `BUZZ_GIT_REPO_PATH` to the code default `/var/lib/buzz/repos` and pre-creating that instead. Arguably tidier, since `/data/git` then only lives in the compose bundle — but it moves the volume mount point, so existing installs would have to relocate their git data. Happy to do it that way if you prefer; it seemed the wrong trade for a bug fix. Signed-off-by: Onno Klein Hofmeijer --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index 23904ab9ee..661be6c3a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -150,6 +150,9 @@ ENV BUZZ_WEB_DIR=/srv/buzz/web \ # 3000: app (WS + REST) · 8080: /_liveness, /_readiness · 9102: /metrics EXPOSE 3000 8080 9102 +# deploy/compose mounts a volume here; pre-created so it inherits buzz:buzz. +RUN mkdir -p /data/git && chown buzz:buzz /data/git + USER buzz:buzz WORKDIR /var/lib/buzz