I’m trying to reform how I do backups and the idea was to start using btrfs receive/send and to do everything from inside containers. It sounded straightforward enough, but I seem to be running into all kinds of issues…
(I’m using alpine 3.15 as the host and running lxd 4.22)
So far I have a priviledged container (idmap: both 0 0) and I’ve added the devices to it
lxc profile create privileged
lxc profile edit privileged <<'EOF'
description: "Map the root user to the host one (which is exactly as safe as it sounds)"
config:
raw.idmap: both 0 0
EOF
lxc launch images:alpine/3.15/cloud test -p default -p privileged
lxc exec test -- apk add btrfs-progs
mkfs.btrfs -m raid1 -d raid1 -L 'Data' /dev/sdb1 /dev/sdc1
lxc config device add test btrfs-control unix-char path=/dev/btrfs-control
lxc config device add test sdb unix-block path=/dev/sdb
lxc config device add test sdb1 unix-block path=/dev/sdb1
lxc config device add test sdc unix-block path=/dev/sdc
lxc config device add test sdc1 unix-block path=/dev/sdc1
lxc restart test
At this point I can read from (and I assume write to) from the devices
# lxc exec test -- sh -c 'dd if=/dev/sdb1 bs=1 count=32 | base64'
32+0 records in
32+0 records out
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
I thought I should be all set at this point, but it turns out I am still unable to mount or to run btrfs device scan
# lxc exec test -- su -c 'mount /dev/sdb1 /mnt'
mount: permission denied (are you root?)
# lxc exec test -- su -c 'btrfs device scan'
Scanning for Btrfs filesystems
ERROR: device scan failed on '/dev/sdc1': Operation not permitted
ERROR: device scan failed on '/dev/sdb1': Operation not permitted
ERROR: there were 2 errors while registering devices
I’m not sure whether my approach is wrong or whether what I plan to do is plain impossible… can you help me out?
I suspect there are kernel restrictions that apply as soon as you run inside of a user namespace, so having the real root user mapped through may not be enough.
You may need to actually use security.privileged=true along with raw.apparmor=mount, to allow for direct mounting.
Though an alternative here may be to:
Drop that privileged profile entirely
Set security.syscalls.intercept.mount=true
Set security.syscalls.intercept.mount.allowed=btrfs
Restart the instance
This may then allow for the mount call to work fine.
It seems to work with (just) security.privileged=true. Thanks!
The apparmor may be necessary if apparmor is instaled (tried installing it and adding raw.apparmor=mount and it worked - didn’t try the inverse).
The two security.syscalls settings don’t seem to have any effect one way or another.
If I wanted to understand more amout this topic, would just diving deeper into the lxd docs be enough or would you recommend I read on cgroups (or something else)?
In this case, it’s mostly a user namespace thing more than cgroups.
The user namespace comes with a lot of security restrictions as any user can set one up.
Privileged containers on the other hand have very little security restrictions. They can be quite dangerous as a result though.
The interception bits allow for unprivileged containers to get temporary elevated privileges mediated by LXD on the host so it can be a viable alternative to having to make the whole thing privileged.
And indeed, the apparmor bits wouldn’t apply here as your host distro and kernel doesn’t support it.