Linux / Unix: chroot Command Examples

chroot command

I am a new Linux and Unix user. How do I change the root directory of a command? How do I change the root directory of a process such as web-server using a chroot command to isolate file system? How do I use a chroot to recover password or fix the damaged Linux/Unix based environment?

Each process/command on Linux and Unix-like system has current working directory called root directory of a process/command. You can change the root directory of a command using chroot command, which ends up changing the root directory for both current running process and its children.[donotprint]

chroot command details
DescriptionChange root directory
Root privilegesYes
Est. reading time30m
Table of contents
[/donotprint]A process/command that is run in such a modified environment cannot access files outside the root directory. This modified environment is commonly known as “jailed directory” or “chroot jail”. Only a privileged process and root user can use chroot command. This is useful to:

  1. Privilege separation for unprivileged process such as Web-server or DNS server.
  2. Setting up a test environment.
  3. Run old programs or ABI in-compatibility programs without crashing application or system.
  4. System recovery.
  5. Reinstall the bootloader such as Grub or Lilo.
  6. Password recovery – Reset a forgotten password and more.


The chroot command changes its current and root directories to the provided directory and then run command, if supplied, or an interactive copy of the user’s login shell. Please note that not every application can be chrooted.


The basic syntax is as follows:

chroot /path/to/new/root command


chroot /path/to/new/root /path/to/server


chroot [options] /path/to/new/root /path/to/server

chroot command examples

In this example, build a mini-jail for testing purpose with bash and ls command only. First, set jail location using mkdir command:
$ J=$HOME/jail
Create directories inside $J:
$ mkdir -p $J
$ mkdir -p $J/{bin,lib64,lib}
$ cd $J

Copy /bin/bash and /bin/ls into $J/bin/ location using cp command:
$ cp -v /bin/{bash,ls} $J/bin
Copy required libs in $J. Use ldd command to print shared library dependencies for bash:
$ ldd /bin/bash
Sample outputs: =>  (0x00007fff8d987000) => /lib64/ (0x00000032f7a00000) => /lib64/ (0x00000032f6e00000) => /lib64/ (0x00000032f7200000)
	/lib64/ (0x00000032f6a00000)

Copy libs in $J correctly from the above output:
$ cp -v /lib64/ /lib64/ /lib64/ /lib64/ $J/lib64/
Sample outputs:

`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'

Copy required libs in $J for ls command. Use ldd command to print shared library dependencies for ls command:
$ ldd /bin/ls
Sample outputs: =>  (0x00007fff68dff000) => /lib64/ (0x00000032f8a00000) => /lib64/ (0x00000032f7a00000) => /lib64/ (0x00000032fda00000) => /lib64/ (0x00000032fbe00000) => /lib64/ (0x00000032f7200000) => /lib64/ (0x00000032f6e00000)
	/lib64/ (0x00000032f6a00000) => /lib64/ (0x00000032f7600000) => /lib64/ (0x00000032f9600000)

You can copy libs one-by-one or try bash shell for loop as follows:

list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
for i in $list; do cp  -v "$i" "${J}${i}"; done

Sample outputs:

`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'
`/lib64/' -> `/home/vivek/jail/lib64/'

Finally, chroot into your new jail:
$ sudo chroot $J /bin/bash
Try browsing /etc or /var:
# ls /
# ls /etc/
# ls /var/

A chrooted bash and ls application is locked into a particular directory called $HOME/$J and unable to wander around the rest of the directory tree, and sees that directory as its “/” (root) directory. This is a tremendous boost to security if configured properly. I usually lock down the following applications using the same techniques:

  1. Apache – Red Hat / CentOS: Chroot Apache 2 Web Server
  2. Nginx – Linux nginx: Chroot (Jail) Setup
  3. Chroot Lighttpd web server on a Linux based system
  4. Chroot mail server.
  5. Chroot Bind DNS server and more.

How do I exit from chrooted jail?

Type exit
$ exit
Sample session from above commands:

Animated gif 01: Linux / Unix: Bash Chroot ls Command Demo

Animated gif 01: Linux / Unix: Bash Chroot ls Command Demo

Find out if service in chrooted jail or not

You can easily find out if Postfix mail server is chrooted or not using the following two commands:

pid=$(pidof -s master)
ls -ld /proc/$pid/root

Sample outputs from my Linux based server:

lrwxrwxrwx. 1 root root 0 Mar  9 11:16 /proc/8613/root -> /

The PID 8613 pointing out to / (root) i.e. the root directory for application is not changed or chrooted. This is a quick and dirty way to find out if application is chrooted or not without opening configuration files. Here is another example from chrooted nginx server:

pid=$(pidof -s master)
ls -ld /proc/$pid/root

Sample outputs:

lrwxrwxrwx 1 nginx nginx 0 Mar  9 11:17 /proc/4233/root -> /nginxjail

The root directory for application is changed to /nginxjail.

Rescue and fix software RAID system with chroot

I’m assuming that software RAID based Linux system is not booting. So you booted system either using the Live CD or networked based remote rescue kernel mode to fix the system. In this example, I booting RHEL based system using live Linux DVD/CD and chroot into /dev/sda1 and/or /dev/md0 to fix the problem:

## Recover data, at live cd prompt type the following commands. ##
## /dev/sda1 main system partition ##
## /dev/md0 /data partition  ##
# Set jail dir 
mkdir $d
# Mount sda1 and required dirs 
mount /dev/sda1 $d
mount -o bind /dev $d/dev
mount -o bind /sys $d/sys
mount -o bind /dev/shm $d/dev/shm
mount -o bind /proc $d/proc
# Mount software raid /dev/md0 
mount /dev/md0 $d/data
# Chroot to our newly created jail. This allows us to fix bootloader or grab data before everything goes to /dev/null
chroot $d
# Can you see?
# Get files to safe location
rsync -avr /path/to/my_precious_data_dir
# Get out of chrooted jail and reboot or format the server as per your needs ;)
umount {dev,sys,[...],}

But wait, there’s more!

See all other chroot command related examples on nixCraft:

  1. Ubuntu: Mount Encrypted Home Directory (~/.private) From an Ubuntu Live CD
  2. Linux Configure rssh Chroot Jail To Lock Users To Their Home Directories Only
  3. Fix a dual boot MS-Windows XP/Vista/7/Server and Linux problem
  4. Restore Debian Linux Grub boot loader

A note about chrooting apps on a Linux or Unix-like systems

Should you use the chroot feature all the time? In the above example, the program is fairly simple but you may end up with several different kinds of problems such as:

  1. Missing libs in jail can result into broken jail.
  2. Complex program are difficult to chroot. I suggest you either try real jail such as provided by FreeBSD or use virtualization soultuon such as KVM on Linux.
  3. App running in jail can not run any other programs, can not alter any files, and can not assume another user’s identity. Loosen these restrictions, you have lessened your security, chroot or no chroot.

Also note that:

  1. Do not forgot, to updated chrooted apps when you upgrade apps locally.
  2. Not every app can or should be chrooted.
  3. Any app which has to assume root privileges to operate is pointless to attempt to chroot, as root can generally escape a chroot.
  4. Chroot is not a silver bullet. Learn how to secure and harden rest of the system too.

chroot command options

From the chroot(8) command man page:

  --userspec=USER:GROUP  specify user and group (ID or name) to use
  --groups=G_LIST        specify supplementary groups as g1,g2,..,gN
      --help     display this help and exit
      --version  output version information and exit
See also
  • chroot(8) Linux/Unix command man page
  • Man pages – chroot(2)
  • OpenBSD documentation – See Apache chrooting faq for more information.

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 10 comments so far... add one

CategoryList of Unix and Linux commands
Disk space analyzersdf ncdu pydf
File Managementcat tree
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
10 comments… add one
  • autarch princeps Mar 9, 2014 @ 18:16

    You should really have a look at lxc. I’ve tried it on Fedora. It even comes with scripts to initialize a minimum Fedora or Debian inside a container. You can just install the necessary libraries and software using the package manager.

  • Prasad Mar 10, 2014 @ 3:25

    Best document on chroot. Thanks for sharing.

  • Mesut Tasci Mar 10, 2014 @ 16:06

    How you make this gif?

  • Kettu Mar 17, 2014 @ 20:57

    I see some similarities between Docker and chroot, although they are made for quite different purposes.

  • Sebastien Dec 23, 2014 @ 14:34

    list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"

    I would recommend:

    JAIL="$(pwd)" #-- if you run this in your jail directory
    echo -n "Give command name to seach libs for: "
    read bashcmd
    [ ! -e "$bashcmd" ] && echo "$bashcmd command not found. Abording." && exit
    list="$(ldd $bashcmd | egrep -o ' /.*/lib.*\.[0-9]* '|sed 's/ //g')"
    for i in $list; do cp -v "$i" "$JAIL${i}"; done

  • Christian Feb 16, 2015 @ 9:18

    Enhancement for your loop to copy the bash and ls dependencies:

    for i in $list; do cp -v --parents "$i" "${J}"; done

    What it does:
    It copies the whole directory structure of the dependencies so you won’t get an error if a subfolder like $HOME/jail/lib/x86_64-linux-gnu/ doesn’t exist.

  • Faron May 14, 2015 @ 21:46

    Aren’t we supposed to `chdir` a folder first before ‘chroot’-ing it as it will tighten holes in chroot environment?

  • Diromedes Malta Jul 13, 2015 @ 21:47

    Very useful. Thanks.

  • ceneblock Jun 15, 2016 @ 20:17

    There are other options that will automate this for you. I’m personally fond of debootstrap.

  • sameer.oak Sep 13, 2017 @ 9:16

    a marvelously written document. indeed, very useful for experts and newbies too.
    thank you very much for your contribution.

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum