KiwiRange Linux Creating a (chroot) virtual environment for whole Linux system

Creating a (chroot) virtual environment for whole Linux system

People introduced on Python may know what a python virtual environment is. You can use them for installing python and PIP modules on a isolated environment. But what happen when you want a virtual environment not only for Python but for the whole system and APT packages?

Imagine you want to install a lot of build tools and development libraries for a compilation. Using APT on your system, will mess all your packages and waste a lot of space. You will need luck erasing all those packages after the compilation.

That is where virtual environments take place to solve your day.

Step 1: Setting up system tools

Sadly, I have to say that you need to install some packages on your system before continue. These are the needed tools for creating the virtual environments. And once you create one, you will no need to install a package in your system anymore (at least not needed package).

For this task you will need GNU “chroot” tool. This tool is what will let you enter in the virtual environment and change your root directory. By default, this command is included in most Linux distributions inside core utils package. You can check it by typing:

$ chroot --version

Then, for installing a minimal OS and create the virtual environment around it, you need the “schroot” and “debootstrap” applications. On Debian systems you can install the with:

$ apt install schroot debootstrap

Schroot (aka secure chroot) is an application above GNU chroot intended for let non-root users to use chroot to enter as non-privileged in the virtual environments. Also add new and improved features to the GNU tool.

The special capability of this tool is that allow users to work in their user directory without the need to copy files inside the virtual environment. Also, maintains the mask and privileges of the user as well as every created file will be owned by him.

The package debootstrap is a tool for installing (bootstrap) basic and minimal Debian systems inside a target directory.

Step 2: Configuring a virtual environment

Once the tools are installed, let’s create and define what will be our virtual environment. Open the file “/etc/schroot/schroot.conf” and define an entry like this one:

description=Ubuntu Focal Fossa for development

In the first line, between brackets you have the name of the virtual environment entry (in my case “focal-devel”. Then, you have the description for the environment and the aliases to call it (you can use them instead of the name).

Then you have the type (a directory) and the users and groups list that are allowed to schroot onto that virtual environment. Finally there are other parameters as the groups that can enter as root or the personality of the environment.

Step 3: Installing the virtual environment OS

Now it’s time to install the operating system inside the virtual environment. This will be done using the debootstrap tool.

$ debootstrap --variant=buildd --arch=amd64 focal /virtenv/devel/

With this command, we are installing Ubuntu Focal Fossa inside “/virtenv/devel/” directory. You specify the system by his code-name.

There are three variants: minbase, buildd and fakechroot. In this case, we are going to install the buildd version which comes with the build-esential package for compiling. However, the minbase, which includes only the minimal packages and apt should be sufficient.

By default, installed system will have the same architecture as the host OS. You can specify the installation architecture with the arch attribute. In this example, as my system is 64 bits, I will proceed with the amd64 version.

Step 4: Mount special filesystems

As a Linux user, you must know that there are special filesystems mounted as directories on the OS that are linked to the host hardware and kernel manage. Those are:

  • /proc
  • /sys
  • /dev

This special filesystems must be mounted to the virtual environment before chroot to them. As those file systems are already mounted on the host OS, so we are going to bind them into the virtual environment directories.

$ sudo mount --bind /dev /virtenv/devel/dev
$ sudo mount --bind /sys /virtenv/devel/sys
$ sudo mount --bind /proc /virtenv/devel/proc

Step 5: Other configuration of the virtual environment

This step is optional and you can just jump into the step 7 and enter on the devel system. However, I recommend performing some actions for having a fully working environment.

First of all, for being able to access all network hosts and stored IPs, you must copy the hosts file.

$ cp /etc/hosts /virtenv/devel/etc/hosts

The virtual environment OS is a clean system. When you chroot to it, the IP and ifaces are still configured form host system but the nameservers not, so you also must copy the resolv.conf file.

$ cp /etc/resolv.conf /virtenv/devel/etc/resolv.conf

Also a another thing you should do is adding the APT repositories for installing new software and any wanted application as in a normal system you will do. This repositories are for Ubuntu Focal. For other suites, you can google search for repositories or get them from a working full installation.

deb focal universe
# deb-src focal universe
deb focal-updates universe
# deb-src focal-updates universe

deb focal multiverse
# deb-src focal multiverse
deb focal-updates multiverse
# deb-src focal-updates multiverse

deb focal-backports main restricted universe multiverse
# deb-src focal-backports main restricted universe multiverse

deb focal-security main restricted
# deb-src focal-security main restricted
deb focal-security universe
# deb-src focal-security universe
deb focal-security multiverse
# deb-src focal-security multiverse

Remember this repositories are dependent of the distribution and major version your have installed.

Step 6: Marking the prompt

In order to have well identified the virtual environment system, I recommend to change the prompt of the shell. This way, we add a tag to identify that we are inside the devel virtual environment. This is done by the PS1 environment variable.

By default, Debian systems set the PS1 variable with a parameter that detects if file “/etc/debian_chroot” exists (because we are on a chrooted environment) and add the contents of the file in the PS1 variable.

You can use this command to set the PS1 variable:

export PS1='${debian_chroot:+\[\033[0;31m\][VirtEnv->$debian_chroot] }\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] \$ '

Or another version with a more advanced prompt:

export PS1='${debian_chroot:+\[\033[0;31m\][VirtEnv->$debian_chroot] }\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\][\[\033[0;35m\]\#\[\033[00m\]\$ '

The PS1 variable defines the prompt of the shell. We are appending this export in the root “bashrc” file in order to set this variable every time the root user logs in. You can personalize it as you want using this guide.

If you want to make persistence to this prompt, you can add the command line into the end of the user “.bashrc” file.

Remember to mark the environment by writing the name of the VirtEnv into the “/etc/debian_chroot” file of the virtual environment file system.

$ sudo echo -n "devel" >/virtenv/devel/etc/debian_chroot

Step 7: Enter the (matrix) virtual environment

Now, you are ready to enter in the virtual environment we defined before. As a root user, you can enter using chroot, but schroot allows the non-root users defined in step 2 to enter in the devel environment (the user maddox).

Warning: When you use schroot, by default it maps the current user directory onto the virtual environment, making you able to access all your files when working inside the VirtEnv. Remember that your user home directory is shared, so be aware of any write you do.

To continue, just type the following line from you user prompt. The name of the virtual environment is defined by the alias parameter in the schroot configuration file.

$ schroot -c devel

If you type this command from the user maddox, you will enter the environment as the maddox non privileged user. A notable thing to consider is that when you enter

Despite if you do it as root, you will enter as the fully privileged root user. That’s why schroot is more secure, as it preserve all limits and privileges of the calling user. Root user directory will never be shared with the virtenv, but the sudoer user will be.

You can still using the common GNU chroot command to enter as root on the virtual environment, but it’s not recommended. Must use sudo or be logged as root to use it and no home is shared.

$ chroot /virtenv/devel

Step 8: (Optional) Install some common tools inside VirtEnv

As it is a minimal system, it doesn’t come with network tools like ping, or IP tools. So, in order to install them, you can run a basic APT install command:

$ apt update
$ apt install ping iproute2

It can be a tricky job, because if you don’t have internet connection inside the virtual environment, you can not install these tools and you can not debug what the problem is. However, if you have an established connection on the host machine and you copied the “hosts” and the “resolve.conf” files, you should be able to access Internet easily.

Enable sudo inside virtual environment

For being able to escalate privileges inside the virtual environment, we need to install the sudo tool inside it, otherwise, we will have to exit the chroot every time we wanted to perform sudo actions. For installing sudo, just run the following command as root inside environment:

$ apt install sudo

Once installed, every user on “sudo” group will be able to run sudo commands just like Ubuntu defaults. NOTE: groups are inherited from host system.

Step 9: Exit and close the virtual environment

It’s true that you can exit the bash session opened inside the virtual environment by typing “exit” command, but that’s not everything to fully close it.

As we did early, we mounted the special file systems (dev, proc and sys) into the virtual environment root directory. In order to be able to erase or modify without risk of damage our host and fully close the VirtEnv, we must unmount those mount points.

Just execute the following commands and everything done:

$ sudo umount /virtenv/devel/dev
$ sudo umount /virtenv/devel/sys
$ sudo umount /virtenv/devel/proc

EXTRA: List all suites available for bootstrap

There are a plenty of suites that can be deployed with “debootstrap” command but no implemented way to list them. So here we have a long command that can be executed directly:

DEBOOTSTRAP_DIR="/usr/share/debootstrap" && [ -d $DEBOOTSTRAP_DIR ] && ls -1 $DEBOOTSTRAP_DIR/scripts && unset DEBOOTSTRAP_DIR

But in a pro way, you can add this option directly on the debootstrap script (line 442) so you can always watch all available suites easily.

In this commit report for modifying the debootstrap command to add the “–list-suite” options, it make use of advanced list management of BASH interpreter:

	echo -n "Available debootstrap suites: "
	for suite in ${file[@]}
	    echo -n "$suite " | sed -e 's/.*\///g'
	echo ""
	exit 0

The problem is that debootstrap uses the SH interpreter, and lists are not implemented on it, so we can modify it to just work with SH this way:

	echo -n "Available debootstrap suites: "
	file=$(ls -1 "$DEBOOTSTRAP_DIR/scripts/" | tr '\n' ' ')
	echo "$file"
	exit 0

Finally, you can add some reference info for this parameter in the help function of this script (Line ~96) and in the man file of debootstrap, but this is up to you.

--list-suites          display all available suites to download and exit


Some of the needed command where obtained from this DigitalOcean post and this other post from

Here also we have a schroot guide for configuring a profile to use X11 applications and a wiki entry for Schroot of how it handles the prompt text (PS1 variable).

Commit report of the modification of debootstrap to add a list-suites option.

What is the “debian_chroot” parameter of PS1 environment variable:

Leave a Reply

Your email address will not be published. Required fields are marked *