WIP: feat(hardening): blocks architecture with core and hardened tiers #16

Draft
bram.buijs wants to merge 1 commit from bram.buijs/DAWO-NixOS:feat/blocks-rework-interface into main
Collaborator

References #8. Supersedes #12.

Reworks the hardening set from the earlier opt-in PR (#12) onto the blocks model
from #8. Every capability is now a block exposed as flake.modules.nixos.<name>,
with the interface dawo.<block>.enable plus dawo.<block>.options.<...> and the
body in mkIf cfg.enable, so a consumer flake takes this repo as an input and
composes blocks (same shape as thecloudexplorers/nixos-blocks).

Two tier-aggregates:

  • profiles-dawo-core (mandatory): usb-control, ssh, sysctl-baseline, timesync,
    audit. Forced on with lib.mkForce, so a consumer can configure them through
    dawo.<block>.options.* but cannot silently drop one. Wired into
    profiles-dawo-generic.
  • profiles-dawo-hardened (opt-in): declares the risky/specialist blocks default
    off (AppArmor for now; pam-u2f/pam-oath/egress-deny to follow). A workplace
    imports it and flips what it wants.

Enforcement follows the #8 rules:

  • mandatory enforcement is lib.mkForce (no escape hatch, a host cannot lower the
    floor); suggested tunables are lib.mkDefault.
  • no option may break a device silently: an empty NTP server list and a
    non-positive maxAuthTries assert at build time; the usbguard empty allowlist
    is a defined safe default (block newly-inserted, allow already-present), not an
    undefined option.
  • the audit block is intentionally a no-op on nixpkgs 26.05: auditctl 4.1.2 plus
    the NixOS audit module reject the generated rules ("error in line 2", status
    255), which would fail every rebuild. The block is wired so the contract holds;
    the body fills once that is fixed upstream. journald and chrony cover the
    log/time base meanwhile.

Norm: BIO/NCSC (the per-block comments map back to the ANSSI/CIS origins).

nix flake check is green on both hosts. Build/deploy proof on a Lenovo T495s to
follow before merge.

Question: are you happy with dawo. as the public option prefix and the two
profile-aggregate names (profiles-dawo-core / profiles-dawo-hardened) as the
consumer interface?

References #8. Supersedes #12. Reworks the hardening set from the earlier opt-in PR (#12) onto the blocks model from #8. Every capability is now a block exposed as `flake.modules.nixos.<name>`, with the interface `dawo.<block>.enable` plus `dawo.<block>.options.<...>` and the body in `mkIf cfg.enable`, so a consumer flake takes this repo as an input and composes blocks (same shape as thecloudexplorers/nixos-blocks). Two tier-aggregates: - `profiles-dawo-core` (mandatory): usb-control, ssh, sysctl-baseline, timesync, audit. Forced on with `lib.mkForce`, so a consumer can configure them through `dawo.<block>.options.*` but cannot silently drop one. Wired into `profiles-dawo-generic`. - `profiles-dawo-hardened` (opt-in): declares the risky/specialist blocks default off (AppArmor for now; pam-u2f/pam-oath/egress-deny to follow). A workplace imports it and flips what it wants. Enforcement follows the #8 rules: - mandatory enforcement is `lib.mkForce` (no escape hatch, a host cannot lower the floor); suggested tunables are `lib.mkDefault`. - no option may break a device silently: an empty NTP server list and a non-positive `maxAuthTries` assert at build time; the usbguard empty allowlist is a defined safe default (block newly-inserted, allow already-present), not an undefined option. - the audit block is intentionally a no-op on nixpkgs 26.05: auditctl 4.1.2 plus the NixOS audit module reject the generated rules ("error in line 2", status 255), which would fail every rebuild. The block is wired so the contract holds; the body fills once that is fixed upstream. journald and chrony cover the log/time base meanwhile. Norm: BIO/NCSC (the per-block comments map back to the ANSSI/CIS origins). `nix flake check` is green on both hosts. Build/deploy proof on a Lenovo T495s to follow before merge. Question: are you happy with `dawo.` as the public option prefix and the two profile-aggregate names (`profiles-dawo-core` / `profiles-dawo-hardened`) as the consumer interface?
Introduce the block interface from #8: each capability is a NixOS module
exposed as flake.modules.nixos.hardening-<name>, switched with
dawo.<block>.enable and tuned through dawo.<block>.options.<...>.

Two aggregate tiers:
- profiles-dawo-core: mandatory BIO/NCSC blocks, forced on with mkForce so a
  host cannot silently drop them (usb-control, ssh, sysctl-baseline, timesync,
  audit). Wired into profiles-dawo-generic.
- profiles-dawo-hardened: opt-in blocks, default off (apparmor for now).

Mandatory enforcement uses mkForce, suggested defaults use mkDefault, and an
empty or undefined option that would break the device asserts at build time
(ssh maxAuthTries > 0, timesync servers non-empty).

Supersedes the opt-in-only set in #12.

Ref: #6 #8

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bram.buijs force-pushed feat/blocks-rework-interface from ca50580b9d to 7b47873dc7 2026-06-18 12:07:35 +00:00 Compare
Collaborator

Loving the detail and references in this PR! Keep up the good work.

Please prove this builds with the defined profiles and I'm happy to merge.

Loving the detail and references in this PR! Keep up the good work. Please prove this builds with the defined profiles and I'm happy to merge.
bram.buijs force-pushed feat/blocks-rework-interface from 7b47873dc7 to dfe1adbd15 2026-06-18 13:24:21 +00:00 Compare
rutger.putter changed title from feat(hardening): blocks architecture with core and hardened tiers to WIP: feat(hardening): blocks architecture with core and hardened tiers 2026-06-22 08:44:52 +00:00
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feat/blocks-rework-interface:bram.buijs-feat/blocks-rework-interface
git switch bram.buijs-feat/blocks-rework-interface
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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
MinBZK/DAWO-NixOS!16
No description provided.