Chapter 10. Creating root level directories and symlinks at runtime with image mode for RHEL
As a privileged user, you can create dynamic, top-level mountpoints at runtime while the filesystem remains read-only by default by using the transient-ro option. This is useful for applications that require bind-mount host paths that can be platform-specific or dynamic.
This feature addresses the following use cases:
- Applications that require specific, absolute host paths for bind-mounts.
-
Platforms that require specific mountpoints, for example,
/users. - Requirement to create dynamic mountpoints after deployment, but before an application starts.
- A security requirement to keep the root filesystem read-only for all regular processes.
10.1. Working of the transient-ro true option Copy linkLink copied to clipboard!
Enable the transient-ro=true option in Red Hat Enterprise Linux bootc images to implement stateless deployments. This configuration directs file system writes to temporary storage, discarding runtime changes upon system reboot.
The following workflow describes the boot process changes:
transient-ro=truemounts theoverlayfsupper directory inread-onlymode by default.-
With this, a privileged process, such as
rootor asystemdservice, can remount the root filesystem asread-write, but only within a new, private mount namespace.
-
With this, a privileged process, such as
- Within the private namespace, the process can perform changes, such as creating new top-level directories to serve as mountpoints.
- The mountpoints persist for the current boot, but do not persist through reboots or upgrades.
-
All other regular processes on the system continue to see the original, unmodified,
read-onlyroot filesystem.
For security reasons, only privileged users (root) can create these mountpoints:
- The mountpoints are transient and do not persist across reboots.
-
The filesystem remains
read-onlyfor non-privileged processes.
Because of a limitation in util-linux, you must set the LIBMOUNT_FORCE_MOUNT2=always environment variable when you perform mount operations with the transient-ro option. This variable affects the mount namespace functionality that transient-ro requires.
10.2. Creating dynamic mountpoints with transient-ro Copy linkLink copied to clipboard!
As a root user, you can use the bootc root.transient-ro feature to build a transient overlay on top of the root file system that is read-only by default, create dynamic top-level mountpoints, and remount the filesystem as read-write when needed.
When using the root.transient-ro feature, to ensure applications can properly access host directories and create necessary mountpoints on read-only filesystems, several considerations apply:
- Applications need to bind-mount host directories that match the host’s absolute paths.
-
Platform-specific mountpoints are required, such as
/Userson macOS. - Creation of dynamic mount points after deployment but before application startup.
-
The filesystem remains
read-onlyfor regular processes.
Prerequisites
-
The
container-toolsmeta-package is installed.
Procedure
Create a
transient-root-example.serviceservice to create the directory withreadandwritepermissions. In the following example,/etc/afsexists.[Unit] Description=Transient Root Example - Dynamic Mount Point Creation After=local-fs.target ConditionPathExists=/etc/afs DefaultDependencies=no [Service] Type=oneshot RemainAfterExit=yes MountFlags=slave # LIBMOUNT_FORCE_MOUNT2=always is required for mount command compatibility # See: https://github.com/util-linux/util-linux/issues/3171 Environment=LIBMOUNT_FORCE_MOUNT2=always ExecStart=/usr/bin/bash -c "echo 'Transient root example: Detected /etc/afs, remounting root as read-write'; mount -o remount,rw /; mkdir -p /afs; echo 'Created /afs directory for AFS mount point'" [Install] WantedBy=multi-user.targetAdd the following configuration to the ContainerFile:
# Copy the systemd service unit that demonstrates dynamic mount point creation # The service will: # 1. Check for existence of /etc/afs (ConditionPathExists) # 2. Use MountFlags=slave for proper mount propagation # 3. Set LIBMOUNT_FORCE_MOUNT2=always for mount command compatibility # 4. Remount root as read-write and create /afs directory when triggered COPY transient-root-example.service /usr/lib/systemd/system/ # Enable the service to start automatically on boot RUN systemctl enable transient-root-example.serviceTo enable the
transient-rooption during the container build process, create the following configuration to the/usr/lib/ostree/prepare-root.conffile inside the image:RUN echo -e '[root]\ntransient=true' > /usr/lib/ostree/prepare-root.conf && \ set -x; kver=$(cd /usr/lib/modules && echo *); dracut -vf /usr/lib/modules/$kver/initramfs.img $kverNoteWhen you make changes to the file system configuration, you must regenerate the initramfs image.
Build the bootc image with the transient root file system:
$ podman build --cap-add SYS_ADMIN -t transient-root-ro:test .This adds the
SYS_ADMINcapability thatbootcrequires forostreeoperations during the build.
Verification
Verify that
transient-ro = trueconfiguration file was correctly set in the built image:$ podman run --rm transient-root-ro:test cat /usr/lib/ostree/prepare-root.confYou can see an output similar to the following:
[root] transient-ro = trueOn the running system, verify the runtime functionality:
- Boot the image.
Create the
/etc/afstest directory.$ sudo mkdir -p /etc/afsRestart the service to trigger dynamic mount point creation:
$ systemctl restart transient-root-example.serviceThe service remounts root as
read-writeand creates the/afsdirectory.
To test the functionality without a
systemdservice, create a test directory as root on the running system:$ sudo export LIBMOUNT_FORCE_MOUNT2=always $ sudo unshare -m -- /bin/sh -c 'mount -o remount,rw / && mkdir /transient-test'Verify if the directory was created:
$ sudo ls -d /transient-test /transient-testVerify the
read-onlystatus for other processes by attempting to write to the root filesystem:$ touch /another-test-file touch: cannot touch '/another-test-file': Read-only file system