mail: enrol the host in ymr.serviceSandbox (nix-config#932) #1965

Merged
hermes merged 1 commit from kb/NCFG-932-mail-sandbox into main 2026-10-13 06:55:41 -06:00
Collaborator

Kanban card nix-config#932 (child of nix-config#928, split by the disjointness referee).

What

Enable ymr.serviceSandbox on mail and enrol the units whose write paths were
measured on the host (cutover from nix-config#896 §9 step 2; template = the vpn-mx
cutover, nix-config#909).

Measured on mail 2026-10-13 with systemctl show <unit> -p ExecStart -p StateDirectory:

unit writes
prometheus-node-exporter (none — reads /proc + /sys)
prometheus-process-exporter (none — reads /proc)
prometheus-systemd-exporter (none — reads the bus)
vmagent /var/cache/vmagent (-remoteWrite.tmpDataPath)
vlagent /var/lib/vlagent (tmpDataPath + file checkpoints)
systemd-journal-upload /var/lib/systemd/journal-upload (--save-state)

prometheus-node-exporter carries the required per-host delta
SystemCallFilter = [ "@system-service" "@clock" ] — node_exporter's timex
collector calls adjtimex(2), which the module's default @system-service
excludes; without it every scrape dies with SIGSYS and the unit crash-loops
(measured on vpn-mx: sig=31 syscall=171, NRestarts=16 in 13 min).

postgres / dovecot / postfix / caddy stay out (module exception register —
mail + ingress writers need measured paths first, one host at a time); the CI runners
are excluded outright; grafana/listmonk/atticd are later cutovers.

The module's table is applied at lib.mkOverride 1500, so each unit's own stronger
declaration wins (the nixpkgs exporters already declare ProtectSystem=strict,
ProtectHome, PrivateTmp, NoNewPrivileges; vlagent declared none and now gains
the full table).

DoD

  • CI green on the head SHA
  • merged (merge commit, not squash)
  • deployed to mail
  • verified LIVE on mail: systemctl show <unit> shows the table, every enrolled
    unit active with NRestarts=0, /etc/fleet-service-sandbox.policy present, and a
    real /metrics scrape returns 200

Offline evidence

  • nix eval .#nixosConfigurations.mail.config.ymr.serviceSandbox.enrolledUnits
    → the six units above
  • nix eval .#nixosConfigurations.mail.config.systemd.services.<unit>.serviceConfig
    → the hardening keys + ReadWritePaths
  • full config.system.build.toplevel.drvPath evaluates (assertions pass)
Kanban card nix-config#932 (child of nix-config#928, split by the disjointness referee). ## What Enable `ymr.serviceSandbox` on **mail** and enrol the units whose write paths were measured on the host (cutover from nix-config#896 §9 step 2; template = the vpn-mx cutover, nix-config#909). Measured on mail 2026-10-13 with `systemctl show <unit> -p ExecStart -p StateDirectory`: | unit | writes | | --- | --- | | prometheus-node-exporter | (none — reads /proc + /sys) | | prometheus-process-exporter | (none — reads /proc) | | prometheus-systemd-exporter | (none — reads the bus) | | vmagent | `/var/cache/vmagent` (`-remoteWrite.tmpDataPath`) | | vlagent | `/var/lib/vlagent` (tmpDataPath + file checkpoints) | | systemd-journal-upload | `/var/lib/systemd/journal-upload` (`--save-state`) | `prometheus-node-exporter` carries the required per-host delta `SystemCallFilter = [ "@system-service" "@clock" ]` — node_exporter's `timex` collector calls `adjtimex(2)`, which the module's default `@system-service` excludes; without it every scrape dies with SIGSYS and the unit crash-loops (measured on vpn-mx: `sig=31 syscall=171`, NRestarts=16 in 13 min). `postgres` / `dovecot` / `postfix` / `caddy` stay out (module exception register — mail + ingress writers need measured paths first, one host at a time); the CI runners are excluded outright; grafana/listmonk/atticd are later cutovers. The module's table is applied at `lib.mkOverride 1500`, so each unit's own stronger declaration wins (the nixpkgs exporters already declare `ProtectSystem=strict`, `ProtectHome`, `PrivateTmp`, `NoNewPrivileges`; vlagent declared none and now gains the full table). ## DoD - [ ] CI green on the head SHA - [ ] merged (merge commit, not squash) - [ ] deployed to mail - [ ] verified LIVE on mail: `systemctl show <unit>` shows the table, every enrolled unit active with NRestarts=0, `/etc/fleet-service-sandbox.policy` present, and a real `/metrics` scrape returns 200 ## Offline evidence - `nix eval .#nixosConfigurations.mail.config.ymr.serviceSandbox.enrolledUnits` → the six units above - `nix eval .#nixosConfigurations.mail.config.systemd.services.<unit>.serviceConfig` → the hardening keys + ReadWritePaths - full `config.system.build.toplevel.drvPath` evaluates (assertions pass)
mail: enrol the host in ymr.serviceSandbox (nix-config#932)
Some checks failed
NixOS Build Check / Flake input regression guard (pull_request) Successful in 6s
NixOS Build Check / Scope changed deployable hosts (pull_request) Successful in 10s
PR base guard / Base drift / conflict check (pull_request) Successful in 11s
NixOS Build Check / Hermes runtime gates (one eval of vpn's runtime) (pull_request) Has been skipped
NixOS Build Check / Worker-scope reaper worker signature (mutation-tested) (pull_request) Successful in 4s
Secret Scan / gitleaks scan (pull_request) Successful in 11s
NixOS Build Check / Kanban pool capacity knob (runtime override + clamp, mutation-tested) (pull_request) Successful in 3s
NixOS Build Check / Sentinel pass budget contract (prompt forbids the full board walk, mutation-tested) (pull_request) Successful in 3s
NixOS Build Check / CI-scratch reaper class table (mutation-tested) (pull_request) Successful in 12s
NixOS Build Check / foremerge accept-order contract (real binary) (pull_request) Has been skipped
NixOS Build Check / Build changed host closures (native, one eval) (pull_request) Successful in 30s
NixOS Build Check / .forgejo/tests python suites (hermetic) (pull_request) Successful in 56s
NixOS Build Check / Repo gates (the folded selftest battery) (pull_request) Has been cancelled
71d7c4746d
Enable the fleet service sandbox on mail and enrol the units whose write
paths were measured on the host: the three prometheus exporters (no
writes), vmagent (/var/cache/vmagent), vlagent (/var/lib/vlagent) and
systemd-journal-upload (/var/lib/systemd/journal-upload). node-exporter
keeps the required @clock syscall delta (timex/adjtimex).

Cutover from nix-config#896 section 9 step 2; template from the vpn-mx
cutover (nix-config#909). postgres/dovecot/postfix/caddy stay out (module
exception register).
hermes force-pushed kb/NCFG-932-mail-sandbox from 71d7c4746d
Some checks failed
NixOS Build Check / Flake input regression guard (pull_request) Successful in 6s
NixOS Build Check / Scope changed deployable hosts (pull_request) Successful in 10s
PR base guard / Base drift / conflict check (pull_request) Successful in 11s
NixOS Build Check / Hermes runtime gates (one eval of vpn's runtime) (pull_request) Has been skipped
NixOS Build Check / Worker-scope reaper worker signature (mutation-tested) (pull_request) Successful in 4s
Secret Scan / gitleaks scan (pull_request) Successful in 11s
NixOS Build Check / Kanban pool capacity knob (runtime override + clamp, mutation-tested) (pull_request) Successful in 3s
NixOS Build Check / Sentinel pass budget contract (prompt forbids the full board walk, mutation-tested) (pull_request) Successful in 3s
NixOS Build Check / CI-scratch reaper class table (mutation-tested) (pull_request) Successful in 12s
NixOS Build Check / foremerge accept-order contract (real binary) (pull_request) Has been skipped
NixOS Build Check / Build changed host closures (native, one eval) (pull_request) Successful in 30s
NixOS Build Check / .forgejo/tests python suites (hermetic) (pull_request) Successful in 56s
NixOS Build Check / Repo gates (the folded selftest battery) (pull_request) Has been cancelled
to 5a09b36272
All checks were successful
PR base guard / Base drift / conflict check (pull_request) Successful in 7s
NixOS Build Check / Flake input regression guard (pull_request) Successful in 8s
NixOS Build Check / Scope changed deployable hosts (pull_request) Successful in 14s
Secret Scan / gitleaks scan (pull_request) Successful in 11s
foremerge intent (advisory) all 1 changed path(s) covered by a live foremerge intent
NixOS Build Check / Hermes runtime gates (one eval of vpn's runtime) (pull_request) Has been skipped
NixOS Build Check / Build changed host closures (native, one eval) (pull_request) Successful in 28s
NixOS Build Check / Worker-scope reaper worker signature (mutation-tested) (pull_request) Successful in 5s
NixOS Build Check / Sentinel pass budget contract (prompt forbids the full board walk, mutation-tested) (pull_request) Successful in 4s
NixOS Build Check / Kanban pool capacity knob (runtime override + clamp, mutation-tested) (pull_request) Successful in 5s
NixOS Build Check / foremerge accept-order contract (real binary) (pull_request) Has been skipped
NixOS Build Check / CI-scratch reaper class table (mutation-tested) (pull_request) Successful in 4s
NixOS Build Check / .forgejo/tests python suites (hermetic) (pull_request) Successful in 42s
NixOS Build Check / Repo gates (the folded selftest battery) (pull_request) Successful in 4m26s
foremerge acceptance (advisory) chg_13bb3924642d464f95bb3fc6cb6335a2 was accepted at 5a09b36272, which is in 5a09b36272's history - the landing record stays reachable
2026-10-13 06:47:55 -06:00
Compare
hermes merged commit ee539e1177 into main 2026-10-13 06:55:41 -06:00
Sign in to join this conversation.
No reviewers
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
ymrtech/nix-config!1965
No description provided.