Make lxc-docker a privileged container: unprivileged can't NFS-mount at all #28

Merged
beatzaplenty merged 1 commits from worktree-fix-container-dns-search-domain into main 2026-07-21 08:50:14 +00:00
Owner

Root cause of the NFS shares never mounting on lxc-docker, found by live-diagnosing the redeployed VMID 105 container after the earlier DNS/FQDN fix (#25, already merged) landed but shares still didn't mount.

The kernel's NFS client filesystem doesn't set FS_USERNS_MOUNT, so mounting NFS from inside any non-init user namespace -- exactly what an unprivileged LXC container's UID-mapped root runs in -- is rejected at the VFS layer with EPERM, regardless of Proxmox's mount=nfs;nfs4 container feature (which only patches the AppArmor layer, confirmed by reading PVE::LXC::make_apparmor_config directly on the node). Confirmed live: TCP to the NFS server's port 2049 succeeds, the server's export table (192.168.2.0/24) matches the container's current IP, and mount.nfs: Operation not permitted fires immediately with no corresponding denial anywhere in the server's own logs -- a kernel-level rejection that no amount of DNS/automount/export tweaking could ever fix.

Fix: modules/platforms/lxc.nix now keys proxmoxLXC.privileged off hostName ("docker" -> true) instead of a blanket false, since modules/build-types/docker.nix is also composed for linode-docker/proxmox-docker, which don't import proxmox-lxc.nix at all -- setting this option there would break their eval. create-proxmox-resource.sh now reads the value back via a new flake_target_lxc_privileged helper instead of hardcoding --unprivileged 1, so the two stay in sync automatically for every lxc-* target.

Validated: nix eval confirms proxmoxLXC.privileged is true only for lxc-docker and false for every other lxc-* target (server/gui/minimal/nix-cache/pxe-boot/tailscale-exit-node/tor-relay), and every affected target's config.system.build.toplevel evaluates cleanly.

Deploy note: privilege level is set at container-creation time, not something a NixOS rebuild alone can change -- VMID 105 will need to be recreated via create-proxmox-resource.sh (which will now correctly pass --unprivileged 0 for this target) rather than just rebuilt in place.

Root cause of the NFS shares never mounting on lxc-docker, found by live-diagnosing the redeployed VMID 105 container after the earlier DNS/FQDN fix (#25, already merged) landed but shares still didn't mount. The kernel's NFS client filesystem doesn't set `FS_USERNS_MOUNT`, so mounting NFS from inside any non-init user namespace -- exactly what an unprivileged LXC container's UID-mapped root runs in -- is rejected at the VFS layer with `EPERM`, regardless of Proxmox's `mount=nfs;nfs4` container feature (which only patches the AppArmor layer, confirmed by reading `PVE::LXC::make_apparmor_config` directly on the node). Confirmed live: TCP to the NFS server's port 2049 succeeds, the server's export table (`192.168.2.0/24`) matches the container's current IP, and `mount.nfs: Operation not permitted` fires immediately with no corresponding denial anywhere in the server's own logs -- a kernel-level rejection that no amount of DNS/automount/export tweaking could ever fix. **Fix:** `modules/platforms/lxc.nix` now keys `proxmoxLXC.privileged` off `hostName` (`"docker"` -> `true`) instead of a blanket `false`, since `modules/build-types/docker.nix` is also composed for `linode-docker`/`proxmox-docker`, which don't import `proxmox-lxc.nix` at all -- setting this option there would break their eval. `create-proxmox-resource.sh` now reads the value back via a new `flake_target_lxc_privileged` helper instead of hardcoding `--unprivileged 1`, so the two stay in sync automatically for every `lxc-*` target. Validated: `nix eval` confirms `proxmoxLXC.privileged` is `true` only for `lxc-docker` and `false` for every other `lxc-*` target (server/gui/minimal/nix-cache/pxe-boot/tailscale-exit-node/tor-relay), and every affected target's `config.system.build.toplevel` evaluates cleanly. **Deploy note:** privilege level is set at container-creation time, not something a NixOS rebuild alone can change -- VMID 105 will need to be recreated via `create-proxmox-resource.sh` (which will now correctly pass `--unprivileged 0` for this target) rather than just rebuilt in place.
beatzaplenty added 1 commit 2026-07-21 08:48:32 +00:00
Make lxc-docker a privileged container: unprivileged can't NFS-mount at all
Check NixOS configurations / eval-hosts (pull_request) Successful in 10m33s
6b09a808ed
The kernel's NFS client filesystem doesn't set FS_USERNS_MOUNT, so mounting
NFS from inside any non-init user namespace -- exactly what an unprivileged
LXC container's UID-mapped root runs in -- is rejected at the VFS layer
with EPERM, regardless of Proxmox's mount=nfs;nfs4 container feature (which
only patches the AppArmor layer). Confirmed live on the redeployed lxc-docker
container: TCP to the NFS server's port 2049 succeeds, the server's export
table matches the container's IP, and mount.nfs: Operation not permitted
still fires immediately with no corresponding denial anywhere in the
server's own logs -- a kernel-level rejection that no amount of DNS/
automount/export tweaking (this branch's earlier commits) could ever fix.

modules/platforms/lxc.nix now keys proxmoxLXC.privileged off hostName
("docker" -> true) rather than a blanket false, since build-types/docker.nix
is also composed for linode-docker/proxmox-docker, which don't import
proxmox-lxc.nix at all -- setting this option there would break their eval.
create-proxmox-resource.sh reads the value back via a new
flake_target_lxc_privileged helper instead of hardcoding --unprivileged 1,
so the two stay in sync automatically for every lxc-* target.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T48qgH3VTvs8wvwj44FEbE
beatzaplenty merged commit e9e2312163 into main 2026-07-21 08:50:14 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No labels
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: beatzaplenty/nixos#28