fix(docker): correct non-root stanza for Alpine and distroless stages (#2604 follow-up) - #2609
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Docker Hardening ValidationHardening Validation ReportValidated: Wed Aug 19 00:07:55 UTC 2026Services CheckedPMOVES.AI Docker Hardening Validation[INFO] Checking: pmoves/docker-compose.hardened.yml [INFO] Validating: hi-rag-gateway-v2 [INFO] Validating: extract-worker [INFO] Validating: langextract [INFO] Validating: presign [INFO] Validating: render-webhook [INFO] Validating: retrieval-eval [INFO] Validating: pdf-ingest [INFO] Validating: jellyfin-bridge [INFO] Validating: invidious-companion-proxy [INFO] Validating: ffmpeg-whisper [INFO] Validating: media-video [INFO] Validating: media-audio [INFO] Validating: hi-rag-gateway-v2-gpu [INFO] Validating: hi-rag-gateway-gpu [INFO] Validating: deepresearch [INFO] Validating: supaserch [INFO] Validating: publisher-discord [INFO] Validating: mesh-agent [INFO] Validating: nats-echo-req [INFO] Validating: nats-echo-res [INFO] Validating: comfy-watcher [INFO] Validating: grayjay-plugin-host [INFO] Validating: agent-zero [INFO] Validating: p7-room-orchestrator [INFO] Validating: archon [INFO] Validating: channel-monitor [INFO] Validating: pmoves-yt [INFO] Validating: notebook-sync [INFO] Validating: supabase_service_role_key [INFO] Validating: supabase_jwt_secret [INFO] Validating: p7_control_token ====================================== |
🔏 CHIT-aware change — control-body routingThis PR touches a CHIT-aware service (ports 8086/8087/8103/8106/8113/9224 surface). Before a Control-Body ACK:
Advisory routing only — the blocking contract check is CHIT Contract. |
…ages Two follow-ups to #2604's restores, found bringing the agents overlay up on SPARK: - notebooklm-agent (node:20-alpine): Alpine has no useradd; the `|| true` fallback silently skipped creation and left `USER pmoves` dangling — the daemon refused to start ("unable to find user pmoves"). Switched to `adduser -D -s /bin/sh` with no silent fallback; verified the rebuilt image carries pmoves (uid 1001) and runs non-root. - agentgym-rl-coordinator (distroless final stage): no shell, no useradd, RUN cannot execute at all. Use the stage's built-in `nonroot` user, which the pre-existing HF_HOME=/home/nonroot was designed around. Hardening ratchet (with #2606's NO_FROM check): 12/12 baselined, 0 new. Generated with Crush
|
Reviewed and verified — both fixes are correct and the scope is complete. Scope check. #2604 restored 9 Dockerfiles and appended the same Exactly the two you fixed. The other seven are Debian-based where distroless. Confirmed the final stage contains no alpine. Ratchet: One observation, not a blocker. The remaining seven still carry |
809bce7 to
35d69c4
Compare
Docker Hardening ValidationHardening Validation ReportValidated: Wed Aug 19 04:08:20 UTC 2026Services CheckedPMOVES.AI Docker Hardening Validation[INFO] Checking: pmoves/docker-compose.hardened.yml [INFO] Validating: hi-rag-gateway-v2 [INFO] Validating: extract-worker [INFO] Validating: langextract [INFO] Validating: presign [INFO] Validating: render-webhook [INFO] Validating: retrieval-eval [INFO] Validating: pdf-ingest [INFO] Validating: jellyfin-bridge [INFO] Validating: invidious-companion-proxy [INFO] Validating: ffmpeg-whisper [INFO] Validating: media-video [INFO] Validating: media-audio [INFO] Validating: hi-rag-gateway-v2-gpu [INFO] Validating: hi-rag-gateway-gpu [INFO] Validating: deepresearch [INFO] Validating: supaserch [INFO] Validating: publisher-discord [INFO] Validating: mesh-agent [INFO] Validating: nats-echo-req [INFO] Validating: nats-echo-res [INFO] Validating: comfy-watcher [INFO] Validating: grayjay-plugin-host [INFO] Validating: agent-zero [INFO] Validating: p7-room-orchestrator [INFO] Validating: archon [INFO] Validating: channel-monitor [INFO] Validating: pmoves-yt [INFO] Validating: notebook-sync [INFO] Validating: supabase_service_role_key [INFO] Validating: supabase_jwt_secret [INFO] Validating: p7_control_token ====================================== |
…ag port var Four compose defects found bringing the agents overlay up on SPARK after the #2604/#2609 Dockerfile repairs, each reproduced live: 1. nats-init hardcoded the weak nats:pmoves creds while the nats service interpolates ${NATS_PASSWORD:-pmoves} — any node with a rotated NATS_PASSWORD gets an init that fails auth 30/30, and its service_completed_successfully dependents (9 services) never start. Now interpolates ${NATS_USER}/${NATS_PASSWORD}; host stays pinned to nats:4222 so the localhost-inheritance hazard the old comment guarded against does not return. 2. The two P7 stanzas disagreed: canonical fell to the weak default (Authorization Violation on rotated nodes), legacy read ${NATS_URL} directly (inherits host-session NATS_URL values, e.g. an interactive shell exporting a localhost helper URL). Both now use ${P7_NATS_URL:-${NATS_URL:-weak}} — explicit override, then the env-file credentialed URL, weak default last. 3. consciousness-service declared nats-init: condition: service_healthy, but nats-init is a healthcheck-less one-shot (restart: "no") — service_healthy can never be satisfied, blocking consciousness on every fresh bring-up. Now service_completed_successfully, matching its 9 siblings. 4. hi-rag-gateway-gpu (v1) interpolated HIRAG_V2_GPU_HOST_PORT — a copy-paste that guarantees a host-port collision with hi-rag-gateway-v2-gpu wherever both run (SPARK: both want 127.0.0.1: 8087). v1-gpu now uses its own HIRAG_V1_GPU_HOST_PORT (default 8187, the value the broken stanza already declared as its default). Splits regenerated via make compose-split. Validated live on SPARK: nats-init exit 0 (streams provisioned), both P7 instances 13 rooms / nats_connected true, overlay-up-agents completes past all four prior failure points. Generated with Crush
…ag port var (#2610) * fix(compose): NATS auth interpolation + one-shot dep condition + hi-rag port var Four compose defects found bringing the agents overlay up on SPARK after the #2604/#2609 Dockerfile repairs, each reproduced live: 1. nats-init hardcoded the weak nats:pmoves creds while the nats service interpolates ${NATS_PASSWORD:-pmoves} — any node with a rotated NATS_PASSWORD gets an init that fails auth 30/30, and its service_completed_successfully dependents (9 services) never start. Now interpolates ${NATS_USER}/${NATS_PASSWORD}; host stays pinned to nats:4222 so the localhost-inheritance hazard the old comment guarded against does not return. 2. The two P7 stanzas disagreed: canonical fell to the weak default (Authorization Violation on rotated nodes), legacy read ${NATS_URL} directly (inherits host-session NATS_URL values, e.g. an interactive shell exporting a localhost helper URL). Both now use ${P7_NATS_URL:-${NATS_URL:-weak}} — explicit override, then the env-file credentialed URL, weak default last. 3. consciousness-service declared nats-init: condition: service_healthy, but nats-init is a healthcheck-less one-shot (restart: "no") — service_healthy can never be satisfied, blocking consciousness on every fresh bring-up. Now service_completed_successfully, matching its 9 siblings. 4. hi-rag-gateway-gpu (v1) interpolated HIRAG_V2_GPU_HOST_PORT — a copy-paste that guarantees a host-port collision with hi-rag-gateway-v2-gpu wherever both run (SPARK: both want 127.0.0.1: 8087). v1-gpu now uses its own HIRAG_V1_GPU_HOST_PORT (default 8187, the value the broken stanza already declared as its default). Splits regenerated via make compose-split. Validated live on SPARK: nats-init exit 0 (streams provisioned), both P7 instances 13 rooms / nats_connected true, overlay-up-agents completes past all four prior failure points. Generated with Crush * fix(compose): finish the hi-rag port split and drop the now-stale baseline entry Two things this PR started but did not finish. 1. HIRAG_V1_GPU_HOST_PORT was introduced with ZERO declarations. Renaming the two `:-8187` stanzas off HIRAG_V2_GPU_HOST_PORT is the right diagnosis -- verified that one variable was driving TWO services with two different defaults (8187 for the stanza publishing container 8086, 8087 for the v2 GPU console in three other files), so setting the declared 8087 would have moved one service on top of the other. But the new name existed nowhere, so it could never be set and the :-8187 default became the only reachable value. Now declared in env.shared.example beside its siblings, and registered in port_allocator.py next to hi-rag-gateway-v2-gpu. 2. python-tests was failing on a STALE baseline entry, which is the ratchet working: this PR fixed test_no_hardcoded_nats_urls_in_compose (confirmed passing locally on the rebased branch) while it was still recorded as a known failure. Removed that one line. The other four failures in the same file are pre-existing and remain baselined -- checked individually, not assumed. Not touched: the local ratchet run also reports tools.tests.test_cymatic as stale, which is an artifact of this machine's dependency set. CI is authoritative for the baseline, so that line stays. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(compose): keep host-side NATS_URL out of the P7 containers Codex P1, confirmed. This PR fixed the legacy P7 stanza (which read ${NATS_URL} directly) by giving it a fallback chain -- but the same edit REGRESSED the canonical stanza, which was already safe at ${P7_NATS_URL:-<pinned>}. Inserting ${NATS_URL:-...} into the chain reintroduced exactly the hazard this PR's own body documents reproducing: Compose gives a host-session export precedence over every --env-file, so a shell exporting a localhost-oriented NATS URL reaches the container, where localhost is P7 itself. P7 then boots log-only with nats_connected:false and silently drops lifecycle events. All four P7 sites now use the shape nats-init uses in this same PR: P7_NATS_URL=${P7_NATS_URL:-nats://${NATS_USER:-nats}:${NATS_PASSWORD:-pmoves}@nats:4222} That solves the actual problem (a rotated NATS_PASSWORD) without inheriting host state, and P7_NATS_URL remains the explicit per-node override. Edited docker-compose.yml (2 sites) and regenerated the overlays with the pinned ruamel, per #2603 -- .core.yml and .agents.yml are GENERATED, so hand-editing them would be reverted by the next compose-split. One wording note: the comment originally spelled out the poisoned assignment literally, which trips test_no_hardcoded_nats_urls_in_compose. That scanner greps raw lines and does not skip comments, so it flags prose. Reworded rather than weakening the gate; the scanner's comment-blindness is worth fixing separately. Authorized under Known Road compose:pr:2610; recorded in known-roads.jsonl. Verified: test_no_hardcoded_nats_urls_in_compose passes; the other 4 failures in that file are pre-existing and baselined. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Agent Zero <agent.zero@pmoves.ai> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Summary
Follow-up to #2604, found during live bring-up of the agents overlay on SPARK (the same run that validated #2604's restores —
mai-ui-agentbuilt and started):node:20-alpine): fix(docker): restore 9 Dockerfiles truncated to fragments by #2285 #2604's restoredRUN useradd ... || truesilently no-ops on Alpine (nouseradd), leavingUSER pmovespointing at a user that was never created — the daemon refused to start the container (unable to find user pmoves: no matching entries in passwd file). Now usesadduser -D -s /bin/sh pmoveswith no silent fallback.gcr.io/distroless/python3-debian12:nonroot): distroless has no shell — the appendedRUN useraddcannot execute and would break the build outright. Switched to the stage's built-innonrootuser, matching the pre-existingHF_HOME=/home/nonrootthe image was designed around.Testing
docker buildnotebooklm with compose's real context (./services/notebooklm-agent) → image carriespmoves:x:1001,idruns non-rootpython3 tools/hardening_ratchet.py(with fix(hardening-ratchet): a Dockerfile with no FROM is a finding, not a pass #2606's NO_FROM check) → 12/12 baselined, 0 newoverlay-up-agentsre-run (SPARK, next)