Hello! I believe the attached AppArmor profile should work. You need to:
1. Drop it in /etc/apparmor.d/guix (it’s actually not specific to ‘guix shell -C’ since it matches any ‘guix’ command!). 2. Run “apparmor_parser -rv /etc/apparmor.d/guix”. And then you can check “guix build whatever” and “guix shell -C hello”. Note that AppArmor is stateful: it memorizes previous rules (“profiles”) and it’s not entirely clear how to remove them, especially when there’s no profile name. So perhaps you’ll want to reboot if in doubt. Anyway, I tested it in an Ubuntu 24.04 VM and everything seemed to work well. If you can confirm, we can add it to the repo and have ‘guix-install.sh’ install it. Ludo’.
abi <abi/3.0>, include <tunables/global> profile guix /gnu/store/{*-guix-command,*/bin/guix} flags=(attach_disconnected) { include <abstractions/base> include <abstractions/consoles> include <abstractions/nameservice> capability net_admin, # for "guix shell -CN" capability sys_admin, # for clone capability sys_ptrace, # for user namespaces # Allow preparing file systems inside the container root mount fstype=(devpts) none -> /tmp/guix-directory.*/dev/pts/, mount fstype=(mqueue) options=(nodev, noexec, nosuid, rw) mqueue -> /tmp/guix-directory.*/dev/mqueue/, mount fstype=(proc) options=(nodev, noexec, nosuid, rw) none -> /tmp/guix-directory.*/proc/, mount fstype=(sysfs) options=(nodev, noexec, nosuid, ro) none -> /tmp/guix-directory.*/sys/, mount fstype=(tmpfs) none -> /tmp/guix-directory.*/**, mount fstype=(tmpfs) none -> /tmp/guix-directory.*/, mount fstype=(tmpfs) options=(nodev, noexec, nosuid, rw) tmpfs -> /tmp/guix-directory.*/dev/shm/, mount fstype=(tmpfs) options=(noexec, rw, strictatime) none -> /tmp/guix-directory.*/dev/, mount options=(bind, rw) /** -> /tmp/guix-directory.*/**, mount options=(rbind, relatime, remount, ro) -> /tmp/guix-directory.*/**/, mount options=(rbind, relatime, remount, ro) -> /tmp/guix-directory.*/**, mount options=(rbind, rw) /** -> /tmp/guix-directory.*/**, umount /real-root/, pivot_root, # 'guix substitute' is responsible for deduplicating files that it downloads # so it needs to be able to create links in /gnu/store/.links. link /gnu/store/.links/** -> /gnu/store/**, # Note: This also needs to provide permissions for 'guix substitute', # which accesses /etc/guix/acl, /var/guix, /gnu/store/.links, etc. /etc/nsswitch.conf r, /etc/passwd r, /gnu/store/** r, /gnu/store/**/** r, /gnu/store/*-guix-*/etc/ld.so.cache r, /gnu/store/*-guix-*/libexec/guix/guile ix, /gnu/store/*/bin/* mrix, /gnu/store/*/lib/**.so** mr, /gnu/store/*/lib/lib*.so* mr, /gnu/store/*/libexec/** ix, /gnu/store/*/sbin/* mrix, /tmp/ rw, /tmp/guix-directory** rw, /var/guix/** r, /var/guix/daemon-socket/socket rw, @{PROC}/*/ns/net rw, @{PROC}/*/ns/user rw, @{PROC}/@{pid}/** rw, @{PROC}/self/ rw, @{PROC}/self/** rw, @{PROC}/sys/kernel/unprivileged_userns_clone rw, # These are permissions inside the container after pivot root owner / w, owner /bin/ w, owner /bin/sh w, owner /etc/ w, owner /etc/group w, owner /etc/group.* r, owner /etc/group.* w, owner /etc/hosts w, owner /etc/passwd rw, owner /etc/passwd.* r, owner /etc/passwd.* w, owner /home/*/* ra, owner /home/*/.cache/guix/profiles/ r, owner /home/*/.cache/guix/profiles/* w, owner /home/*/.cache/guix/profiles/last-expiry-cleanup r, owner /real-root/ w, allow userns, }