diff --git a/docs/SERVICES.md b/docs/SERVICES.md index 8e96b34..1cd61b2 100644 --- a/docs/SERVICES.md +++ b/docs/SERVICES.md @@ -184,8 +184,11 @@ curl -k -i -X OPTIONS https://mail.dezky.local/Microsoft-Server-ActiveSync curl -k -i -u user@tenant.tld:app-password -X OPTIONS \ https://mail.dezky.local/Microsoft-Server-ActiveSync -# Per-device sync state -docker exec dezky-zpush php /usr/share/z-push/z-push-admin.php -a list +# Per-device sync state. ALWAYS run as www-data — a root-run z-push-admin +# leaves root-owned state files that 500 every request ("Not possible to +# write to the configured state directory"). The prod pod has an +# initContainer that re-chowns the state dir on start as a backstop. +docker exec -u www-data dezky-zpush php /usr/share/z-push/z-push-admin.php -a list ``` --- diff --git a/infrastructure/production/fleet/apps/zpush.yaml b/infrastructure/production/fleet/apps/zpush.yaml index 14270ac..19d54c0 100644 --- a/infrastructure/production/fleet/apps/zpush.yaml +++ b/infrastructure/production/fleet/apps/zpush.yaml @@ -45,6 +45,19 @@ spec: labels: app.kubernetes.io/name: zpush spec: + # Normalize state ownership on every start: Apache/Z-Push runs as + # www-data, but anything exec'd as root (kubectl exec z-push-admin, + # debugging) can leave root-owned files on the PVC — which 500s every + # request with "Not possible to write to the configured state + # directory" (bitten 2026-06-12). State is disposable, ownership isn't + # precious: just take it back at boot. + initContainers: + - name: fix-state-ownership + image: git.lastcloud.io/ronnibaslund/dezky/zpush:latest + command: ["sh", "-c", "chown -R www-data:www-data /var/lib/z-push"] + volumeMounts: + - name: state + mountPath: /var/lib/z-push containers: - name: zpush # CI pins this to the commit SHA at deploy time; :latest is the fallback.