Chroot Jail the Apache Web Server in RHEL / CentOS 7 - CentLinux


Sunday, 2 September 2018

Chroot Jail the Apache Web Server in RHEL / CentOS 7

Chroot Jail the Apache Web Server in RHEL/CentOS 7

In Linux, Chroot is an operation to change the apparent root directory i.e. / for a running process and their child processes. The process running in Chroot can not access the files and commands outside that environmental directory tree. This modified environment is called a Chroot Jail.

By chrooting the Apache web server, we do not actually increase the security, rather we limit the access to files and commands by the httpd process and decreases the possible impact, when an Apache web server is compromised. Also potentially dangerous CGI scripts can only access the environmental root directory.

A chroot environment is relatively difficult to set up than a traditional install, especially if we run other software like MySQL, PHP, Python, etc.

In this post, we will set up a chroot jail for Apache Web Server in RHEL/CentOS 7, and create the systemd unit to autostart the httpd service.

Note: All demonstrations in this article are CLI based, therefore, it is recommended that you should have The Linux Command Line: A Complete Introduction for quick reference.


System Specification:

We are using a Linux machine with following specification for this demonstration.

  • Hostname -
  • IP Address -
  • Operating System - RHEL 7.5

Read Also: Installation of CentOS 7 Server


Chrooting Apache Web Server:

Connect to our Linux machine using ssh and create the directory for setting up the chroot jail.

[root@webserver-01 ~]# mkdir -p /chroot/httpd/

We have already configured the local yum repository on the machine. Please refer to my previous article Configure Local Yum Repository using ISO in RHEL 7.

Now, we are installing Apache web server using yum, but in a non-default directory.

[root@webserver-01 ~]# yum install -y httpd --installroot=/chroot/httpd ... Installed: httpd.x86_64 0:2.4.6-80.el7 Dependency Installed: acl.x86_64 0:2.2.51-14.el7 apr.x86_64 0:1.4.8-3.el7_4.1 apr-util.x86_64 0:1.5.2-6.el7 audit-libs.x86_64 0:2.8.1-3.el7 basesystem.noarch 0:10.0-7.el7 bash.x86_64 0:4.2.46-30.el7 binutils.x86_64 0:2.27-27.base.el7 bzip2-libs.x86_64 0:1.0.6-13.el7 ca-certificates.noarch 0:2017.2.20-71.el7 chkconfig.x86_64 0:1.7.4-1.el7 coreutils.x86_64 0:8.22-21.el7 cpio.x86_64 0:2.11-27.el7 cracklib.x86_64 0:2.9.0-11.el7 cracklib-dicts.x86_64 0:2.9.0-11.el7 cryptsetup-libs.x86_64 0:1.7.4-4.el7 curl.x86_64 0:7.29.0-46.el7 cyrus-sasl-lib.x86_64 0:2.1.26-23.el7 dbus.x86_64 1:1.10.24-7.el7 dbus-libs.x86_64 1:1.10.24-7.el7 device-mapper.x86_64 7:1.02.146-4.el7 device-mapper-libs.x86_64 7:1.02.146-4.el7 diffutils.x86_64 0:3.3-4.el7 dracut.x86_64 0:033-535.el7 elfutils-default-yama-scope.noarch 0:0.170-4.el7 elfutils-libelf.x86_64 0:0.170-4.el7 elfutils-libs.x86_64 0:0.170-4.el7 expat.x86_64 0:2.1.0-10.el7_3 filesystem.x86_64 0:3.2-25.el7 findutils.x86_64 1:4.5.11-5.el7 gawk.x86_64 0:4.0.2-4.el7_3.1 glib2.x86_64 0:2.54.2-2.el7 glibc.x86_64 0:2.17-222.el7 glibc-common.x86_64 0:2.17-222.el7 gmp.x86_64 1:6.0.0-15.el7 grep.x86_64 0:2.20-3.el7 gzip.x86_64 0:1.5-10.el7 hardlink.x86_64 1:1.0-19.el7 httpd-tools.x86_64 0:2.4.6-80.el7 info.x86_64 0:5.1-5.el7 keyutils-libs.x86_64 0:1.5.8-3.el7 kmod.x86_64 0:20-21.el7 kmod-libs.x86_64 0:20-21.el7 kpartx.x86_64 0:0.4.9-119.el7 krb5-libs.x86_64 0:1.15.1-18.el7 libacl.x86_64 0:2.2.51-14.el7 libattr.x86_64 0:2.4.46-13.el7 libblkid.x86_64 0:2.23.2-52.el7 libcap.x86_64 0:2.22-9.el7 libcap-ng.x86_64 0:0.7.5-4.el7 libcom_err.x86_64 0:1.42.9-11.el7 libcurl.x86_64 0:7.29.0-46.el7 libdb.x86_64 0:5.3.21-24.el7 libdb-utils.x86_64 0:5.3.21-24.el7 libffi.x86_64 0:3.0.13-18.el7 libgcc.x86_64 0:4.8.5-28.el7 libgcrypt.x86_64 0:1.5.3-14.el7 libgpg-error.x86_64 0:1.12-3.el7 libidn.x86_64 0:1.28-4.el7 libmount.x86_64 0:2.23.2-52.el7 libpwquality.x86_64 0:1.2.3-5.el7 libselinux.x86_64 0:2.5-12.el7 libsemanage.x86_64 0:2.5-11.el7 libsepol.x86_64 0:2.5-8.1.el7 libssh2.x86_64 0:1.4.3-10.el7_2.1 libstdc++.x86_64 0:4.8.5-28.el7 libtasn1.x86_64 0:4.10-1.el7 libuser.x86_64 0:0.60-9.el7 libutempter.x86_64 0:1.1.6-4.el7 libuuid.x86_64 0:2.23.2-52.el7 libverto.x86_64 0:0.2.5-4.el7 libxml2.x86_64 0:2.9.1-6.el7_2.3 lua.x86_64 0:5.1.4-15.el7 lz4.x86_64 0:1.7.5-2.el7 mailcap.noarch 0:2.1.41-2.el7 ncurses.x86_64 0:5.9-14.20130511.el7_4 ncurses-base.noarch 0:5.9-14.20130511.el7_4 ncurses-libs.x86_64 0:5.9-14.20130511.el7_4 nspr.x86_64 0:4.17.0-1.el7 nss.x86_64 0:3.34.0-4.el7 nss-pem.x86_64 0:1.0.3-4.el7 nss-softokn.x86_64 0:3.34.0-2.el7 nss-softokn-freebl.x86_64 0:3.34.0-2.el7 nss-sysinit.x86_64 0:3.34.0-4.el7 nss-tools.x86_64 0:3.34.0-4.el7 nss-util.x86_64 0:3.34.0-2.el7 openldap.x86_64 0:2.4.44-13.el7 openssl-libs.x86_64 1:1.0.2k-12.el7 p11-kit.x86_64 0:0.23.5-3.el7 p11-kit-trust.x86_64 0:0.23.5-3.el7 pam.x86_64 0:1.1.8-22.el7 pcre.x86_64 0:8.32-17.el7 pkgconfig.x86_64 1:0.27.1-4.el7 popt.x86_64 0:1.13-16.el7 procps-ng.x86_64 0:3.3.10-17.el7 qrencode-libs.x86_64 0:3.4.1-3.el7 readline.x86_64 0:6.2-10.el7 redhat-logos.noarch 0:70.0.3-6.el7 redhat-release-server.x86_64 0:7.5-8.el7 rpm.x86_64 0:4.11.3-32.el7 rpm-libs.x86_64 0:4.11.3-32.el7 sed.x86_64 0:4.2.2-5.el7 setup.noarch 0:2.8.71-9.el7 shadow-utils.x86_64 2: shared-mime-info.x86_64 0:1.8-4.el7 sqlite.x86_64 0:3.7.17-8.el7 systemd.x86_64 0:219-57.el7 systemd-libs.x86_64 0:219-57.el7 tar.x86_64 2:1.26-34.el7 tzdata.noarch 0:2018c-1.el7 ustr.x86_64 0:1.0.4-16.el7 util-linux.x86_64 0:2.23.2-52.el7 xz.x86_64 0:5.2.2-1.el7 xz-libs.x86_64 0:5.2.2-1.el7 zlib.x86_64 0:1.2.7-17.el7 Complete! [root@webserver-01 ~]#

Above command will install the Apache Web Server and its dependencies in the /chroot/httpd. You may observe that, it installs many packages that were already installed on the default root /. These packages are reinstalled in /chroot/httpd for the sake of chroot jail setup.

Create some required devices for the chroot environment.

[root@webserver-01 ~]# cd /chroot/httpd/dev [root@webserver-01 dev]# rm -f null [root@webserver-01 dev]# mknod /chroot/httpd/dev/null c 1 3 [root@webserver-01 dev]# mknod /chroot/httpd/dev/random c 1 8 [root@webserver-01 dev]# mknod /chroot/httpd/dev/urandom c 1 9 [root@webserver-01 dev]# ls -al total 0 drwxr-xr-x. 2 root root 47 Sep 2 19:26 . dr-xr-xr-x. 17 root root 224 Sep 2 19:17 .. crw-r--r--. 1 root root 1, 3 Sep 2 19:26 null crw-r--r--. 1 root root 1, 8 Sep 2 19:26 random crw-r--r--. 1 root root 1, 9 Sep 2 19:26 urandom [root@webserver-01 dev]#

Add a default homepage for Apache web server.

[root@webserver-01 dev]# cd /chroot/httpd/var/www/html/ [root@webserver-01 html]# cat >> index.html << EOF > <html> > <head> > <body> > <h1>Apache Homepage from Chroot Jail.</h1> > </body> > </html> > EOF [root@webserver-01 html]#

Allow httpd service to communicate through Firewall.

[root@webserver-01 html]# firewall-cmd --permanent --add-service=http success [root@webserver-01 html]# firewall-cmd --reload success

Configure systemd unit to autostart httpd service. First copy the required configuration files from chroot jail to host environment.

[root@webserver-01 html]# cp /chroot/httpd/etc/sysconfig/httpd /etc/sysconfig/ [root@webserver-01 html]# cp /chroot/httpd/usr/lib/systemd/system/httpd.service /usr/lib/systemd/system/

Now edit the httpd.service unit to start Apache in chrooted environment.

[root@webserver-01 html]# vi /usr/lib/systemd/system/httpd.service

Search and update the following three lines.

Type=simple ExecStart=/sbin/chroot /chroot/httpd /usr/sbin/httpd $OPTIONS -DFOREGROUND ExecReload=/sbin/chroot /chroot/httpd /usr/sbin/httpd $OPTIONS -k graceful

For further clarification, the differences in files after editing are shown below.

[root@webserver-01 html]# diff /chroot/httpd/usr/lib/systemd/system/httpd.service /usr/lib/systemd/system/httpd.service 8c8 < Type=notify --- > Type=simple 10,11c10,11 < ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND < ExecReload=/usr/sbin/httpd $OPTIONS -k graceful --- > ExecStart=/sbin/chroot /chroot/httpd /usr/sbin/httpd $OPTIONS -DFOREGROUND > ExecReload=/sbin/chroot /chroot/httpd /usr/sbin/httpd $OPTIONS -k graceful [root@webserver-01 html]#

Start and enable httpd service.

[root@webserver-01 html]# systemctl daemon-reload [root@webserver-01 html]# systemctl start httpd ; systemctl enable httpd Created symlink from /etc/systemd/system/ to /usr/lib/systemd/system/httpd.service.

Check root directory for running httpd service. First we obtain the PID of the httpd process and then check it’s root directory in the proc folder.

[root@webserver-01 html]# systemctl status httpd â httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled) Active: active (running) since Sun 2018-09-02 20:18:23 PKT; 1min 16s ago Docs: man:httpd(8) man:apachectl(8) Main PID: 10620 (httpd) CGroup: /system.slice/httpd.service ââ10620 /usr/sbin/httpd -DFOREGROUND ââ10639 /usr/sbin/httpd -DFOREGROUND ââ10640 /usr/sbin/httpd -DFOREGROUND ââ10641 /usr/sbin/httpd -DFOREGROUND ââ10642 /usr/sbin/httpd -DFOREGROUND ââ10643 /usr/sbin/httpd -DFOREGROUND Sep 02 20:18:23 systemd[1]: Started The Apache HTTP ... Sep 02 20:18:23 systemd[1]: Starting The Apache HTTP... Hint: Some lines were ellipsized, use -l to show in full. [root@webserver-01 html]# ls /proc/10620/root -al lrwxrwxrwx. 1 root root 0 Sep 2 20:20 /proc/10620/root -> /chroot/httpd [root@webserver-01 html]#

Browse the URL from a client’s browser to verify the httpd service.

Chrooted HTTP Homepage

We have successfuly set up a chroot jail for our Apache Web Server in RHEL/CentOS 7.


  1. One issue... when I tried the initial yum install, I got this error:

    Cannot find a valid baseurl for repo: base/$releasever/x86_64

    When using --installroot=, the variable $releasever isn't populated. The fix is to include --releasever=7 in the command:

    yum install -y httpd --releasever=7 --installroot=/chroot/httpd

    After that it worked perfectly. Thanks!

  2. Hi, its good that you resolve the issue by yourself. But the problem does not related to Chroot, rather it is caused due to the yum configuration. Please refer to Configure Local Yum Repository using ISO in RHEL 7

  3. Hello, thanks a lot, very useful !
    Can you tell how to use php in that configuration please ? Does it need to be installed in the jail ?
    Thanks a lot

    1. There are different ways to install PHP in chrooted environment. It depends upon the user requirement. But if you are following the above article, then it is better that you install PHP in the jail as well.