P1 — harden container state/config/key volumes, non-root execution, and read-only-root policy #180

Open
opened 2026-08-22 21:57:48 +00:00 by lost-rob0t · 0 comments
lost-rob0t commented 2026-08-22 21:57:48 +00:00 (Migrated from github.com)

Parent epic: #153
Depends on: #149
Integrates with: #130 security, #131 principal-scoped persistence.

Goal

Define and enforce the mutable-state contract for the Nix-built zara-server image so secrets/private state live only in explicit mounts and the service can run with least privilege.

Required state layout

Research and document exact container paths for configuration, Prolog user configuration where supported, conversation SQLite/state, memory/vector persistence, CURVE server identity and enrolled-client registry, optional logs/metrics, plugin/module mounts, model/cache data, and runtime IPC/temp files. Immutable image assets and mutable state must never be conflated.

Security/runtime requirements

  • choose a deterministic non-root UID/GID strategy unless research proves a stronger alternative;
  • reject unsafe ownership/permissions for CURVE private keys and security registries;
  • make owner/private directory creation deterministic on fresh volumes;
  • support a read-only root filesystem where practical, declaring every writable mount/tmp path;
  • no secret-bearing defaults in environment/image metadata;
  • no world-writable state directories;
  • explicit migration/initialization semantics for empty vs existing volumes;
  • plugin mounts are opt-in with clear trust/permission policy;
  • no /var/run/docker.sock, privileged mode, host root filesystem, X11/Wayland/Pulse/PipeWire mounts by default.

Mandatory tests

  • fresh empty volumes initialize with correct ownership/modes;
  • existing valid volume starts without rewriting secrets;
  • world/group-readable private key rejected or repaired only under explicit safe policy;
  • wrong owner, read-only state, missing/corrupt security registry, unwritable temp/runtime paths;
  • read-only root + declared writable mounts;
  • non-root process cannot write outside allowed locations;
  • conversation/memory state survives restart and remains principal-scoped;
  • no secret content in image layers/config/default environment/startup diagnostics.

Gates

TDD-first container-state tests, focused non-interactive volume/permission script, Nix image build, container engine integration where available, full repo/Nix and exact-head Actions.

Acceptance

A freshly pulled image runs zara-server as a least-privileged service using explicit private mounts, survives restart with state, and cannot depend on writable image layers or baked credentials.

Parent epic: #153 Depends on: #149 Integrates with: #130 security, #131 principal-scoped persistence. ## Goal Define and enforce the mutable-state contract for the Nix-built `zara-server` image so secrets/private state live only in explicit mounts and the service can run with least privilege. ## Required state layout Research and document exact container paths for configuration, Prolog user configuration where supported, conversation SQLite/state, memory/vector persistence, CURVE server identity and enrolled-client registry, optional logs/metrics, plugin/module mounts, model/cache data, and runtime IPC/temp files. Immutable image assets and mutable state must never be conflated. ## Security/runtime requirements - choose a deterministic non-root UID/GID strategy unless research proves a stronger alternative; - reject unsafe ownership/permissions for CURVE private keys and security registries; - make owner/private directory creation deterministic on fresh volumes; - support a read-only root filesystem where practical, declaring every writable mount/tmp path; - no secret-bearing defaults in environment/image metadata; - no world-writable state directories; - explicit migration/initialization semantics for empty vs existing volumes; - plugin mounts are opt-in with clear trust/permission policy; - no `/var/run/docker.sock`, privileged mode, host root filesystem, X11/Wayland/Pulse/PipeWire mounts by default. ## Mandatory tests - fresh empty volumes initialize with correct ownership/modes; - existing valid volume starts without rewriting secrets; - world/group-readable private key rejected or repaired only under explicit safe policy; - wrong owner, read-only state, missing/corrupt security registry, unwritable temp/runtime paths; - read-only root + declared writable mounts; - non-root process cannot write outside allowed locations; - conversation/memory state survives restart and remains principal-scoped; - no secret content in image layers/config/default environment/startup diagnostics. ## Gates TDD-first container-state tests, focused non-interactive volume/permission script, Nix image build, container engine integration where available, full repo/Nix and exact-head Actions. ## Acceptance A freshly pulled image runs `zara-server` as a least-privileged service using explicit private mounts, survives restart with state, and cannot depend on writable image layers or baked credentials.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/zara#180
No description provided.