Chroot: Difference between revisions
mok0>Morten Kjeldgaard Not currently under git control |
mok0>Morten Kjeldgaard Not currently under git control |
||
| Line 1: | Line 1: | ||
<!-- language en --> | <!-- language: en --> | ||
[[de:{{PAGENAME}}]] | |||
[[es:{{PAGENAME}}]] | |||
[[fr:{{PAGENAME}}]] | |||
[[it:{{PAGENAME}}]] | |||
<!-- end of language versions --> | |||
<!-- | {{Warning|This is a launch status check of the wiki migration, you can edit this entry to test things, but it might be deleted at any time, so save it if you want to keep your edits.}} | ||
[[DebianMan:chroot]] is an utility that changes which folder is considered the root of the filesystem hierarchy by its child processes, so that it is impossible for them to access the parent folder of the new root, even though it physically exists on the disk. | [[DebianMan:chroot]] is an utility that changes which folder is considered the root of the filesystem hierarchy by its child processes, so that it is impossible for them to access the parent folder of the new root, even though it physically exists on the disk. | ||
| Line 14: | Line 12: | ||
------- | ------- | ||
= Common use-cases = | = Common use-cases = | ||
| Line 30: | Line 25: | ||
------- | ------- | ||
= Basic setup and usage = | = Basic setup and usage = | ||
''Unless explicitly stated otherwise, all commands in the below subsections require <code>root</code><nowiki> </nowiki>privileges.'' | ''Unless explicitly stated otherwise, all commands in the below subsections require <code>root</code><nowiki> </nowiki>privileges.'' | ||
== Create or provide a file hierarchy of a Linux system == | == Create or provide a file hierarchy of a Linux system == | ||
| Line 44: | Line 35: | ||
* In case of switching to existing installations, it boils down to mounting their root filesystem at a target folder of your choice. | * In case of switching to existing installations, it boils down to mounting their root filesystem at a target folder of your choice. | ||
* In case you want to create a fresh Debian image, you can use utilities such as [[DebianMan:mmdebstrap]], for example to create a clean environment to build deb packages:<pre> | * In case you want to create a fresh Debian image, you can use utilities such as [[DebianMan:mmdebstrap]], for example to create a clean environment to build deb packages: | ||
<pre> | |||
mmdebstrap --skip=output/dev,output/mknod --variant=buildd \ | mmdebstrap --skip=output/dev,output/mknod --variant=buildd \ | ||
trixie "${chrootFolder}" http://deb.debian.org/debian | trixie "${chrootFolder}" http://deb.debian.org/debian | ||
</pre> | </pre> | ||
== Mount virtual filesystems == | == Mount virtual filesystems == | ||
As of 2026 these are <code>proc</code>, <code>sysfs</code>, <code>udev</code> and "children" of the latter 2 of which there are too many and which also tend to die off or spawn way too often. Fortunately, [[DebianMan:mount]] has <code>--rbind</code> option that allows to bind an already mounted filesystem together with all its children to an additional target folder. You need to use either <code>--make-rslave</code> or <code>--make-rprivate</code> flag too (see [[DebianMan:mount_namespaces]] for details). | As of 2026 these are <code>proc</code>, <code>sysfs</code>, <code>udev</code> and "children" of the latter 2 of which there are too many and which also tend to die off or spawn way too often. Fortunately, [[DebianMan:mount]] has <code>--rbind</code> option that allows to bind an already mounted filesystem together with all its children to an additional target folder. You need to use either <code>--make-rslave</code> or <code>--make-rprivate</code> flag too (see [[DebianMan:mount_namespaces]] for details). | ||
<pre> | <pre> | ||
mount -t proc proc "${chrootFolder}/proc" | mount -t proc proc "${chrootFolder}/proc" | ||
| Line 59: | Line 51: | ||
</pre> | </pre> | ||
In case you are wondering: <code>proc</code> has 1 child also: <code>binfmt_misc</code>, which is used for registering binary executable handlers/interpreters, which does not make sense in a <code>chroot</code> (the absolute path of a given interpreter needs to be provided, which is inaccessible from a <code>chroot</code>-ed context), therefore no point in binding it. | In case you are wondering: <code>proc</code> has 1 child also: <code>binfmt_misc</code>, which is used for registering binary executable handlers/interpreters, which does not make sense in a <code>chroot</code> (the absolute path of a given interpreter needs to be provided, which is inaccessible from a <code>chroot</code>-ed context), therefore no point in binding it. | ||
== Copy the DNS resolver config == | == Copy the DNS resolver config == | ||
| Line 66: | Line 57: | ||
cp /etc/resolv.conf "${chrootFolder}/etc/" | cp /etc/resolv.conf "${chrootFolder}/etc/" | ||
</pre> | </pre> | ||
== Perform a chroot switch == | == Perform a chroot switch == | ||
This usually boils down to<pre> | This usually boils down to | ||
<pre> | |||
chroot "${chrootFolder}" | chroot "${chrootFolder}" | ||
</pre> | </pre> | ||
...which will start an interactive login shell of <code>root</code> user inside the <code>chroot</code>-ed environment, so that you can interactively perform whatever tasks you need. | ...which will start an interactive login shell of <code>root</code> user inside the <code>chroot</code>-ed environment, so that you can interactively perform whatever tasks you need. | ||
For non-interactive tasks, you can instead provide an alternative command and its args:<pre> | For non-interactive tasks, you can instead provide an alternative command and its args: | ||
<pre> | |||
chroot "${chrootFolder}" /root/myScriptToBeExecutedInChroot.sh myArg1 myArg2 | chroot "${chrootFolder}" /root/myScriptToBeExecutedInChroot.sh myArg1 myArg2 | ||
</pre> | </pre> | ||
<code>/root/myScriptToBeExecutedInChroot.sh</code> is a path inside the <code>chroot</code>-ed hierarchy. | <code>/root/myScriptToBeExecutedInChroot.sh</code> is a path inside the <code>chroot</code>-ed hierarchy. | ||
== Cleanup == | == Cleanup == | ||
After the <code>chroot</code> process exits, you need to unbind / <code>umount</code> all the virtual filesystems bound / mounted previously. Fortunately <code>umount</code> also has <code>--recursive</code> / <code>-R</code> flag to help with this:<pre> | After the <code>chroot</code> process exits, you need to unbind / <code>umount</code> all the virtual filesystems bound / mounted previously. Fortunately <code>umount</code> also has <code>--recursive</code> / <code>-R</code> flag to help with this: | ||
<pre> | |||
umount -R "${chrootFolder}/dev" | umount -R "${chrootFolder}/dev" | ||
umount -R "${chrootFolder}/sys" | umount -R "${chrootFolder}/sys" | ||
umount -R "${chrootFolder}/proc" | umount -R "${chrootFolder}/proc" | ||
</pre> | </pre> | ||
If <code>${chrootFolder}</code> is a mount point of an external drive and you want to <code>umount</code> it also, you can replace all the above commands with the below single one:<pre> | If <code>${chrootFolder}</code> is a mount point of an external drive and you want to <code>umount</code> it also, you can replace all the above commands with the below single one: | ||
<pre> | |||
umount -R "${chrootFolder}" | umount -R "${chrootFolder}" | ||
</pre> | </pre> | ||
------- | ------- | ||
= Additional notes and scenarios = | = Additional notes and scenarios = | ||
== Running X11 GUI apps == | == Running X11 GUI apps == | ||
| Line 105: | Line 94: | ||
----- | ----- | ||
== Running Systemd services == | == Running Systemd services == | ||
| Line 112: | Line 100: | ||
----- | ----- | ||
== Foreign architectures == | == Foreign architectures == | ||
| Line 119: | Line 106: | ||
----- | ----- | ||
== Modifying boot data == | == Modifying boot data == | ||
| Line 129: | Line 115: | ||
It is usually most convenient to mount these filesystems right after performing a <code>chroot</code> switch. | It is usually most convenient to mount these filesystems right after performing a <code>chroot</code> switch. | ||
After performing a <code>chroot</code> switch, check which filesystem are present by running <code>grep /boot /etc/fstab</code>. Below is an example output from a system with both <code>/boot</code> and <code>/boot/efi</code> entries:<pre> | After performing a <code>chroot</code> switch, check which filesystem are present by running <code>grep /boot /etc/fstab</code>. Below is an example output from a system with both <code>/boot</code> and <code>/boot/efi</code> entries: | ||
<pre> | |||
UUID=7a307683-255a-4bac-937f-95aa2af2ca17 /boot ext4 defaults 0 2 | UUID=7a307683-255a-4bac-937f-95aa2af2ca17 /boot ext4 defaults 0 2 | ||
UUID=4D18-6163 /boot/efi vfat umask=0077 0 1 | UUID=4D18-6163 /boot/efi vfat umask=0077 0 1 | ||
</pre> | </pre> | ||
If <code>/etc/fstab</code> entries use UUIDs as in the example above (which is the default on most modern distros) or unique <code>PARTLABEL</code>s or <code>LABEL</code>s, then all you need to do is to point <code>mount</code> to their corresponding mount-points:<pre> | If <code>/etc/fstab</code> entries use UUIDs as in the example above (which is the default on most modern distros) or unique <code>PARTLABEL</code>s or <code>LABEL</code>s, then all you need to do is to point <code>mount</code> to their corresponding mount-points: | ||
<pre> | |||
mount /boot | mount /boot | ||
mount /boot/efi | mount /boot/efi | ||
| Line 142: | Line 130: | ||
----- | ----- | ||
[[:Category:System]] | [[:Category:Virtualization]] | [[:Category:System]] | [[:Category:Virtualization]] | ||
Revision as of 16:18, 28 September 2026
DebianMan:chroot is an utility that changes which folder is considered the root of the filesystem hierarchy by its child processes, so that it is impossible for them to access the parent folder of the new root, even though it physically exists on the disk.
Common use-cases
chroot utility is intended mostly for an occasional, ad-hoc usage.
If you regularly need different environments, then consider a container runtime like podman instead.
- Fast switching to another environment (distro, version, flavor, package mix etc) for the purposes of testing, building, debugging etc.
- Repairing a broken Linux installation by connecting its primary drive as an external device (for example using an USB enclosure) to some other working system and performing operations from within the system being repaired.
- Historically
chrootwas also used to increase the security of network services running on a given machine: if an attacker managed to trick a service to an arbitrary code execution, he would still not have access to the whole filesystem of the machine (he would remain in a so called chroot jail). This however does not prevent the attacker from using the machine's network interfaces to further penetrate the internal network, moreover on Linux and some other UNIXes, escaping a "chroot jail" is relatively easy. As a result, for security-related purposeschrootwas replaced by virtual machines and containers.
Basic setup and usage
Unless explicitly stated otherwise, all commands in the below subsections require root privileges.
Create or provide a file hierarchy of a Linux system
In the subsequent sections, ${chrootFolder} will refer to the root folder of a file hierarchy created or provided as described below.
- In case of switching to existing installations, it boils down to mounting their root filesystem at a target folder of your choice.
- In case you want to create a fresh Debian image, you can use utilities such as DebianMan:mmdebstrap, for example to create a clean environment to build deb packages:
mmdebstrap --skip=output/dev,output/mknod --variant=buildd \
trixie "${chrootFolder}" http://deb.debian.org/debian
Mount virtual filesystems
As of 2026 these are proc, sysfs, udev and "children" of the latter 2 of which there are too many and which also tend to die off or spawn way too often. Fortunately, DebianMan:mount has --rbind option that allows to bind an already mounted filesystem together with all its children to an additional target folder. You need to use either --make-rslave or --make-rprivate flag too (see DebianMan:mount_namespaces for details).
mount -t proc proc "${chrootFolder}/proc"
mount --rbind --make-rslave /sys "${chrootFolder}/sys"
mount --rbind --make-rslave /dev "${chrootFolder}/dev"
In case you are wondering: proc has 1 child also: binfmt_misc, which is used for registering binary executable handlers/interpreters, which does not make sense in a chroot (the absolute path of a given interpreter needs to be provided, which is inaccessible from a chroot-ed context), therefore no point in binding it.
Copy the DNS resolver config
cp /etc/resolv.conf "${chrootFolder}/etc/"
Perform a chroot switch
This usually boils down to
chroot "${chrootFolder}"
...which will start an interactive login shell of root user inside the chroot-ed environment, so that you can interactively perform whatever tasks you need.
For non-interactive tasks, you can instead provide an alternative command and its args:
chroot "${chrootFolder}" /root/myScriptToBeExecutedInChroot.sh myArg1 myArg2
/root/myScriptToBeExecutedInChroot.sh is a path inside the chroot-ed hierarchy.
Cleanup
After the chroot process exits, you need to unbind / umount all the virtual filesystems bound / mounted previously. Fortunately umount also has --recursive / -R flag to help with this:
umount -R "${chrootFolder}/dev"
umount -R "${chrootFolder}/sys"
umount -R "${chrootFolder}/proc"
If ${chrootFolder} is a mount point of an external drive and you want to umount it also, you can replace all the above commands with the below single one:
umount -R "${chrootFolder}"
Additional notes and scenarios
Running X11 GUI apps
Running X11 GUI apps from within a chroot-ed environment and displaying them on host's X11 server works using standard mechanisms: just export the value of DISPLAY env var from the host in the chroot and make sure the host X server will allow connections (for example using DebianMan:xhost utility).
Running Systemd services
Systemd services will generally refuse to run in a chroot-ed environment. Use systemd-nspawn instead of chroot if you need to run Systemd services.
Foreign architectures
If DebianPkg:qemu-user-binfmt is installed, it is possible to chroot to a filesystem for any foreign arch it supports.
Modifying boot data
If you want to modify the boot data of another system whose drive you chroot-ed into (this includes for example running update-grub, update-initramfs, installing a new kernel or firmware + kernel modules for boot-critical devices etc), you need to mount its /boot hierarchy. This may include the following:
/bootitself is sometimes a separate partition, most commonly on systems using some disk encryption scheme.- On UEFI systems (which includes most of modern x86 and ARM hardware), their ESP partitions are mounted at
/boot/efi.
It is usually most convenient to mount these filesystems right after performing a chroot switch.
After performing a chroot switch, check which filesystem are present by running grep /boot /etc/fstab. Below is an example output from a system with both /boot and /boot/efi entries:
UUID=7a307683-255a-4bac-937f-95aa2af2ca17 /boot ext4 defaults 0 2 UUID=4D18-6163 /boot/efi vfat umask=0077 0 1
If /etc/fstab entries use UUIDs as in the example above (which is the default on most modern distros) or unique PARTLABELs or LABELs, then all you need to do is to point mount to their corresponding mount-points:
mount /boot mount /boot/efi
On some older systems, instead of UUIDs or labels, device nodes may be used in /etc/fstab, like for example /dev/sdaX etc. In such case you need to figure out what device node currently corresponds to a given filesystem. Most commonly, it will be another partition on the same physical drive as the root filesystem of that external system.
After you are done with your chroot work, these filesystems may be umount-ed either from within the chroot or after exiting.