Files
nix-config-ryan4yin/hardening
Ryan Yin 0d800c4d9c fix(apparmor): attach disconnected paths in the sudo profile
Nix 2.35's root nix-env -- used by nixos-rebuild to set the system profile --
calls saveMountNamespace(), which opens /proc/self/ns/mnt before remounting
the read-only /nix/store writable. Those magic links have no connected path,
so AppArmor cannot match them against any rule and denies the open with
EACCES even in complain mode. The private mount namespace is then never
created and nixos-rebuild aborts with:

  cannot remount "/nix/store" writable: not in a private mount namespace

Adding flags=(attach_disconnected) lets AppArmor re-root those paths on / so
the existing `file /**` rule matches. This also fixes any other sudo'd tool
that needs namespaces (unshare, nsenter, bwrap, ...).

Rolling this out to a host that already has the old profile loaded needs one
deploy with --no-reexec, so the current system's Nix performs nix-env --set
instead of the new system's; after that generation is active, plain
`just niri` works and the Nix version is never rolled back.
2026-10-07 19:39:42 +08:00
..

Linux Hardening

Work in progress.

Application sandboxing (nixpak/bubblewrap) and Linux hardening knowledge for this repository. For the repository security policy, architecture and audit status, see SECURITY.md; for temporary exceptions and known gaps, see WORKAROUNDS.md.

Goal

  • System Level: Protect critical files from being accessed by untrusted applications.
    1. Such as browser cookies, SSH keys, etc.
  • Per-App Level: Prevent untrusted applications(such as closed-source apps) from:
    1. Accessing files they shouldn't.
      • Such as a malicious application accessing your browser's cookies, SSH keys, etc.
    2. Accessing the network when they don't need to.
    3. Accessing hardware devices they don't need.

Current Structure

1. System Level

  • AppArmor (apparmor/): AppArmor profiles and configuration
  • Kernel & process hardening (kernel-hardening.nix): sysctl baseline and unused-module deny list; rationale and verification live in SECURITY.md.

2. Per-App Level

  • Nixpak (nixpaks/): Bubblewrap-based sandboxing for applications
    • Firefox configuration
    • QQ (Chinese messaging app) configuration
    • Telegram Desktop configuration
    • Modular system with reusable components
  • Bubblewrap (bwraps/): Direct bubblewrap configurations
    • WeChat sandboxing configuration

Current Implementation Status

Component Status Notes
AppArmor Profiles 🚧 WIP Basic structure in place
Nixpak Firefox ✅ Active Firefox sandboxing via nixpak
Nixpak QQ ✅ Active QQ application sandboxing
Nixpak Telegram ✅ Active Telegram Desktop sandboxing
Bubblewrap WeChat ✅ Active WeChat specific sandboxing

Directory Structure

hardening/
├── README.md
├── kernel-hardening.nix # sysctl baseline + unused-module deny list
├── apparmor/           # AppArmor security profiles
│   └── default.nix
├── bwraps/            # Direct bubblewrap configurations
│   ├── default.nix
│   └── wechat.nix
└── nixpaks/           # Nixpak application sandboxing
    ├── default.nix
    ├── firefox.nix
    ├── qq.nix
    ├── telegram-desktop.nix
    └── modules/       # Reusable nixpak modules
        ├── custom-policy.nix
        ├── gui-base.nix
        └── network.nix

System Hardening

Application Sandboxing

NOTE

Running untrusted code is never safe, kernel hardening & sandboxing cannot change this; run untrusted code in a VM on an isolated network. The threat model lives in SECURITY.md.

References