diff --git a/services/anki-sync-server.sh b/services/anki-sync-server.sh index 29b726d..c73fdba 100644 --- a/services/anki-sync-server.sh +++ b/services/anki-sync-server.sh @@ -440,6 +440,16 @@ install_anki-sync-server() { case "$MODE" in update) log_info "Refreshing the Anki Sync Server image only — existing accounts, port, and Caddy setup are left as-is." + # The image is a Google distroless "nonroot" build (fixed UID/GID + # 65532, no shell — it can't chown anything itself at startup), so + # ./data has to already be writable by that exact UID or the + # container fails to start. Versions of this installer before this + # fix chowned it to ACTUAL_USER instead, which the container can't + # write to — re-asserting the correct ownership here repairs any + # install made under that bug, non-destructively (it's the + # installer's own bug being corrected, not a config choice, so it + # belongs in the non-destructive update path). + chown -R 65532:65532 "$ANKI_DIR/data" 2>/dev/null ( cd "$ANKI_DIR" && docker compose pull && docker compose up -d ) \ && log_success "Anki Sync Server image refreshed" \ || log_warning "Refresh failed — check: docker compose -f $ANKI_DIR/docker-compose.yml logs" @@ -568,6 +578,19 @@ ANKI_ENV chown -R "$ACTUAL_USER:$ACTUAL_USER" "$ANKI_DIR" + # afrima/anki-sync-server is built on gcr.io/distroless/static-debian12:nonroot + # — the process always runs as that image's fixed "nonroot" UID/GID (65532), + # never as ACTUAL_USER, and distroless has no shell so nothing inside the + # container can chown its own data dir at startup. Applied AFTER the + # ACTUAL_USER chown above (not before — that call would just clobber it, + # since it recurses over the whole $ANKI_DIR including data/) so ./data ends + # up owned by 65532 specifically while docker-compose.yml/.env/README.md + # (which the sysadmin edits, not the container) stay owned by ACTUAL_USER. + # Confirmed live: getting this wrong is exactly what makes the container + # fail to come up with a permissions error the moment it tries to create + # anything under /data (e.g. a new user's collection). + chown -R 65532:65532 "$ANKI_DIR/data" + echo "" log_success "Anki Sync Server${INSTANCE_SUFFIX:+ ($INSTANCE_SUFFIX)} configured at $ANKI_DIR (port $WEB_PORT)" echo ""