How to create a chroot jail in WSL2 step by step

Last update: 27/08/2025
Author Isaac
  • Chroot isolates processes by changing their file root to a directory.
  • The jail requires binaries and libraries copied with the help of ldd.
  • It can be used for testing, confined services and recovery.
  • In WSL2 it works the same, with practical nuances of routes and mounts.

Chroot Guide in WSL2

Creating a chroot jail in WSL2 It is a simple and powerful way to isolate processes within your distro. Linux en Windows (enable developer mode in Windows 11), ideal for testing without fear of breaking anything. Although it is not a virtual machine or a container, properly configured it allows you to limit the scope of commands and applications to a specific directory tree.

In the next lines you will find a detailed, step-by-step guide which integrates classic Linux chroot practices (copying binaries and dependencies with ldd, mounting /proc, /dev, and /sys when necessary, adjusting the prompt, etc.) along with useful nuances and shortcuts in WSL2. You'll see typical uses, limits you should be aware of, and various ways to enter the jail depending on your situation.

What is a chroot cage and when is it best to use it?

Concept of chroot

The chroot command changes the file system root of a process to a directory of your choice; from that point on, that process "believes" that its/is the cageIn practice, it is used for several very useful scenarios:

  • Test Sandbox to run suspicious or untrustworthy programs without affecting the rest.
  • Isolate network services, such as an FTP server or even a web server, limiting what you can see and touch.
  • Restricted environments on devices or systems where users should only have a minimal set of functions.
  • System Recovery: You boot from a LiveCD, chroot into the damaged system, and repair it from within.

Before creating the cage, there is a golden rule to follow: Inside the chroot you must place everything you are going to use (binaries, libraries, configuration files, and, if applicable, pseudo-systems like /proc, /dev, and /sys mounted with bind). If a utility is not available in the jail, it will not work.

Key requirements and concepts before starting

Chroot Requirements

To work with chroot on any Linux (including a distro within WSL2) you need privileges of root. In WSL2 you can log in as root by running on Windows: wsl -d YourDistroName -u root, or elevating to root within the session with su – if you have it configured.

Furthermore, it should be understood that chroot is not an absolute security solution: It isolates you at the file system level, but it's not equivalent to a robust sandbox like containers with namespaces/cgroups. Still, for the cases described above, it's incredibly practical and quick to set up.

Lastly, remember that Not all daemons and programs work well in chrootSome expect system structures, sockets, or services that aren't present. Among the classic troublemakers is sendmail, for example.

  Hotmail Opening Sessions - How to Close Outlook / Hotmail?

Basic example: a jail in /opt/chroot_dir to run ls

Basic chroot example

Let's start with a simple example: create a jail in /opt/chroot_dir where we can run ls (and bash), copying the libraries they need. This applies equally to WSL2 and any standard Linux distro.

Identify binary dependencies with ldd. It's very convenient to view bash and ls at the same time:

ldd /bin/bash /bin/ls

You will see output similar to the following, indicating which dynamic libraries need to be copied into the jail: libtinfo.so.6, libdl.so.2, libc.so.6, the ld-linux dynamic loader, etc. An example of what you could get:

linux-gate.so.1 => (0x0013c000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2

Next, create the directory structure and copy binaries and libraries into the jail. Adapt routes according to your system (ldd gives you the exact clues):

mkdir -p /opt/chroot_dir/{bin,lib,lib64,usr/lib}
cp /bin/bash /opt/chroot_dir/bin/
cp /bin/ls   /opt/chroot_dir/bin/
cp /lib/x86_64-linux-gnu/libtinfo.so.6 /opt/chroot_dir/lib/
cp /lib/x86_64-linux-gnu/libdl.so.2    /opt/chroot_dir/lib/
cp /lib/x86_64-linux-gnu/libc.so.6     /opt/chroot_dir/lib/
cp /lib64/ld-linux-x86-64.so.2         /opt/chroot_dir/lib64/

It's not mandatory, but you can customize the prompt within the chroot to instantly recognize it. For example, affix the PS1 with a catchy prefix:

echo "PS1='JAULA $ '" | sudo tee /opt/chroot_dir/etc/bash.bashrc

Enter the cage launching bash as the initial process:

chroot /opt/chroot_dir /bin/bash

From that moment on, everything you run inside will be limited to the /opt/chroot_dir tree; will not affect processes outside the cage and if any dependencies are missing, you'll know right away because the binary won't start.

Per-user jail: login script and minimal structure in /home

Cage per user

Another approach is to prepare a cage specific to a specific userImagine you want to confine the user pajaro to /home/pajaro, with access to bash and basic utilities like ls and cp.

First, create the user (from root):

su -
adduser pajaro
passwd pajaro

Next, set up a “wrapper” shell that launches the chroot upon entry. Edit /bin/cage with your favorite editor and put this content:

vim /bin/jaula
#!/bin/bash
/usr/sbin/chroot /home/pajaro /bin/bash

Give execution permissions to the script so that it can be used as a shell. It is essential for usermod to accept it:

chmod a+x /bin/jaula

Now, create the basic directory structure within the user's home directory and prepare dependencies. Remember that Depending on the architecture you may need lib64 in addition to lib:

mkdir -p /home/pajaro/{bin,lib,lib64,usr/lib}

Inspect bash dependencies and copy everything you need as indicated by ldd:

ldd /bin/bash
cp /bin/bash /home/pajaro/bin/
cp /lib/x86_64-linux-gnu/libtinfo.so.6 /home/pajaro/lib/
cp /lib/x86_64-linux-gnu/libdl.so.2    /home/pajaro/lib/
cp /lib/x86_64-linux-gnu/libc.so.6     /home/pajaro/lib/
cp /lib64/ld-linux-x86-64.so.2         /home/pajaro/lib64/

It also includes common utilities such as ls and cp and their libraries. Confirm with ldd which files you should take:

cp /bin/ls /home/pajaro/bin/
cp /bin/cp /home/pajaro/bin/
ldd /bin/ls
ldd /bin/cp

To have the user enter the cage directly upon login, assign your default shell:

usermod -s /bin/jaula pajaro

Ready: when bird logs in, will land inside the /home/pajaro chroot and will work with the minimal set of tools you have copied.

  Windows Startup: Fix Synaptics touchpad disabled

Using chroot with specific IDs: –userspec and checking /etc/passwd

chroot with userspec

Sometimes you might want to enter the jail as a specific UID and GID, for example for testing permissions. With chroot you can do this using –userspec=UID:GID.

First, identify the target user IDs by looking at / Etc / passwd; you can use grep to help you locate it quickly:

cat /etc/passwd | grep ${usuario}

Fields are separated by colons, and The third and fourth fields correspond to UID and GID, respectively. With those values ​​in hand, run chroot specifying the desired jail and IDs. For example, if the jailed user has UID 1002 and GID 1003 and your jail is located at /usr/src/jail:

chroot --userspec=1002:1003 /usr/src/jaula/

If when trying to log in you see an error indicating that bash is not found inside the cage, this indicates that you haven't yet copied the binary and its libraries to the jail structure. Repeat the ldd process on /bin/bash and /bin/ls and move the dependencies to their proper locations.

System Recovery: Chrooting from a Live CD

Recovery with LiveCD and chroot

Another very common situation is to use chroot to repair a system installed on disk booting first with a Live CD. This allows you to log in as if you had booted normally, but from the live environment.

The generic steps would be:

  1. Create a working directory where you will mount the target file system.
  2. Mount the root partition of the system you want to repair (for example, /dev/sda1).
  3. Bind mount /proc, /dev and /sys to make the tools work properly inside the chroot.
  4. Run chroot to the mount directory.
mkdir /media/jaula
mount /dev/sda1 /media/jaula
mount --bind /proc /media/jaula/proc
mount --bind /dev  /media/jaula/dev
mount --bind /sys  /media/jaula/sys
chroot /media/jaula

The –bind option causes the same file system is accessible at both points, preserving the environment necessary for commands such as apt, update-initramfs or editors to function normally within the chroot.

Useful features if you work in WSL2

A lightweight VMIn WSL2, you run Linux inside a lightweight VM, but all the previous steps apply almost the same. Here are some practical tips that will make your life easier in this environment and that fit in with what we've already seen:

  • Log in as root quickly: From Windows, use wsl -d YourDistro -u root to open a direct root session and mount your jail without hindrance.
  • Routes and montages: if you need access Windows files, remember that they are under /mnt/c, /mnt/d, etc. It is not usual to mount them inside the chroot, but you can do so if your case requires it.
  • /proc, /sys and /dev: When preparing a jail to run system tools within WSL2, you can use mount –bind as in the LiveCD section to get things working.
  • Scripts and shells: The pattern of creating /bin/jail and assigning it with usermod -s works the same in WSL2; just make sure you have copied binaries and libraries by checking ldd as usual and create scripts in bash adequate.
  How to fix the "Try connecting your device" error in Windows 11

Although WSL2 offers isolation from Windows, The chroot cage operates within the distro itselfIf you're looking for stronger isolation at the kernel level, consider supplementing it with specific containers or sandboxes or reviewing how configure WSL2 with custom kernel.

Extensions, limits and tricks for a more complete cage

If the jail is not enough for you, in Debian you can use debootstrap to jailbreak a complete system within a directory, so it looks very similar to a minimal installation. It's a very clean way to have a self-sufficient environment within your distro, even in WSL2.

Remember the nuance already mentioned: Not all services are chroot-ready without additional configurations (paths, sockets, status files, etc.). Sendmail is a classic example. For modern services, a container or a systemd-nspawn service may be more beneficial if you need something very close to a mini-system.

A custom that helps to avoid confusion is leave the shell prompt clearly marked inside the cage (as we did with PS1) and place logs and configurations in consistent paths. This way, whether you log in with chroot –userspec or via the /bin/jail shell, you'll always know you're in.

To get out of the cage just run exit in the bash session you started with chroot; you'll be returned to your normal environment immediately, with no side effects if you've copied only the necessary parts.

If you want to add more commands to the cage, repeat the pattern: Locate the binary you need, examine its dependencies with ldd, and copy everything to the equivalent paths within the jail. Binaries usually go to bin or usr/bin; libraries to lib or lib64, depending on the application.

Upon completion, you'll have a caged environment where you can run specific utilities, isolate simple services, or perform administrative tasks without fear of messing up your main system. With WSL2 the experience is just as direct and very convenient for testing on Windows without setting up heavy VMs.

Setting up a development environment with Windows Subsystem for Linux
Related article:
Setting up a development environment with WSL on Windows