The chroot
command can send you to jail, keep your development or test environments isolated, or just improve your system's security. We show you the easiest way to use it.
You can use chroot
to set up and run programs or interactive shells such as Bash in an encapsulated filesystem that is prevented from interacting with your regular filesystem. Everything within the chroot
environment is penned in and contained. Nothing in the chroot
environment can see out past its own, special, root directory without escalating to root privileges. That has earned this type of environment the nickname of a chroot
jail. The term "jail" shouldn't be confused with FreeBSD'sjail
command, which creates a chroot
environment that is more secure than the usual chroot
environment.
If you try to measure the usefulness of a command, you must take into account the functionality it provides and its ease of use. If it is too complicated for people to use or too long-winded to make them want to try to use it, the functionality might as well be zero. If no one uses it, it doesn't provide any functionality.
In discussions with Linux users — in person and on forums — it seems that the chroot
command is one that is pegged as being difficult to use, or too persnickety and tedious to setup. It seems this terrific utility isn't used as much as it might be.
But actually, there's a very straightforward way to use chroot
, and we're going to give you a specific example of how to use chroot. We're using regular Linux commands which will work on all distributions. Some Linux distributions have dedicated tools to set up chroot
environments, such as debootstrap for Ubuntu, but we're being distro-agnostic here.
A chroot
environment provides functionality similar to that of a virtual machine, but it is a lighter solution. The captive system doesn't need a hypervisor to be installed and configured, such as VirtualBox or Virtual Machine Manager. Nor does it need to have a kernel installed in the captive system. The captive system shares your existing kernel.
In some senses, chroot
environments are closer to containers such as LXC than to virtual machines. They're lightweight, quick to deploy, and creating and firing one up can be automated. Like containers, one convenient way to configure them is to install just enough of the operating system for you to accomplish what is required. The "what is required" question is answered by looking at how you're going to use your chroot
environment.
Some common uses are:
Software Development and Product Verification. Developers write software and the product verification team (PV) tests it. Sometimes issues are found by PV that can't be replicated on the developer's computer. The developer has all sorts of tools and libraries installed on their development computer that the average user — and PV — won't have. Often, new software that works for the developer but not for others turns out to be using a resource on the developer's PC that hasn't been included in the test release of the software. chroot
allows the developers to have a plain vanilla captive environment on their computer that they can sheep-dip the software in before giving it to PV. The captive environment can be configured with the bare minimum dependencies that the software requires.
Reducing Development Risk. The developer can create a dedicated development environment so that nothing that happens in it can mess up his actual PC.
Running Deprecated Software. Sometimes you just have to have an old version of something running. If the old software has requirements that would clash or be incompatible with your version of Linux you can chroot
an environment for the problem software.
Recovery and Filesystem Upgrades: If a Linux installation becomes inoperable, you can use chroot
to mount the damaged filesystem to a mount point on a Live CD. This allows you to work in the damaged system and attempt to fix it as though it were mounted normally at root /. This means the expected file paths within the damaged system will be correctly referenced from the root directory, and not from the mount point of the Live CD. A similar technique was used in the article describing how to migrate the Linux filesystem from ext2 or ext3 to ext4.
Ringfencing Applications. Running an FTP server or other internet-connected appliance inside a chroot
environment limits the damage an external attacker can do. This can be a valuable step in hardening the security of your system.
We need a directory to act as the root directory of the chroot
environment. So that we have a shorthand way of referring to that directory we'll create a variable and store the name of the directory in it. Here we're setting up a variable to store a path to the "testroot" directory. It doesn't matter if this directory doesn't exist yet, we're going to create it soon. If the directory does exist, it should be empty.
chr=/home/dave/testroot
If the directory doesn't exist, we need to create it. We can do that with this command. The -p
(parents) option ensures any missing parent directories are created at the same time:
mkdir -p $chr
We need to create directories to hold the portions of the operating system our chroot
environment will require. We're going to set up a minimalist Linux environment that uses Bash as the interactive shell. We'll also include the touch
, rm
, and ls
commands. That will allow us to use all Bash's built-in commands and touch
, rm
, and ls
. We'll be able to create, list and remove files, and use Bash. And — in this simple example — that's all.
List the directories you need to create within the {}
brace expansion.
mkdir -p $chr/{bin,lib,lib64}
Now we'll change directory into our new root directory.
cd $chr
Let's copy the binaries that we need in our minimalist Linux environment from your regular "/bin" directory into our chroot
"/bin" directory. The -v
(verbose) option makes cp
tell us what it is doing as it performs each copy action.
cp -v /bin/{bash,touch,ls,rm} $chr/bin
The files are copied in for us:
These binaries will have dependencies. We need to discover what they are and copy those files into our environment as well, otherwise bash
, touch
, rm
, and ls
will not be able to function. We need to do this in turn for each of our chosen commands. We'll do Bash first. The ldd
command will list the dependencies for us.
ldd /bin/bash
The dependencies are identified and listed in the terminal window:
We need to copy those files into our new environment. Picking the details out of that listing and copying them one at a time is going to be time-consuming and error-prone.
Thankfully, we can semi-automate it. We'll list the dependencies again, and this time we'll form a list. Then we'll loop through the list copying the files.
Here we're using ldd
to list the dependencies and feed the results through a pipe into egrep
. Using egrep
is the same as using grep
with the -E
(extended regular expressions) option. The -o
(only matching) option restricts the output to the matching parts of lines. We're looking for matching library files that end in a number [0-9]
.
list="$(ldd /bin/bash | egrep -o '/lib.*\.[0-9]')"
We can check the contents of the list using echo
:
echo $list
Now that we have the list, we can step through it with the following loop, copying the files one at a time. We're using the variable i
to step through the list. For each member of the list, we copy the file to our chroot
root directory which is the value held in $chr
.
The -v
(verbose) option causes cp
to announce each copy as it performs it. The --parents
option ensures any missing parent directories are created in the chroot
environment.
for i in $list; do cp -v --parents "$i" "${chr}"; done
And this is the output:
We'll use that technique to capture the dependencies of each of the other commands. And we'll use the loop technique to perform the actual copying. The good news is we only need to make a tiny edit to the command that gathers the dependencies.
We can retrieve the command from our command history by hitting the Up Arrow
key a few times and then make the edit. The looping copy command doesn't need to change at all.
Here we've used the Up Arrow
key to find the command, and we've edited it to say touch
instead of bash
.
list="$(ldd /bin/touch | egrep -o '/lib.*\.[0-9]')"
We can now repeat the exact same loop command as before:
for i in $list; do cp -v --parents "$i" "${chr}"; done
And our files are copied for us:
We can now edit the list
command line for ls
:
list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
Again, we'll use the same loop command. It doesn't care what files are in the list. It blindly works through the list copying the files for us.
for i in $list; do cp -v --parents "$i" "${chr}"; done
And the dependencies for ls
are copied over for us:
We edit the list
command line for the last time, making it work for rm
:
list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
We use the looping copy command one last time:
for i in $list; do cp -v --parents "$i" "${chr}"; done
The last of our dependencies are copied into our chroot
environment. We're finally ready to use the chroot
command. This command sets the root of the chroot
environment, and specifies which application to run as the shell.
sudo chroot $chr /bin/bash
Our chroot
environment is now active. The terminal window prompt has changed, and the interactive shell is the being handled by the bash
shell in our environment.
We can try out the commands that we have brought into the environment.
ls
ls /home/dave/Documents
The ls
command works as we'd expect when we use it within the environment. When we try to access a directory outside of the environment, the command fails.
We can use touch
to create a file, ls
to list it, and rm
to remove it.
touch sample_file.txt
ls
rm sample_file.txt
ls
Of course, we can also use the built-in commands that the Bash shell provides. If you type help
at the command line, Bash will list them for you.
help
Use exit to leave the chroot
environment:
exit
If you want to remove the chroot
environment, you can simply delete it:
rm -r testroot/
This will recursively delete the files and directories in the chroot
environment.
If you're thinking that chroot
environments might be useful to you, but they're a bit fiddly to set up, remember that you can always take the strain and the risk out of repetitive tasks by using aliases, functions, and scripts.
Linux Commands | ||
Files | tar·pv·cat·tac·chmod·grep ·diff·sed·ar·man·pushd·popd·fsck·testdisk·seq·fd·pandoc·cd·$PATH·awk·join·jq·fold·uniq·journalctl·tail·stat·ls·fstab·echo·less·chgrp·chown·rev·look·strings·type·rename·zip·unzip·mount·umount·install·fdisk·mkfs·rm·rmdir·rsync·df·gpg·vi·nano·mkdir·du·ln·patch·convert·rclone·shred·srm·scp·gzip·chattr·cut·find·umask·wc· tr | |
Processes | alias·screen·top·nice·renice·progress·strace·systemd·tmux·chsh·history·at·batch·free·which·dmesg·chfn·usermod·ps·chroot·xargs·tty·pinky·lsof·vmstat·timeout·wall·yes·kill·sleep·sudo·su·time·groupadd·usermod·groups·lshw·shutdown·reboot·halt·poweroff·passwd·lscpu·crontab·date·bg·fg·pidof·nohup·pmap | |
Networking | netstat·ping·traceroute·ip·ss·whois·fail2ban·bmon·dig·finger·nmap·ftp·curl·wget·who·whoami·w·iptables·ssh-keygen·ufw·arping·firewalld |
ncG1vNJzZmivp6x7qbvWraagnZWge6S7zGhrbWllaIFwtM6wZK2nXarApnnToZxmm5invLDAjJympqWRo7Fuu81mo6Kmpa18