Prepare the Linux sandbox
For: People installing a server or node.
Set up bubblewrap and the distribution's sandbox profile before starting a Linux node that needs tier 1.
Sandbox tier 1 on Linux
Run as root, both install.sh scripts run orchestrator-zero-node sandbox setup before the node first starts, since a node finds its tier when it starts. On another machine, or after installing by hand, run it yourself:
sudo oz0-node sandbox setup --dry-run # what it would do; needs no root
sudo oz0-node sandbox setup
It does two things, and says each one and how to undo it:
- bubblewrap, when
bwrapis missing, with the distribution's package manager:apt-get,dnf,apkorzypper. - Ubuntu's own AppArmor profile for bwrap, where the kernel lets only AppArmor-profiled programs create user namespaces (
kernel.apparmor_restrict_unprivileged_userns=1, Ubuntu 24.04 and later). Ubuntu 25.04 and later ship that profile,bwrap-userns-restrict, enabled, and setup then changes nothing. On 24.04 the profile is in theapparmor-profilespackage, which setup does not install: its postinst would also enforce about 19 other profiles (dnsmasq,smbd,nmbd,php-fpm,avahi-daemon,nscd,pingand more), which can break those daemons.
Setup downloads the package withapt-get download(apt checks it against the archive's signed indexes), unpacks it withdpkg-deb -xin a temporary directory, copies onlyextra-profiles/bwrap-userns-restrictbyte for byte into/etc/apparmor.dand loads it withapparmor_parser; the apparmor service loads it again at every boot. If you installedapparmor-profilesyourself, setup copies the file from/usr/share/apparmor/extra-profilesinstead.
The profile lets/usr/bin/bwrapcreate the sandbox's namespaces and stacksunpriv_bwrapon everything bwrap starts, which denies every capability.
It ends by running sandbox check as the node's account (oz0-node, or nobody). On a fresh cloud machine, where unattended-upgrades holds apt's locks for the first minutes, it waits up to five minutes for them. sudo oz0-node sandbox setup --undo unloads and removes the profile it copied, which it records in /var/lib/orchestrator-zero-node-sandbox/setup.json; a profile it did not copy (one you put there, one changed since, or the one the apparmor package installs on 25.04 and later) stays.
Before a release upgrade from 24.04 to 25.04 or later, whose apparmor package ships that file itself, run sudo oz0-node sandbox setup --undo (and sandbox setup again after it, which then changes nothing): dpkg otherwise finds a file no package installed where its own goes and asks what to do, and without a terminal that package's upgrade fails.
--no-sandbox-setup keeps either install script away from all of this.
What setup never does, and what you should not do instead:
- It never writes a profile of its own. An unconfined profile for
bwrapthat allowsuserns(some tools install one) lets any local user runbwrap --cap-add ALLand hold every capability in a user namespace, which is the bypass class Qualys reported in Ubuntu's restrictions. Setup warns about such profiles in/etc/apparmor.d, and leaves them to you. - It never changes kernel settings. Setting
kernel.apparmor_restrict_unprivileged_userns=0would work, but lifts the restriction for every program on the machine. On an old Debian withkernel.unprivileged_userns_clone=0, or a machine withuser.max_user_namespaces=0, setup says whichsysctlwould allow user namespaces. - Only
/usr/bin/bwrapis covered: Ubuntu's profile attaches to that path, so a bwrap of your own (OZ0_BWRAP) stays restricted.
A node still at tier 0 is a health finding with the fix it worked out. A node installed as a service of the machine before this release has ProtectKernelTunables and ProtectKernelLogs in its unit, which keep bwrap from mounting a fresh /proc: rewrite the unit with service install again, with the node's own --data-dir and --service-name when it was installed with them (oz0-node sandbox check on the node names both), for example sudo /usr/local/bin/orchestrator-zero-node service install --data-dir /srv/oz0 --service-name oz0-b (Nodes as services).
Run the binary install.sh put in /usr/local/bin, not the service's own copy in <data-dir>/bin: the node's account owns that copy so it can update itself, and the fix never names it.