https://documentation.ubuntu.com/server/how-to/security/apparmor/
https://git.m-labs.hk/sinara-hw/assembly/src/branch/master/src/sw_sup/setup_build_pc.md#installation
https://forum.m-labs.hk/d/903-can-not-access-to-vivado-when-building-the-artiq
Refer to dodgy ways (completely dissabling Apparmor):
https://www.reddit.com/r/gamemaker/comments/1filv6k/completely_disabling_apparmor_in_ubuntu_for/
https://askubuntu.com/questions/1536716/why-cant-i-disable-apparmor-on-24-04-1
Below is a repeatable “Ubuntu + Nix + bwrap” setup that gets FPGA/Nix builds working without turning AppArmor off system-wide.
What Ubuntu changed: on newer Ubuntu, unprivileged processes can only create user namespaces if they’re confined and their AppArmor profile allows userns,. Otherwise the kernel forces the action into a restrictive fallback profile (unprivileged_userns) and you see errors like setpcap / uid_map denied. (Ubuntu)
Your machine has both:
/usr/bin/bwrap(system)/nix/store/.../bin/bwrap(Nix-provided) — you confirmed at least two store copies
So you need AppArmor coverage for both bwrap locations, plus a “label” for Nix itself.
command -v nix
readlink -f "$(command -v nix)"
command -v bwrap
readlink -f "$(command -v bwrap)"
sudo find /nix/store -type f -path '*/bin/bwrap' -name bwrap 2>/dev/null | head -n 20sudo apt update
sudo apt install apparmor-utils apparmor-profiles apparmor-profiles-extraThat profile is commonly shipped as an “extra” and may not be loaded by default. (apparmor-documentation-c38b15.gitlab.io)
# Link the shipped profile into /etc/apparmor.d (if not already)
if [ -f /usr/share/apparmor/extra-profiles/bwrap-userns-restrict ] && [ ! -e /etc/apparmor.d/bwrap-userns-restrict ]; then
sudo ln -s /usr/share/apparmor/extra-profiles/bwrap-userns-restrict /etc/apparmor.d/bwrap-userns-restrict
fi
# Load/reload it into the kernel
sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrict || \
sudo apparmor_parser -a /etc/apparmor.d/bwrap-userns-restrictImportant: aa-enforce expects an executable path (like /usr/bin/bwrap), not the profile file path. The Ubuntu docs show aa-enforce /path/to/bin. (Ask Ubuntu)
Optional:
sudo aa-enforce /usr/bin/bwrapBecause Nix may call its own bwrap from the store, the /usr/bin/bwrap profile won’t match it. Create this file:
sudo tee /etc/apparmor.d/bwrap-nixstore-userns-restrict >/dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>
# Nix-store bubblewrap attachment.
profile bwrap_nixstore /nix/store/**/bin/bwrap flags=(attach_disconnected) {
allow capability,
allow file rwlkm /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
# Stack a child profile (same idea as the shipped bwrap-userns-restrict).
allow px /** -> bwrap_nixstore//&unpriv_bwrap_nixstore,
include if exists <local/bwrap-userns-restrict>
}
profile unpriv_bwrap_nixstore flags=(attach_disconnected) {
allow file rwlkm /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
allow pix /** -> &unpriv_bwrap_nixstore,
audit deny capability,
include if exists <local/unpriv_bwrap>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/bwrap-nixstore-userns-restrictWhy this works: Ubuntu’s model is “selectively allow userns per application via AppArmor policy” instead of a global on/off switch. (Ubuntu)
Don’t attach to ~/.nix-profile/... (user-writable). Attach to the immutable store path instead (/nix/store/**/bin/nix).
sudo tee /etc/apparmor.d/nix-userns >/dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile nix-userns /nix/store/**/bin/nix flags=(unconfined) {
allow userns,
include if exists <local/nix-userns>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/nix-userns(You generally should not run aa-enforce on this one; flags=(unconfined) is intentional.)
sudo aa-status | grep -E 'bwrap($|//)|unpriv_bwrap|bwrap_nixstore|unpriv_bwrap_nixstore|nix-userns'sudo journalctl -k -b | grep -E 'comm="bwrap"|unprivileged_userns|DENIED' | tail -n 80What you want now:
comm="bwrap"entries should showprofile="bwrap"orprofile="bwrap_nixstore"- you should not see new
profile="unprivileged_userns"DENIED lines forsetpcap/uid_map
This directly demonstrates it wasn’t “magic reloading”: the process is now running under a profile that explicitly allows userns, which is exactly what Ubuntu requires. (Ubuntu)
Run:
sudo journalctl -k -b | grep 'apparmor="DENIED"' | tail -n 50Whatever shows up in comm="..." is the next helper binary you need to label/cover.
Ubuntu’s own docs and community answers often mention the global sysctl (kernel.apparmor_restrict_unprivileged_userns=0) as an “all apps” workaround, but it’s explicitly an all-or-nothing switch and increases attack surface. (Ubuntu)
If you want, paste the output of:
sudo aa-status | grep -E 'bwrap|bwrap_nixstore|nix-userns'and one fresh journalctl -k -b | grep 'comm="bwrap"' | tail -n 10
and I’ll sanity-check that your system is in the “good” state.