The chroot Technique – a Swiss army multitool for Linux systems
122 comments
·April 9, 2025seba_dos1
thatcherc
> you can even chroot into foreign CPU architectures, which is a handy thing to have when you mount your phone's eMMC
This sounds very interesting! What's the scenario where you'd do this? Would you be, for example, emulating an ARM processor with qemu on an x86 computer and chrooting into Android on an eMMC?
benou
Here is an example of preparing a debian ARM image on x86 with debootstrap, qemu and chroot:
~# sudo apt install qemu-user-static debootstrap
~# mkdir /tmp/arm
~# debootstrap --foreign --arch=armhf buster /tmp/arm http://deb.debian.org/debian
~# cp /usr/bin/qemu-arm-static /tmp/arm/usr/bin/
~# chroot /tmp/arm # from that point, you're running ARM!
~# /debootstrap/debootstrap --second-stage
seba_dos1
These days (with recent kernels) you don't even have to copy the qemu binary into the rootfs nor use a static binary - these used to be workarounds for things that kernel now handles on its own.
fsniper
This is very cool! I had no idea you could chroot into different architectures.
bitbang
I've done this to build custom RPi images. Way faster than trying to build on a low power ARM platform, and way less fragile than cross compilers.
jlundberg
Same here, and it is blazingly fast for me running on a M2 macbook air using macOS built in virtulization framework to run an arm64 Debian.
Probably even faster on Asahi Linux, but having both macOS and a fast Debian at the same time is soo neat :)
tonyarkles
Yeah, that’s how we customize the NVidia Orin BSP before flashing it. Untar the rootfs onto a fast x86-64 machine, chroot into it, and use qemu-user to run a bunch of Arm commands and build some stuff. Way easier than trying to set up a cross-compiler toolchain.
messe
I've done this on some tinker boards we use at work.
systemd-nspawn is a great tool for this.
jeroenhd
chroot can be a alternative to setting up fussy cross-compilers. It'll be slower, but that slowness pays off as long as you spend less time on extra CPU cycles than you do on getting cross compilers to work.
It's also useful for reverse-engineering router/IoT firmware.
seba_dos1
I used it with Debian on my phone, but yes.
fragmede
yeah exactly that. your laptop is x86 and your phone or raspberry pi or other hardware is not.
declan_roberts
Indeed you can skip most of the unnecessary additional mount requirements with systemd-nspawn. If /dev/sde1 (your root partition) is mounted to /tmp/rescue just run:
systemd-nspawn --directory /tmp/rescue --boot -- --unit rescue.target
It should automatically find the boot partition and mount it as well.
kristianp
Of course you don't need it, but if you're into docker images, docker or podman can be configured to use QEMU when running a container too.
jasongill
This brings back memories - I owned a large web hosting company and we had thousands of machines. When hardware issues came up, or machines wouldn't boot, using this method was our first line of defense - we'd boot the machine from a burned copy of "Recovery Is Possible" which was an all-in-one Linux distro for recovery, then mount the partitions and chroot in to figure out what is going on - or use rsync to migrate data off as needed.
Just looked and it looks like "Recovery Is Possible" hasn't been updated in a dozen years which dates my story, but I fondly remember overnight phone calls from panicked new sysadmins and telling them to be calm and "RIP it and get chrooted in" and then waking up to help them troubleshoot.
woleium
System Rescue is what i use these days, but to be honest i can’t recall using it in the last couple of year. Virtualization and containers have taken over.
jimmaswell
I use my Gentoo installation usb when this comes up
gerdesj
System Rescue used to be Gentoo based and then switched to Arch. You can install both Arch and Gentoo with SR and obviously you can install Arch with a Gentoo install CD and vice versa.
SR also has some rather handy SAM database editing facilities. Mount Windows at /mnt and then enable and reset the Administrator password. Jolly handy for getting super duper user access on a Windows box.
Its been a while since I installed Gentoo but you can probably quite easily add more stuff to your Gentoo install CD. I don't know if Gentoo have added a script to do all the bind mounts but "arch-chroot /bin/bash" is very convenient. I used to forget about /sys.
nurettin
Hetzner also chroots you into a recovery linux and mounts your drive for access. Same thing different scale.
dicroce
I actually wish that instead of docker & etc we had just gotten a better chroot... Or maybe just a new kernel syscall that is chroot()++.
alphazard
There seems to be a fundamental mismatch between how sane people think about sandboxing, and how linux manages namespaces.
A linux-naive developer would expect to spawn a new process from a payload with access to nothing. It can't see other processes, it has a read only root with nothing in it, there are no network devices, no users, etc. Then they would expect to read documentation to learn how to add things to the sandbox. They want to pass in a directory, or a network interface, or some users. The effort goes into adding resources to the sandbox, not taking them away.
Instead there is this elaborate ceremony where the principal process basically spawns another version of itself endowed with all the same privileges and then gives them up, hopefully leaving itself with only the stuff it wants the sandboxed process to have. Make sure you don't forget to revoke anything.
kccqzy
> a read only root with nothing in it
A lot of things break if there's no /proc/self. A lot more things break if the terminfo database is absent. More things break if there's no timezone database. Finally, almost everything breaks if the root file system has no libc.so.6.
When you write Dockerfiles, you can easily do it FROM scratch. You can then easily observe whether the thing you are sandboxing actually works.
> no users
Now you are breaking something as fundamental as getuid.
alphazard
The modern statically linked languages (I'm thinking of Go and Zig specifically) increasingly need less and less of the cruft you mentioned. Hopefully, that trend continues.
> no users
I mean running as root. I think all processes on Linux have to have a user id. Anything inside a sandbox should start with all the permissions for that environment. If the sandbox process wants to muck around with the users/groups authorization model then it can create those resources inside the sandbox.
rootnod3
That is pretty much what jails are in FreeBSD, especially thin jails.
vacuity
Or capabilities. Additive security has been known for decades; Linux really dropped the ball here. Linux file descriptors (open file descriptions, whatever) are close to a genuine capability model, except there's plenty of leakage where you can get at the insecure base.
duped
> Instead there is this elaborate ceremony where the principal process basically spawns another version of itself endowed with all the same privileges and then gives them up
The flags to unshare are copies of clone3 args, so you're actually free to do this. There's some song and dance though, because it's not actually possible to exec an arbitrary binary will access to nothing.
But I think the big discrepancy is that there is inherently a two step process to "spawn a new process with a new executable." Doesn't work that way - you clone3/fork into a new child process, inheriting what you will from the parent based on the clone args/flags (which could be everything, could be nothing), do some setup work, and then exec.
foresto
> There seems to be a fundamental mismatch between how sane people think about sandboxing, and how linux manages namespaces.
What bothers me most about sandboxing with linux namespaces is that edge cases keep turning up that allow them to trick the kernel into granting more privileges than it should.
I wonder if Landlock can/will bring something more like FreeBSD jails to the table. (I haven't made time to read about it in detail yet.)
alfiedotwtf
This is why I would still rather isolate using QEMU, docker, or Virtually Box rather than a very think chroot-like environment
mytailorisrich
I believe this is because on POSIX systems the only way to create a new process is fork().
adrian_b
There is the later added posix_spawn, which could be implemented with a system call, even if on Linux it is emulated with clone + exec.
posix_spawn can do much, but not all, of what is possible with clone + exec. Presumably the standard editors have been scared to add too complex function parameters for its invocation, though that should not have been a problem if all parameters had reasonable default values.
nesarkvechnep
Come to FreeBSD, we have just that - jails.
masom
yup! FreeBSD jails are essentially what OP wants with chroot++.
I was pretty puzzled when Docker and LXC came around as this whole new thing believed to have "never been done before"; FreeBSD had supported a very similar concept for years before security groups were added in Linux.
Jails and ezjail were stellar to make mini no-overhead containers when running various services on a server. Being able to archive them and expand them on a new machine was also pretty cool (as long as the BSD version was the same.)
danieldk
this whole new thing believed to have "never been done before";
Nobody with knowledge of sandboxing believed this, Virtuozzo and later OpenVZ had been on Linux for a long time after all. Virtuozzo was even from a similar time frame as FreeBSD jails (2000-ish).
The key innovation of Docker was to provide a standardized way to build, distribute, and run container images.
tonyarkles
Solaris Zones too. Absolute magic, many years before Docker and friends.
VWWHFSfQ
Or DragonFlyBSD with vkernels
devrandoom
We kind of did but its all put in the context of containers. Check out the unshare command.
unshare --mount
Most examples you'll find put it in the context of containers, like https://www.redhat.com/en/blog/mount-namespaces
paulddraper
Apples and oranges.
Among many other things, Docker (and Podman etc) has
1. Images and OverlayFS
2. Networking
3. User namespace mappings
4. Resource management
---
If all you want is file system isolation, then docker (and postman, etc) is massive overkill chroot is correct.
paulddraper
*podman, etc
IshKebab
Plan9 had a proper solution for this. New processes don't get access to any files by default - you have to explicitly mount directories for them, capability style.
Shame Plan9 blew its weirdness budget.
teddyh
It has nothing to do with weirdness; Unix itself was plenty weird for its time. The relevant difference between Unix™ and Plan 9 is that Unix source code was given away (or cheaply licensed) to hardware companies which all wrote their own operating systems on top (SunOS, Ultrix, HP-UX, etc. etc.). This made Unix the common factor of very many commercial workstation environments. Plan 9? It was sold directly as a commercial product, for no hardware platform in particular. Nobody wanted to buy it.
People liked Unix because it was free – either really free, via BSD, or as a Unix derivative provided at no cost when people bought their workstations. A new revolutionary operating system had absolutely no reason for anybody to buy it: No commercial developers wanted to develop to a platform without users, and no users wanted a platform without software.
Plan 9 only changed their license many years later, when it was too late for anybody to care, and Unix had become the established standard.
anthk
rfork it's easy :D
gnuser
Pids and cgroups all the way down (also why the wise greybeards rejected docker)
aidanhs
As a number of comments have noted, there are a bunch of different axes that chroot could be 'better' on - e.g. security and sandboxing.
I wrote https://github.com/aidanhs/machroot (initially forked from bubble wrap) a while ago to lean into the pure "pretend I see another filesystem" aspect of chroot with additional conveniences (so no security focus). For example, it allows setting up overlay filesystems, allows mounting squashfs filesystems with an overlay on top...and because it uses a mount namespace, means you don't need to tear down the mount points - just exit the command and you're done.
The codebase is pretty small so I just tweaked it with whatever features I needed at the time, rather than try and make it a fully fledged tool.
(honestly you can probably replicate most of it with a shell script that invokes unshare and appropriate mount commands)
SuperNinKenDo
systemd-nspawn is probably what you want.
smallpipe
The arch linux install has a little wrapper around chroot, used to configure the installed system without booting it.
znpy
Gentoo’s stage3 would like to say a word
slicktux
I remember first installing Gentoo…printed the whole manual and followed along. After a failed attempt and second successful install I learned enough to know that I could use a LiveUSB of my choosing and chroot into the install. Good times!
adrian_b
On Gentoo, it is also simple to install a completely new system in a chroot environment, even if it is intended for a computer with a different, but compatible architecture.
This is frequently very convenient if you want to install Gentoo by compiling everything from sources on a cheap and small computer, e.g. one with some Intel Atom CPU.
Instead of compiling anything on the resource-constrained computer, you install a fresh Gentoo system for it, in a chroot environment on a fast desktop computer, which supports a superset of the ISA of the small computer, so you can still execute the programs intended for the target computer.
Then you just copy the installation result over the SSD/HDD of the destination computer. If you have many identical computers, you can copy the installed Gentoo over all of them without any problems, removing the need for multiple installations.
If desired, you can keep the chroot environment with the installation result and perform any later updates on it. Then you synchronize the updated Gentoo from the chroot with the one or more target computers.
whalesalad
Debian's debootstrap would also like to participate in this discussion
glitchcrab
Debootstrap is for installing a minimal system into a dir from another running system (so only useful in the setup phase), whereas arch-chroot is used to access an already installed system (e.g. when booting off a USB stick to fix something). They're not the same thing. The debootstrap-like tool in arch is called pacstrap.
mystified5016
Manjaro has the same, I'd assume inherited from arch and modified.
I just wish the script could figure out a BTRFS drive without me manually mounting volumes :(
out-of-ideas
i was very happy when that arch-chroot + pacstrap simplified my arch setup not having to run those mounts (i remember doin the same setup process for arch for centos/rhel just to not use anaconda and removing bloat, or rather installing what i wanted)
for btrfs, if you use a consistent volume mapping on your systems, its pretty easy. in arch setup i typically enable ssh and have a pretty simple set of bashisms for target device, compression, and mount points. then its copy-pasta since its a boiler plate for when i need to recover or fresh install
not glanced at manjaro so not familiar with its install-methods
acheong08
I've actually used this to unbrick my laptop before. Very useful
amstan
> sudo mkdir /rescue/boot
> sudo mount /dev/nvme0n1p3 /rescue/boot
This is a little extra. What you can generally do is immediatelly after chroot just run 'mount -a' to mount everything from the chroot's fstab. The empty `/boot` probably already exists.
declan_roberts
Good idea!
jimmaswell
I just installed Gentoo from WSL2 this way, on my secondary NVME on my Framework 16. Went without a hitch besides some minor things you need to be aware of:
-the lack of access to efi subsystem from wsl means you need to pass some extra flags to help grub/etc along, and you may need to set it as the boot partition in the bios manually
-you'll have to mount the drive to wsl with `wsl --mount <DiskPath> --bare`, after finding the right DiskPath with `Get-CimInstance -query "SELECT * from Win32_DiskDrive"`, and you might have to offline the disk first in Windows disk manager
samuell
That's pretty incredible, that it works from Windows too!
Now I'm just wondering if it would work from a Linux running in the browser, accessing the USB through WebUSB ;D
a_t48
Currently working on scripts to provision a drive outside of the machine it’s meant to go on using chroot. I’ve so far accidentally unmounted /dev/pts several times from the host system and running docker inside the chroot caused a hard lock. Fun stuff.
yobbo
chroot was (is?) the recommended way of installing gentoo which is pedagogical.
There are various handy (chroot) techniques that are probably considered "old school" now. For example, having a "rescue partition" which can be booted into remotely, and from there reinstall or repair the "main os". This is necessary when repartitioning remotely, for example.
jethro_tell
That’s still how most Linux OS installers install. They just do that for you.
It’s still used for recovery but recovery partitions have kinda gone out of fashion as the ability to consistently boot has gotten better. Additionally, thumb drives and net boot make the partition a little less necessary.
ndsipa_pomu
Used this or at least a very similar technique a few times to fix boot issues.
I've got a version of the mounting command that I think is easier to use:
for f in proc sys dev run dev/pts ; do mount --bind /$f /mnt/$f ; done
Change the "/mnt/$f" to whatever mountpoint that you're using which would be "/rescue/$f" to align with TFA.I don't know what difference it makes to have /run mounted, but once you chroot into the mountpoint you can mount the boot partition etc and run whatever grub or mkinitramfs command you need to fix stuff.
I would leave the /boot mounting to later in the process - after you chroot. This way you can easily check /etc/fstab for where the boot partition lives (or if there is one), so you only need to locate the root partition initially which is generally easy to figure out from the disk sizes.
There's extra steps needed however if the system uses LVM.
Arch-TK
It's kind of funny to see this being called a technique. It has been something I've done so many times to impressive results. To me, it's just something you can do, among a million other things, if you know enough about Linux.
akoboldfrying
"Technique" is a term for "something you can do, among a million other things, if you know enough about X".
wang_li
The tools shouldn't require the use of chroot. It is quite common on Solaris to be able to specify a path that should be considered the root directory for the tool, usually -R. This was super useful in a netboot world using nfs, and also for crash recovery.
If a system is screwed up enough, then a chroot strategy won't work because it relies on the path you are chrooting to to be generally valid and functional. If it's missing libraries you may well be screwed.
artemonster
I can highly recommend: https://github.com/fsquillace/junest
With qemu-user and binfmt you can even chroot into foreign CPU architectures, which is a handy thing to have when you mount your phone's eMMC to fix a hacking session gone wrong.
Though these days you may want to look into things like systemd-nspawn instead of plain chroot.