[HN Gopher] The chroot Technique - a Swiss army multitool for Li...
___________________________________________________________________
The chroot Technique - a Swiss army multitool for Linux systems
Author : mariuz
Score : 182 points
Date : 2025-04-09 14:12 UTC (8 hours ago)
(HTM) web link (livesys.se)
(TXT) w3m dump (livesys.se)
| smallpipe wrote:
| The arch linux install has a little wrapper around chroot, used
| to configure the installed system without booting it.
|
| https://wiki.archlinux.org/title/Installation_guide#Chroot
| znpy wrote:
| Gentoo's stage3 would like to say a word
| slicktux wrote:
| 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 wrote:
| 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 wrote:
| Debian's debootstrap would also like to participate in this
| discussion
| mystified5016 wrote:
| 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 :(
| acheong08 wrote:
| I've actually used this to unbrick my laptop before. Very
| useful
| seba_dos1 wrote:
| 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.
| declan_roberts wrote:
| 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.
| thatcherc wrote:
| > 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?
| fragmede wrote:
| yeah exactly that. your laptop is x86 and your phone or
| raspberry pi or other hardware is not.
| messe wrote:
| I've done this on some tinker boards we use at work.
|
| systemd-nspawn is a great tool for this.
| bitbang wrote:
| 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.
| benou wrote:
| 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 wrote:
| 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.
| seba_dos1 wrote:
| I used it with Debian on my phone, but yes.
| dicroce wrote:
| 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()++.
| gnuser wrote:
| Pids and cgroups all the way down (also why the wise greybeards
| rejected docker)
| zoobab wrote:
| Working on proot-docker, a bash script on top of skopeo and
| proot:
|
| https://github.com/mtseet/proot-docker
|
| We need more people to improve it!
| nesarkvechnep wrote:
| Come to FreeBSD, we have just that - jails.
| VWWHFSfQ wrote:
| Or DragonFlyBSD with vkernels
|
| https://www.dragonflybsd.org/docs/handbook/vkernel/
| masom wrote:
| 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 wrote:
| _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.
| mystified5016 wrote:
| Isn't LXC more or less an unsupervised chroot in an isolated
| process?
| goku12 wrote:
| Yes. And so is bubblewrap - if security through isolation is
| a priority.
| SuperNinKenDo wrote:
| systemd-nspawn is probably what you want.
| duped wrote:
| what would "better chroot" do?
| goku12 wrote:
| I'm not GP, but if I were to hazard a guess, they want
| something more than just mount space isolation. Something
| akin to BSD jails, without the bells and whistles of OCI
| containers like overlay filesystem, network virtualization,
| resource management, etc.
|
| That requirement is pretty legitimate, since its easier and
| suitable enough for many applications for which we currently
| use OCI containers. For example, isolated builds, development
| environments, sandboxes etc. (I have an isolated build tool
| for Gentoo).
|
| But Linux already has multiple solutions that fit the bill,
| like systemd-nspawn, LXC, bubblewrap, etc. Too bad, they
| aren't as widely known as chroot.
| duped wrote:
| None of those things do what chroot does but many of them
| involve chroot - so I'm still not grasping what "better
| chroot" is, other than "not chroot, but something
| completely different."
|
| It sounds like people want "better exec"
| aidanhs wrote:
| One annoying part of using chroot if you're creating them
| on the fly is teardown - you have to manually invoke
| umount, and also take care to get this right for
| partially created chroots (maybe you detected an error
| after mounting proc, in the process of getting other
| files in place).
|
| This was my original motivation in creating machroot
| (mentioned elsewhere in this thread) and having it use
| namespaces.
| NexRebular wrote:
| what Solaris and now illumos zones do[1]
|
| [1] https://www.usenix.org/legacy/event/lisa04/tech/full_pape
| rs/...
| paulddraper wrote:
| 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 wrote:
| *podman, etc
| devrandoom wrote:
| 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
| alphazard wrote:
| 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.
| mytailorisrich wrote:
| I believe this is because on POSIX systems the only way to
| create a new process is fork().
| adrian_b wrote:
| 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.
| rootnod3 wrote:
| That is pretty much what jails are in FreeBSD, especially
| thin jails.
| duped wrote:
| > 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.
| kccqzy wrote:
| > 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 wrote:
| 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.
| PaulDavisThe1st wrote:
| The things that break in C if /proc/self or the terminfo
| DB are missing will break in Go and Zig too.
|
| What I think you might mean is something like: "in modern
| statically linked applications written with languages
| like Go and Zig, it is much less likely for the them to
| call on OS services that require these sorts of
| resources".
| foresto wrote:
| > 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.)
| udev4096 wrote:
| Docker is not using chroot in any way. Escaping chroot is only
| a matter of calling chdir('..') and poof, you are out of the
| "sandbox"
| aidanhs wrote:
| 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)
| jbverschoor wrote:
| I built https://github.com/jrz/container-shell as a simple
| chroot on docker. I use it for both development and sandboxing.
|
| Besides that I have a simple script that starts an ephemeral
| docker with debian-full + tools.
|
| I also have some scripts that leverage macOS's 'sandbox-exec'
| IshKebab wrote:
| 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.
| anthk wrote:
| rfork it's easy :D
| bigpeopleareold wrote:
| Ah - my attempt at doing this was almost there, except for the
| few bits that kept erroring out because I didn't mount the
| proc,dev,etc. mountpoints correctly :) Something to give another
| whirl on. At the time, I wanted something simple without docker
| to store everything development-related using different
| libraries. This is where debootstrap+chroot comes in - to build
| against various versions of libraries in Debian (if I remember
| correctly - it's been awhile.)
| a_t48 wrote:
| 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.
| miftassirri wrote:
| Haha, learned this technique while installing Void Linux
| ddoolin wrote:
| Chroot has saved my system more times than I care to admit. I
| didn't really understand how it worked though, interesting.
| andreareina wrote:
| This is how Linux From Scratch is done, and I've used the same
| technique to install missing video drivers that the Ubuntu
| install didn't include for whatever reason.
| zokier wrote:
| Sure, chroot can be useful in a pinch, but it would not be the
| first thing I'd reach to. If you got the partitions mounted, you
| can already do quite a lot of things without needing to chroot.
| declan_roberts wrote:
| This is usually right. In this particular case the issue was
| actually in /boot, which might not have been obvious just
| mounting the main partition.
| artemonster wrote:
| I can highly recommend: https://github.com/fsquillace/junest
| wang_li wrote:
| 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.
| remram wrote:
| Creating a mount namespace and using pivot_root seems like a
| safer solution.
| alexgartrell wrote:
| I don't think pivot_root is necessary for something like this,
| but a new mount namespace will definitely help avoid creating a
| mess on accident
| throwway120385 wrote:
| Came here to suggest this. pivot_root has the advantage that it
| can remount the existing root. It's essentially meant for going
| from an initramfs using linuxrc to boot to a full-on init in
| the other root filesystem. If things are horribly broken you
| could use a shell or some other process as init.
| mycall wrote:
| Is there already a wrapper utility to automate all of this
| process laid out in the article?
| JanisErdmanis wrote:
| sudo arch-chroot .
|
| This is now my default tool setting up raspberry like
| computers.
| amstan wrote:
| There is!
|
| arch-chroot [1], despite its name pretty much does all the
| `mount -t proc` stuff the post says. It's also available on
| other distros like debian [2]. I have used it in the past to
| chroot into fedora as well.
|
| [1] https://man.archlinux.org/man/arch-chroot.8 [2]
| https://packages.debian.org/arch-install-scripts
| r4indeer wrote:
| In addition to the other comments: If you are on NixOS, you can
| use nixos-enter [1].
|
| [1] https://wiki.nixos.org/wiki/Change_root
| amstan wrote:
| > 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 wrote:
| Good idea!
| yobbo wrote:
| 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 wrote:
| 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.
| whalesalad wrote:
| This is why Linux and Unix are so awesome. It's really all just
| files.
| sgt wrote:
| Not really, but yes there's a lot of files or things that seem
| to be files. Try plan9 though.
| immibis wrote:
| If you want to blow your mind in what's possible in
| operating-system isolation read about KeyKOS from 1985:
| https://css.csail.mit.edu/6.858/2014/readings/keykos.pdf
|
| Such systems are rarely very pragmatic, but do show off a
| bunch of weird concepts.
| sgt wrote:
| Once I had to rescue a SunOS system and edit /etc/vfstab but I
| only had ed to my disposal. At that point I had never touched ed
| before, so that was a bit of a learning exercise, for sure.
| shagie wrote:
| In a computer lab I hung out in back in college...
|
| We used rcp to keep passwords in sync. Add the account on the
| main machine, rcp the password file to the other machine. sudo
| rcp /etc/password other:/etc/passwd was muscle memory.
|
| One day, someone was getting added to the groups file to be
| able to work in the server web project. sudo rcp /etc/group
| other:/etc/passwd
|
| Ooops. Couldn't log in to fix it.
|
| "Is anyone logged into the other machine?" (someone said yes).
| "Type while 1 sync" ... (ok) ... And we flipped the power
| switch and brought it up in single user mode (since the
| password file was invalid). Next, need to establish a minimal
| /etc/passwd ... emacs /etc/passwd (nope) vi /etc/passwd (nope -
| invalid terminal 300h not in termcap). "Uhm... cat >
| /etc/passwd ?" (possible, but a PITA when there is a typo in
| transcription)
|
| I was a wizard on a lpmud. "I know ed".
|
| And we got a minimal password file restored while reading the
| hashed values over (no way where we going to have root::0:0:...
| as the file even for a second) and then rcp'ed the proper
| /etc/passwd and /etc/group file over to the other machine.
|
| https://www.gnu.org/fun/jokes/ed-msg.txt
| Arch-TK wrote:
| 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.
| jasongill wrote:
| 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 wrote:
| 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.
|
| https://www.system-rescue.org/
| jimmaswell wrote:
| I use my Gentoo installation usb when this comes up
| nurettin wrote:
| Hetzner also chroots you into a recovery linux and mounts your
| drive for access. Same thing different scale.
| jimmaswell wrote:
| 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
| aussieguy1234 wrote:
| What we all know as Docker and containers is really just fancy
| chroot.
|
| On non Linux systems, it's fancy chroot inside a Linux VM.
| immibis wrote:
| Which raises the question of why they need chroot if they have
| the VM.
|
| Another semi-related but equally odd view: Docker is an
| operating system and containers are processes.
|
| The difference between Docker and chroot, by the way, is that
| Docker does a bunch more system calls to ch the root of several
| other things that are not the filesystem. It also sets up
| things inside those roots for you by default, so your
| containers can access the internet, for example.
___________________________________________________________________
(page generated 2025-04-09 23:00 UTC)