A web server, as many will recognize, “serves” web content which may be in the form of static or dynamic pages which may also provide interfaces to database structures and system resources.  Apache, the most widely used web server, is free and open-source with an enormous community of users.  Chrooting, which is a process to augment security, “jails” the Apache process and it’s children to a more secure root environment which decreases the surface area upon which an exploit can be applied.

So, in brief, what we’re talking about is preventing exploits from getting past Apache to other users’ directories or the root system by putting them into a restricted “jail” environment.  Note that I am going to make some assumptions, as dangerous as those are, and if you are curious about doing things differently you can go ahead and use this as a launching off point.  The first assumption is rather simple:  you have a pre-installed server running Debian linux.

Now that you have server running the Debian Linux kernel you may want to install additional packages commonly associated with an Apache install like MySQL.  This is a fine time to do so, let’s begin with MySQL:

apt-get install mysql-server mysql-client libmysqlclient15-dev

immediately after doing so edit /etc/mysql/my.cnf and make sure the bind-address is set to 127.0.0.1 to prevent MySQL from listening on public-facing interfaces.  Restart MySQL using “/etc/init.d/mysql restart”  You should now set your MySQL root password.

Now Apache and PHP:

apt-get install apache2 apache2-doc apache2-mpm-prefork apache2-utils libexpat1 ssl-cert && apt-get install libapache2-mod-php5 php5 php5-common php5-curl php5-dev php5-gd php-idn php-pear php5-imagick php5-imap php5-json php5-mcrypt php5-memcache php5-mhash php5-ming php5-mysql php5-ps php5-pspell php5-recode php5-smtp php5-sqlite php5-tidy php5-xmlrpx php5-xsl

I chained the installations of Apache and PHP together using the “&&” operator which tells the kernel not to move on to the second chain until the first completes successfully.  Agree to anything you’re prompted with.

Edit the /etc/apache2/mods-available/dir.conf and under the <IfModule mod_dir.c> include any extensions for Index files which you may wish to use as your Directory Index.  Edit /etc/apache2/ports.conf and enable listening on port 443 similarly to the way port 80 is also referenced.  Now enable the following Apache modules:

a2enmod ssl && a2enmod suexec && a2enmod include && a2enmod rewrite

again note the use of the “&&” to combine commands.  Nifty.  It’s high time we got some chroot jails up in here so we install the chroot module, enable it and reload Apache:

apt-get install libapache2-mod-chroot && a2enmod mod_chroot && /etc/init.d/apache2 force-reload

We’re going to use /var/jail/www as our chroot environment.  I’m using /var/jail as the parent directory so you can add additional services here jailed likewise.  Let’s create the required directories now:

mkdir -p /var/jail/www/run && chown -R root:root /var/jail/www/run

next we have to tell Apache about this chroot directory, so we edit the /etc/apache2/apache2.conf and add “ChrootDir /var/jail/www” under the reference to “PidFile” – note that the location of the pid (process id) file is going to reside within /var/jail/www as /var/jail/www/var/run/apache2.pid.  Then we link the /var/run/apache2.pid file to /var/jail/www/var/run/apache2.pid like so:

/etc/init.d/apache2 stop && ln -s /var/jail/www/var/run/apache2.pid /var/run/apache2.pid && /etc/init.d/apache2 start

At this point you can setup sites within /var/jail/www/<sitename> and be comforted by the added security.  To use PHP those sites will need to use mod_php and to use perl or python you’ll have to copy the binary and any libraries into the chroot jail – you can discover which libraries perl needs, for example, by executing “ldd /usr/bin/perl”, and copying those libraries listed into your chroot jail for use along with the interpreter.

Final Notes:  if you really want to make this secure you won’t run chrooted Apache as root.  You’d probably also disable PHP globally and use ISPConfig.