This is a read-only archive. Find the latest Linux articles, documentation, and answers at the new!

Feature: Security

Chrooting Apache

By Mike Peters on May 27, 2004 (8:00:00 AM)

Share    Print    Comments   

The chroot daemon allows you to run a program and have it see a given directory as the root (/) directory. This effectively locks the process into its very own filesystem ("chroot jail") isolated from the real / filesystem. In this article we will look at how to install the Apache Web server in such an environment.

Installing Apache in a chroot jail does not make Apache itself any more secure. Rather, it serves to restrict the access of Apache and its child processes to a small subset of the filesystem. The advantage in chrooting a process is not in preventing a breakin, but rather in containing a potential threat.

Before deciding whether you need to chroot your Web server you should consider the advantages and disadvantages of such a setup.


If Apache is compromised, an intruder will have access only to the files within the chroot jail.

Potentially dangerous CGI scripts do not have access to your server's filesystem.

Your Web tree is contained in one area that's easy to back up and move.


A chroot environment is more difficult to set up than a traditional install, especially if you run external software such as Perl, PHP, MySQL, or Python.

The process is only viable if your entire Web tree can exist on a single filesystem.

Compiling and installing the Apache binary

There are no special steps needed to build the Apache binary in order to install it in a chroot jail. The following steps apply equally to a precompiled binary (such as an RPM) or one you have compiled yourself. Starting with a working binary helps with debugging later, if necessary. Just make sure that you are using the latest patched version of the server, install Apache normally, and ensure that it is working as expected.

Finally, make sure you configure Apache to run with its own user and group IDs. Create a user and group with the commands:

# groupadd apache
# useradd -c "Apache Server" -d /dev/null -g apache -s /bin/false apache

These commands create the regular user apache and the apache group. Apache runs as nobody by default. User nobody may be used by many processes, and if it is compromised an intruder will gain access to all processes on your system running under that UID.

Creating the chroot tree

Our chroot jail is a mini-version of the Linux filesystem. I prefer to use a seperate partition mounted as /chroot, with Apache under a directory named httpd on my chroot partition.

# mkdir /chroot/httpd
# mkdir /chroot/httpd/dev
# mkdir /chroot/httpd/lib
# mkdir /chroot/httpd/etc
# mkdir -p /chroot/httpd/usr/sbin
# mkdir /chroot/httpd/usr/lib
# mkdir /chroot/httpd/usr/libexec
# mkdir -p /chroot/httpd/var/run
# mkdir -p /chroot/httpd/var/log/apache
# mkdir -p /chroot/httpd/home/httpd

Now set the permissions on your directory structure:

# chown -R root /chroot/httpd
# chmod -R 0755 /chroot/httpd
# chmod 750 /chroot/httpd/var/log/apache/

Your exact structure may vary slightly depending upon what features of Apache you are using and where the nescessary libraries live on your main file system.

Once you have created the nescessary directories you need to create the null device.

# mknod  /chroot/httpd/dev/null c 1 3
# chown root.sys /chroot/httpd/dev/null 
# chmod 666 /chroot/httpd/dev/null

You need the null device and /chroot/httpd/var/log/httpd/ because, when run in chroot jail, Apache sees the /chroot/httpd directory as the equivalent of /. This means that it cannot access /dev/null or /var/log on the normal filesystem.

Copying the nescessary files

Now shut down Apache, run killall httpd, and you're ready to start copying across the necessary files. Note that some directory names may be different in your case depending upon how you originally installed Apache. First, copy your configuration files:

# cp -r /etc/apache /chroot/httpd/etc/

Next, copy your Apache DocumentRoot and CGI scripts:

# cp -r /home/httpd/html /chroot/httpd/home/httpd/
# cp -r /home/httpd/cgi-bin /chroot/httpd/home/httpd/

Now copy your httpd binary (and, if you use them, the Apache scripts) from /usr/sbin:

# cp /usr/sbin/httpd /chroot/usr/sbin/
# cp /usr/sbin/apache* /chroot/usr/sbin/

If you use mod_ssl you need to copy the /etc/ssl directory and its contents too:

# cp -a /etc/ssl /chroot/httpd/etc/

You should also copy any modules from your original install:

cp -r /usr/libexec/apache /chroot/httpd/usr/libexec/

Once you have copied Apache itself (and ssl if needed) you need to copy all of the shared libraries Apache relies on to run. To find out which libraries you need, execute # ldd /chroot/httpd/usr/sbin/httpd. This should give output something like:

        /lib/ => /lib/ (0x40017000) => /lib/ (0x40037000) => /lib/ (0x40059000) => /lib/ (0x40086000) => /usr/lib/ (0x40096000) => /lib/ (0x400b6000) => /lib/ (0x400b9000)
        /lib/ => /lib/ (0x40000000)

The exact output will depend upon how your httpd binary was built in the first place. Copy the required files to their respective directories in your chroot:

# cp /lib/libsafe* /chroot/httpd/lib/
# cp /lib/libm* /chroot/httpd/lib/
# cp /lib/libcrypt* /chroot/httpd/lib/
# cp /lib/libdb* /chroot/httpd/lib/
# cp /usr/lib/libexpat* /chroot/httpd/usr/lib/
# cp /lib/libdl* /chroot/httpd/lib/
# cp /lib/libc* /chroot/httpd/lib/
# cp /lib/ld-* /chroot/httpd/lib/

You need certain libraries for some standard networking functionality:

# cp /lib/libnss_compat* /chroot/httpd/lib/
# cp /lib/libnss_dns* /chroot/httpd/lib/
# cp /lib/libnss_files* /chroot/httpd/lib/
# cp /lib/libnsl* /chroot/httpd/lib/

The /chroot/httpd/etc configuration files

For Apache to function properly you also need several configuration files from /etc. First, edit the /etc/passwd and /etc/group files. These should contain only entries for the Apache user and group you created earlier. For example:

apache:x:12347:12348:Apache Server:/dev/null:/bin/false


You also need several network configuration files:

# cp /etc/hosts /chroot/httpd/etc/
# cp /etc/host.conf /chroot/httpd/etc/
# cp /etc/resolv.conf /chroot/httpd/etc/
# cp /etc/nsswitch.conf /chroot/httpd/etc/

For extra security you can set the immutable bit on these configuration files. When the immutable bit is set, root has to specifically unset it before a file can be modified, making it much harder for an intruder to tamper with the files:

# chattr +i /chroot/httpd/etc/hosts
# chattr +i /chroot/httpd/etc/host.conf
# chattr +i /chroot/httpd/etc/resolv.conf
# chattr +i /chroot/httpd/etc/nsswitch.conf
# chattr +i /chroot/httpd/etc/passwd
# chattr +i /chroot/httpd/etc/group

In order that the log files be written with the correct time, you need to check /etc/localtime. localtime is a symlink to a file in /usr/share/zoneinfo. To find out which file, run ls -l /etc/localtime and copy the appropriate file to /chroot/httpd/etc/localtime.

By default, syslogd monitors log files only in /var/log. The chrooted httpd daemon will write its logs to /chroot/httpd/var/log, however, so you need to tell syslogd to monitor this directory too. To change this you need to edit the appropriate startup script, /etc/rc.d/rc.syslog or /etc/rc.d/init.d/syslog, depending upon your distro.

For /etc/rc.d/rc.syslog change daemon syslogd -m 0 to daemon syslogd -m 0 -a /chroot/httpd/dev/log.

For /etc/rc.d/rc.syslog change:

    echo -n " /usr/sbin/syslogd"


    echo -n " /usr/sbin/syslogd"
    /usr/sbin/syslogd -m 0 -a /chroot/httpd/dev/log

It is a good idea to create the nescessary log files and set the appendable bit on them too.

# touch /chroot/httpd/var/log/apache/access_log
# touch /chroot/httpd/var/log/apache/error_log
# chmod 600 /chroot/httpd/var/log/apache/*
# chattr +a /chroot/httpd/var/log/apache/*

Finally, you need to change the httpd startup script to run the chrooted httpd. Depending on your distro, open up /etc/rc.d/rc.httpd or /etc/rc.d/init.d/httpd and change the command that starts the httpd daemon to read /usr/sbin/chroot /chroot/httpd/ /usr/sbin/httpd.

Testing the server

If you have not already done so you should shut down the httpd daemon now. Next, restart the syslog daemon: /etc/rc.d/rc.syslog restart (or /etc/rc.d/init.d/syslog restart accordingly). Now start the chrooted version of Apache with /etc/rc.d/rc.httpd start (or /etc/rc.d/init.d/httpd start).

If there are no errors, check the daemon is running with the command ps -aux | grep httpd. You should see several entries indicating a running httpd process. Taking the process number from the output of ps and running ls -l /proc/PROC_NUMBER/root/ should show the structure of your /chroot/httpd rather than your server's / filesystem.

If something has gone wrong, you should try running your chrooted httpd with strace. The command # strace chroot /chroot/httpd /usr/sbin/httpd 2> httpd.strace redirects the output of strace to a file named httpd.strace which should give you an idea where the problem lies.

Once everything is running you can remove your original Apache install.


Although chroot can be used to help create a more secure environment, it is not perfect. You still need to keep your Web server patched up to date and monitor your logs. Your chroot environment should help to contain a potential breakin and protect your system's main filesystem from unseen vulnerabilities in your Web server.

Share    Print    Comments   


on Chrooting Apache

Note: Comments are owned by the poster. We are not responsible for their content.


Posted by: Anonymous Coward on May 28, 2004 12:10 AM
Ummmm. Last I checked chroot is NOT a daemon.

It is a (privileged) system call that changes the definition of "/" for the process. And the chroot program does this, drops privilege, then execs the program.


its not quite a jail either...

Posted by: Anonymous Coward on May 28, 2004 05:40 AM
the chrooted process can always mount<nobr> <wbr></nobr>/dev and then mount a partition and write to it. Its just not likely to do this by accident.


Re: its not quite a jail either...

Posted by: Anonymous [ip:] on August 25, 2007 01:07 PM
Only if it has permissions to mount it... which would be daft thing to give to the chrooted process.



Posted by: Anonymous Coward on May 28, 2004 07:58 AM
OpenBSD has had this for quite a while. The code might even be from the hands of one of the OpenBSD developers, i'm not sure on that. It's a fairly interesting obscurity solution which has some unfortunate results on the behaviour of certain parts of Apache. For example some PHP scripts might suddenly be broken because of this. Try searching on Google for something like "OpenBSD Apache Chroot Howto" or search for this on Deadly/ for an interesting howto which solves several common issues on this.


Doesn't work on debian 3.1 (sarge)

Posted by: Anonymous Coward on April 14, 2006 11:16 AM

Thanks for the article, but it isn't working for me. At the end I run this command and get an error:
sarah:~#<nobr> <wbr></nobr>/etc/init.d/apache2 start
Starting web server: Apache2/usr/sbin/chroot: cannot run command `/usr/sbin/apache2ctl': No such file or directory
sarah:~# ls -l<nobr> <wbr></nobr>/usr/sbin/apache2ctl
-rwxr-xr-x 1 root root 3102 Sep 5 2005<nobr> <wbr></nobr>/usr/sbin/apache2ctl
sarah:~# ls -l<nobr> <wbr></nobr>/chroot/httpd/usr/sbin/apache2ctl
-rwxr-xr-x 1 root root 3102 Apr 13 16:51<nobr> <wbr></nobr>/chroot/httpd/usr/sbin/apache2ctl

(As you can see, both files exist.)

Please help.


Re:Doesn't work on debian 3.1 (sarge)

Posted by: Anonymous Coward on April 25, 2006 06:22 AM
i had similiar issues with centos.. and it seems an issue with all the pam stuff.. i used the following script to make a chrooted user and just copied all chroot dir it created into my apache's chroot and then found out what other libraries i needed to move over and it works

ttp://<nobr>t<wbr></nobr> -jail/


Re:Doesn't work on debian 3.1 (sarge)

Posted by: Anonymous Coward on May 21, 2006 01:35 PM
Hello Gezim.

Another way to test your chrooted apache server is to run the apache2ctl command from the chroot directory. As you can see, running the command from the init scripts forces your distro to run the installed apache from the regular directory structure. If you do<nobr> <wbr></nobr>/chroot/httpd/usr/sbin/apache2ctl start, it will run as expected.



Back Pain relief

Posted by: Anonymous Coward on May 28, 2006 06:45 PM
[URL=] Pain relief [/URL]

  [URL=] Back Pain [/URL]

  [URL=] Pain relief [/URL]
[URL=] Pain relief [/URL]
[URL=<nobr>.<wbr></nobr> htm] Nerve pain relief [/URL]


Re:Doesn't work on debian 3.1 (sarge)

Posted by: Administrator on November 03, 2006 01:53 AM
Well I had the same problem and I as a bit desperate searching all over google for the solution

The problem is the lack of some libraries from the shell

The solution is to check the libraries necessary by the shell

ldd<nobr> <wbr></nobr>/bin/sh

       => (0xffffe000)

       =><nobr> <wbr></nobr>/lib/ (0xb7eea000)

       =><nobr> <wbr></nobr>/lib/ (0xb7ee3000)

       =><nobr> <wbr></nobr>/lib/ (0xb7e9c000)

       =><nobr> <wbr></nobr>/lib/ (0xb7e98000)

       =><nobr> <wbr></nobr>/lib/ (0xb7d77000)<nobr> <wbr></nobr>/lib/ (0xb7f42000)

and then to pass all of them to the<nobr> <wbr></nobr>/chroot/httpd/lib

Jorge de Jesus


Re: Doesn't work on debian 3.1 (sarge)

Posted by: Anonymous [ip:] on February 15, 2008 09:49 AM
Hi all
apache2ctl is just a shell-script, here is it's first-line
so if there is no shell with all dependent libraries within the chroot_jail
apache2ctl will not run correctly.
IMHO there is no place for shells in a chroot_jail if security is the main goal, and of course
if you do not need them desperately. So, if there is no shell within the chroot_jail an
appropriate solution is to edit apache2ctl to suit your needs(just adjust correct paths)
and leave it outside the jail.


Root permission

Posted by: Administrator on March 23, 2007 08:36 PM
Did you login as root user?


This story has been archived. Comments can no longer be posted.

Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya