Running Vhosts Under Separate UIDs/GIDs With Apache2 mpm-peruser On Debian Etch

Version 1.0
Author: Falko Timme

This article explains how you can install and configure apache2-mpm-peruser on a Debian Etch server. apache2-mpm-peruser is an MPM (Multi-Processing Module) for the Apache 2 web server, very similar to apache2-mpm-itk, but faster (almost as fast as apache2-mpm-prefork). mpm-peruser allows you to run each of your vhosts under a separate UID and GID - in short, the scripts and configuration files for one vhost no longer have to be readable for all the other vhosts. It is based on metuxmpm, a working implementation of the perchild MPM. The result is a sane and secure web server environment for your users, without kludges like PHP's safe_mode.

This document comes without warranty of any kind! I do not issue any guarantee that this will work for you!


1 Preliminary Note

For speed considerations, take a look at

I'm assuming you have a working Apache2 installation with mod_php on your Debian Etch server, e.g. installed like this:

apt-get install apache2-mpm-prefork libapache2-mod-php5

When you create a PHP file with the phpinfo(); function, e.g. like this...

vi /var/www/info.php


... and call it in a browser, you'll see that prefork is listed in the Loaded Modules row under apache2handler:


2 Installing apache2-mpm-peruser

Unlike apache2-mpm-itk, apache2-mpm-peruser is not available as a Debian package, therefore I will build my own Debian package (I will use the apache2-mpm-itk source package as the basis for building my apache2-mpm-peruser Debian package since they are so similar).

Before I start building the package, I install a few prerequisites:

apt-get install build-essential dpkg-dev fakeroot debhelper dpatch apache2-prefork-dev libcap-dev apache2-src autoconf

Then I go to /usr/src and download the apache2-mpm-itk source package:

cd /usr/src
apt-get source apache2-mpm-itk

ls -l

server1:/usr/src# ls -l
total 52
drwxr-xr-x 3 root root  4096 2008-08-16 13:29 apache2-mpm-itk-2.2.3-01
-rw-r--r-- 1 root src  11392 2007-10-03 19:02 apache2-mpm-itk_2.2.3-01-2.diff.gz
-rw-r--r-- 1 root src    664 2007-10-03 19:02 apache2-mpm-itk_2.2.3-01-2.dsc
-rw-r--r-- 1 root src  29071 2006-10-31 00:04 apache2-mpm-itk_2.2.3-01.orig.tar.gz

Next I rename the apache2-mpm-itk directory to apache2-mpm-peruser:

mv apache2-mpm-itk-2.2.3-01 apache2-mpm-peruser-2.2.3-01

Then I go to that directory, download the mpm-peruser patch and delete the mpm-itk patch that's already in the directory:

cd apache2-mpm-peruser-2.2.3-01/
rm -f apache2.2-mpm-itk.patch

Now let's go to the debian/ subdirectory:

cd debian/
ls -l

server1:/usr/src/apache2-mpm-peruser-2.2.3-01/debian# ls -l
total 64
-rw-r--r-- 1 root root    10 2008-08-15 16:21 apache2-mpm-itk.dirs
-rw-r--r-- 1 root root   633 2008-08-15 16:21 apache2-mpm-itk.postinst
-rw-r--r-- 1 root root   561 2008-08-15 16:21 apache2-mpm-itk.preinst
-rw-r--r-- 1 root root   342 2008-08-15 16:21 apache2-mpm-itk.prerm
-rw-r--r-- 1 root root   438 2008-08-15 16:21 changelog
-rw-r--r-- 1 root root     2 2008-08-15 16:21 compat
-rw-r--r-- 1 root root   980 2008-08-15 16:21 control
-rw-r--r-- 1 root root 31777 2008-08-15 16:21 copyright
-rwxr-xr-x 1 root root  1328 2008-08-15 16:21 rules

We rename all files that contain itk in the file name:

mv apache2-mpm-itk.dirs apache2-mpm-peruser.dirs
mv apache2-mpm-itk.postinst apache2-mpm-peruser.postinst
mv apache2-mpm-itk.preinst apache2-mpm-peruser.preinst
mv apache2-mpm-itk.prerm apache2-mpm-peruser.prerm

Next we must modify the changelog file, e.g. like this:

cat /dev/null > changelog
vi changelog

apache2-mpm-peruser (2.2.3-01-1) stable; urgency=low

  * Initial port to Apache 2.2.

 -- Falko Timme <[email protected]>  Fri, 15 Aug 2008 14:29:36 +0100

Make sure that the last line has exactly one space at the beginning (before --) and two spaces between the email address and the date!

Now we open the control file and replace all occurrences of apache2-mpm-itk with apache2-mpm-peruser. I leave the Description as is, but replace ITK with Peruser. In the Conflicts line, I add apache2-mpm-itk:

vi control

Source: apache2-mpm-peruser
Section: net
Priority: extra
Build-Depends: apache2-src, apache2-prefork-dev, libcap-dev, autoconf, debhelper (>> 5.0.0)
Maintainer: Falko Timme <[email protected]>
Standards-Version: 3.7.2

Package: apache2-mpm-peruser
Provides: apache2-modules, apache2, httpd, httpd-cgi
Conflicts: apache2-mpm-prefork, apache2-mpm-itk, apache2-mpm-worker, apache2-mpm-perchild, apache2-mpm-event, apache2-common
Depends: ${apache:Depends}, ${shlibs:Depends}
Architecture: any
Description: multiuser MPM for Apache 2.2
 The Peruser Multi-Processing Module (MPM) works in about the same way as the
 classical "prefork" module (that is, without threads), except that it allows
 you to constrain each individual vhost to a particular system user. This
 allows you to run several different web sites on a single server without
 worrying that they will be able to read each others' files.
 Please note that this MPM is highly experimental, and is not from the same
 tree as the other MPMs.

Next we modify the rules file:

vi rules


cd apache2.2/ && patch -p1 < ../apache2.2-mpm-itk.patch


cd apache2.2/ && patch -p1 < ../httpd-2.2.3-peruser-0.3.0.patch


sed 's,prefork,itk,;s,^".*/configure",../apache2.2/configure,;s,^"--srcdir=.*",--srcdir=../apache2.2/,' < /usr/share/apache2/build/config.nice > build-tree/config.nice


sed 's,prefork,peruser,;s,^".*/configure",../apache2.2/configure,;s,^"--srcdir=.*",--srcdir=../apache2.2/,' < /usr/share/apache2/build/config.nice > build-tree/config.nice


install -m 0755 build-tree/apache2 debian/apache2-mpm-itk/usr/sbin/


install -m 0755 build-tree/apache2 debian/apache2-mpm-peruser/usr/sbin/


echo "apache:Depends=apache2.2-common (= `dpkg -s apache2.2-common | grep ^Version: | cut -d" " -f2`)" >> debian/apache2-mpm-itk.substvars


echo "apache:Depends=apache2.2-common (= `dpkg -s apache2.2-common | grep ^Version: | cut -d" " -f2`)" >> debian/apache2-mpm-peruser.substvars

The complete file looks as follows:

#! /usr/bin/make -f

        $(RM) -r build-tree/
        $(RM) -r apache2.2/
        $(RM) build-stamp

build: build-stamp
build-arch: build-stamp
        mkdir build-tree/
        mkdir apache2.2/
        cd apache2.2/ && tar zxf /usr/src/apache2.tar.gz

        # workaround for apache2-src 2.2.3-3
        if [ -d apache2.2/apache2 ]; then \
                mv apache2.2/apache2/* apache2.2/; \
                rmdir apache2.2/apache2/; \

        cd apache2.2/ && patch -p1 < ../httpd-2.2.3-peruser-0.3.0.patch
        cd apache2.2/ && autoconf
        sed 's,prefork,peruser,;s,^".*/configure",../apache2.2/configure,;s,^"--srcdir=.*",--srcdir=../apache2.2/,' < /usr/share/apache2/build/config.nice > build-tree/config.nice
        chmod +x build-tree/config.nice
        cd build-tree/ && ./config.nice
        cd build-tree/ && $(MAKE)
        touch build-stamp

binary: binary-arch
binary-arch: build-arch

        install -m 0755 build-tree/apache2 debian/apache2-mpm-peruser/usr/sbin/

        dh_installdocs README
        echo "apache:Depends=apache2.2-common (= `dpkg -s apache2.2-common | grep ^Version: | cut -d" " -f2`)" >> debian/apache2-mpm-peruser.substvars

.PHONY: clean build build-arch binary binary-arch binary-indep

That are all changes we need to make - we can now build the package:

cd ..

The package will be available in the /usr/src directory:

cd /usr/src
ls -l

server1:/usr/src# ls -l
total 6512
-rw-r--r-- 1 root src    11392 2007-10-03 19:02 apache2-mpm-itk_2.2.3-01-2.diff.gz
-rw-r--r-- 1 root src      664 2007-10-03 19:02 apache2-mpm-itk_2.2.3-01-2.dsc
-rw-r--r-- 1 root src    29071 2006-10-31 00:04 apache2-mpm-itk_2.2.3-01.orig.tar.gz
drwxr-xr-x 5 root root    4096 2008-08-16 13:40 apache2-mpm-peruser-2.2.3-01
-rw-r--r-- 1 root src      353 2008-08-16 13:36 apache2-mpm-peruser_2.2.3-01-1.dsc
-rw-r--r-- 1 root src      710 2008-08-16 13:40 apache2-mpm-peruser_2.2.3-01-1_i386.changes
-rw-r--r-- 1 root src   165438 2008-08-16 13:40 apache2-mpm-peruser_2.2.3-01-1_i386.deb
-rw-r--r-- 1 root src    50282 2008-08-16 13:36 apache2-mpm-peruser_2.2.3-01-1.tar.gz
-rw-r--r-- 1 root root 6364431 2008-03-22 10:35 apache2.tar.gz

The mpm-peruser package we've just built is named apache2-mpm-peruser_2.2.3-01-1_i386.deb. Before we can install it, we must uninstall apache2-mpm-prefork as it is conflicting with apache2-mpm-peruser (remember the control file):

apt-get remove apache2-mpm-prefork

server1:/usr/src# apt-get remove apache2-mpm-prefork
Reading package lists... Done
Building dependency tree... Done
The following packages will be REMOVED:
  apache2-mpm-prefork libapache2-mod-php5
0 upgraded, 0 newly installed, 2 to remove and 68 not upgraded.
Need to get 0B of archives.
After unpacking 6115kB disk space will be freed.
Do you want to continue [Y/n]? 
<-- Y
(Reading database ... 29620 files and directories currently installed.)
Removing libapache2-mod-php5 ...
Module php5 disabled; run /etc/init.d/apache2 force-reload to fully disable.
Removing apache2-mpm-prefork ...
Stopping web server (apache2)....

Unfortunately, this also removes the libapache2-mod-php5 package so that PHP will not work anymore. We will address that in a moment.

Now we can install the apache2-mpm-peruser package:

dpkg -i apache2-mpm-peruser_2.2.3-01-1_i386.deb

Now if you try to reinstall the libapache2-mod-php5 package, you will see that apt insists on removing apache2-mpm-peruser and reinstalling apache2-mpm-prefork which is not what we want - therefore we abort this:

server1:/usr/src# apt-get install libapache2-mod-php5
Reading package lists... Done
Building dependency tree... Done
The following extra packages will be installed:
Suggested packages:
The following packages will be REMOVED:
The following NEW packages will be installed:
  apache2-mpm-prefork libapache2-mod-php5
0 upgraded, 2 newly installed, 1 to remove and 61 not upgraded.
Need to get 0B/2833kB of archives.
After unpacking 5681kB of additional disk space will be used.
Do you want to continue [Y/n]? 
<-- n

This happens because when the libapache2-mod-php5 package was built, the maintainer told it that it depends on either apache2-mpm-prefork or apache2-mpm-itk. This means we will have to rebuild the libapache2-mod-php5 from the sources and add the apache2-mpm-peruser package to the dependencies of that package (you can do this with any other package as well if you have the same problem with other packages). I will come to that in a moment.

Falko Timme

About Falko Timme

Falko Timme is an experienced Linux administrator and founder of Timme Hosting, a leading nginx business hosting company in Germany. He is one of the most active authors on HowtoForge since 2005 and one of the core developers of ISPConfig since 2000. He has also contributed to the O'Reilly book "Linux System Administration".

Share this page:

Suggested articles

0 Comment(s)

Add comment