feat: overheid baseline (hardening opt-in, users, T495s host, 26.05 pin) #7

Closed
bram.buijs wants to merge 9 commits from bram.buijs/DAWO-NixOS:feat/overheid-baseline into main
Collaborator

Implements the proposal in #6, plus the rest of the overheid baseline I run on. Branch: bram.buijs:feat/overheid-baseline (9 commits). Evaluates green across the hosts.

Hardening (opt-in), see #6: capabilities under modules/<category>/, nothing auto-enabled in profiles-dawo-generic; the org/host imports what it wants. Norm and origin per item in docs/standards.md (BIO/NCSC, cross-referenced to CIS-DIL / ANSSI / DISA STIG). services-usbguard is default-off and needs an allowlist, otherwise it blocks newly plugged USB.

Declarative users: users-hardened (opt-in, mutableUsers=false) plus agenix passwords (hashedPasswordFile), workflow in docs/users.md. Opt-in because it is lockout-risk.

T495s reference client and in-place upgrade: hardware/lenovo-t495s, a disko variant nvme-luks-ext4 that matches an existing install (in-place migration without a wipe, reusing the lanzaboote keys), and docs/deploy.md (nixos-anywhere + deploy-rs).

Pin nixpkgs to 26.05: was nixos-unstable with a 25.11 fallback. This is a policy call, so if unstable is deliberate I'm happy to drop this commit.

Happy to split into per-topic PRs if that is easier to review. (Small note: there's a .forgejo/ CI workflow in here that's mirror-specific; I'll drop it on request.)

Implements the proposal in #6, plus the rest of the overheid baseline I run on. Branch: `bram.buijs:feat/overheid-baseline` (9 commits). Evaluates green across the hosts. **Hardening (opt-in)**, see #6: capabilities under `modules/<category>/`, nothing auto-enabled in `profiles-dawo-generic`; the org/host imports what it wants. Norm and origin per item in `docs/standards.md` (BIO/NCSC, cross-referenced to CIS-DIL / ANSSI / DISA STIG). `services-usbguard` is default-off and needs an allowlist, otherwise it blocks newly plugged USB. **Declarative users**: `users-hardened` (opt-in, `mutableUsers=false`) plus agenix passwords (`hashedPasswordFile`), workflow in `docs/users.md`. Opt-in because it is lockout-risk. **T495s reference client and in-place upgrade**: `hardware/lenovo-t495s`, a disko variant `nvme-luks-ext4` that matches an existing install (in-place migration without a wipe, reusing the lanzaboote keys), and `docs/deploy.md` (nixos-anywhere + deploy-rs). **Pin nixpkgs to 26.05**: was `nixos-unstable` with a 25.11 fallback. This is a policy call, so if unstable is deliberate I'm happy to drop this commit. Happy to split into per-topic PRs if that is easier to review. (Small note: there's a `.forgejo/` CI workflow in here that's mirror-specific; I'll drop it on request.)
Was nixos-unstable with a 25.11 fallback that is nearly end of life.
26.05 is the current stable release; evaluates green across the config.
Modular hardening following the existing category layout:
- boot/hardening: memory kernelParams
- nixos/hardening: sysctl, sudo wheel-only, tmp mount options, login banner
- services/{usbguard,openssh,journald,chrony}: base security + log/time sources
- networking/client: log refused connections

Optional opt-in modules (off by default): nixos/apparmor, nixos/pam-u2f,
services/pcscd (smartcard), services/auditd (stubbed for the auditctl bug).
Wired the base set into profiles-dawo-generic; docs/modules.md documents the
enable/disable workflow. No SIEM shipper here by design.
AMD ThinkPad T495s client wired through profiles-dawo-generic, reusing the
single-nvme-luks disko layout, with a commented opt-in block for the optional
security modules. initrd modules come from an on-device nixos-generate-config;
replace with facter once it boots.
Add users-hardened (opt-in, mutableUsers=false) for fully declarative,
no-drift users. docs/users.md documents the workflow: one module per user
under modules/users, hosts import the users they have, and passwords come
from agenix (hashedPasswordFile) instead of plaintext hashes in git. agenix
is already wired via the environment module.
Document fleet provisioning with nixos-anywhere (uses the existing disko
layout, optional facter hardware generation) and updates via the already
wired deploy-rs nodes.
Match the laptop's existing storage and boot so it can switch to this config
without a wipe: ext4 cryptroot disko layout and lanzaboote secure boot (same
/var/lib/sbctl keys, so the signed chain and TPM2 unlock keep working). Add a
Forgejo CI workflow to build the toplevel on a runner instead of locally.
Add docs/standards.md mapping every hardening item to its norm (BIO/NCSC,
CIS-DIL, ANSSI R-numbers, DISA STIG) and origin, including what came from
securix/bureautix (with file and R-number). Add a norm/origin reference to
each module header so every control is traceable in audits and issues.
Add the four gaps as opt-in modules, each with its norm/origin in the header
and in docs/standards.md:
- nixos-pki-overheid: Firefox enterprise-roots for PKIoverheid (Logius) trust
- networking-dns-tls: opportunistic DNS-over-TLS (NCSC)
- networking-egress-deny: egress default-deny (BIO; no-op until allowlist)
- nixos-pam-oath: TOTP 2FA (NCSC)
Also add tpm2-tools and oath-toolkit to the smartcard module. All verified by
evaluating dawo-t495s with every opt-in module enabled.
The generic image is the neutral grounding; the org/host picks the posture. profiles-dawo-generic no longer enables any hardening - hosts import what they want (docs/modules.md). usbguard ships default-off and needs an allowlist, so a fresh import can't silently kill USB/tethering.
bram.buijs changed title from feat: overheid-baseline — hardening (opt-in), users, T495s-host, 26.05-pin to feat: overheid baseline — hardening (opt-in), users, T495s host, 26.05 pin 2026-06-18 07:49:42 +00:00
bram.buijs changed title from feat: overheid baseline — hardening (opt-in), users, T495s host, 26.05 pin to feat: overheid baseline & hardening (opt-in), users, T495s host, 26.05 pin 2026-06-18 07:51:05 +00:00
bram.buijs changed title from feat: overheid baseline & hardening (opt-in), users, T495s host, 26.05 pin to feat: overheid baseline (hardening opt-in, users, T495s host, 26.05 pin) 2026-06-18 07:51:32 +00:00
Collaborator

@bram.buijs In general, please split up you large (and highly appreciated! 😄) PR into smaller chunks. Each with their own issue, describing what you're solving. This will lead to less discussion and faster merges of smaller (and less risky) code changes.

Secondly, please add proof of a working deploy/build by adding the output of your deploy command and/or a screenshot of a system as a comment.

@bram.buijs In general, please split up you large (and highly appreciated! :smile:) PR into smaller chunks. Each with their own issue, describing what you're solving. This will lead to less discussion and faster merges of smaller (and less risky) code changes. Secondly, please add proof of a working deploy/build by adding the output of your deploy command and/or a screenshot of a system as a comment.
Author
Collaborator

Splitting this up per the review feedback, one topic per PR/issue:

  • Hardening modules (opt-in): #12 (issue #6)
  • Declarative user management: #13 (issue #9)
  • T495s reference client + in-place disko: #14 (issue #10)
  • nixpkgs pin question: #11

Superseded by the above. Closing this one.

Splitting this up per the review feedback, one topic per PR/issue: - Hardening modules (opt-in): #12 (issue #6) - Declarative user management: #13 (issue #9) - T495s reference client + in-place disko: #14 (issue #10) - nixpkgs pin question: #11 Superseded by the above. Closing this one.
bram.buijs closed this pull request 2026-06-18 08:37:05 +00:00

Pull request closed

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!7
No description provided.