HOWTO: PerUser MPM with Apache2 (increased security)

thoroughfare

Verified User
Joined
Aug 11, 2003
Messages
575
Hello,

This is my first how-to and also my first patch for anything so please bear with me, if I've made any mistakes please say so and I'll fix it :)

PerUser homepage:
http://www.telana.com/peruser.php

Working test systems:

  • Working on Ubuntu Server (a Debian fork).
  • Please post your OS, version, distribution, kernel version and architecture (64bit?) if you have PerUser running smoothly on your box.

The PerUser MPM is an experimental MPM processor for Apache 2. This won't work with Apache 1.x. Saying that, the upgrade to Apache 2 is very very easy (much easier than I anticipated), and caused me no problems. I'd say go for it.

The idea behind PerUser is that it creates a new Apache process running as a user you specify for each VirtualHost, when requested. In other words, if you have a user called 'joesmith', any requests for the VirtualHosts owned by Joe will run as user 'joesmith'. This solves the problems with running PHP as nobody or 'apache', and means you can avoid nasty (but useful) hacks like SuPHP, SuExec.

The other important thing about PerUser is that it's not threaded. This is really important for PHP etc, as most PHP extensions aren't threadsafe. The difference between PerUser and say, the PerChild MPM is that PerChild is threaded, and so is not safe to use with PHP. The same applies for forks of PerChild, like MetuxMPM.


Please don't bork your system because of my how-to :) This MPM is
experimental and may well not work. Use this on production systems at your own risk. Please do, however, give it a shot on your dev/test boxes and send in some debug info to the PerUser mailing list.


Righty, here we go...

First of all you need to patch the DA's CustomApache build script with this patch:

DirectAdmin PerUser MPM Patch (version 0.1.1 released April 5th 2006 to enable debug logging)

To patch, do this:

Code:
cd /usr/local/directadmin/customapache/
wget -nc [url]http://www.retroweb.net/pub/DirectAdmin-build-httpd-peruser-mpm.patch[/url]
patch -p1 < DirectAdmin-build-httpd-peruser-mpm.patch

Easy-peasy. Next, add this to your /etc/httpd/conf/httpd.conf

Code:
<IfModule peruser.c>
	ServerLimit 256
	MaxClients 256
	MinSpareProcessors 2
	MaxProcessors 10
	MaxRequestsPerChild 1000
	# kill off idle processors after this many seconds
	# set to 0 to disable
	ExpireTimeout 1800
	# try 'nobody nobody' instead of 'apache apache' if this doesn't work
	Multiplexer apache apache
</IfModule>

Note: It's been suggested that you use 'nobody nobody' for the Multiplexer line, as the apache user can still read user directories. I'm not a big fan of the nobody user however; I'd suggest that if you're going to stick with the PerUser MPM, that you chown your user directories to user:user rather than user:apache.

KeepAlive needs to be turned off:

Code:
perl -pi -e 's/^KeepAlive On/KeepAlive Off/' /etc/httpd/conf/httpd.conf

One last thing, we need to edit our VirtualHost templates. Look for this directory:

Code:
ls -ald /usr/local/directadmin/data/templates/custom/

If doesn't exist, do:

Code:
mkdir /usr/local/directadmin/data/templates/custom/
cp /usr/local/directadmin/data/templates/* /usr/local/directadmin/data/templates/custom/

This will allow us to edit the templates without them getting overwritten every time we upgrade DA.

All you need to do is edit the following files:

/usr/local/directadmin/data/templates/custom/virtual_host2_sub.conf
/usr/local/directadmin/data/templates/custom/virtual_host2_secure_sub.conf
/usr/local/directadmin/data/templates/custom/virtual_host2_secure.conf
/usr/local/directadmin/data/templates/custom/virtual_host2.conf

...and add this to each one of them, inside the <VirtualHost></VirtualHost> directive:

Code:
	<IfModule peruser.c>
		# this must match a Processor
		ServerEnvironment |USER| |GROUP|
		# these are optional - defaults to the values specified above
		MinSpareProcessors 4
		MaxProcessors 20
	</IfModule>

WAIT! One more thing to add to each of these files, just above the <VirtualHost> section:

Code:
Processor |USER| |GROUP|

For example:

Code:
|?DOCROOT=`HOME`/domains/`DOMAIN`/public_html|
Processor |USER| |GROUP|
<VirtualHost |IP|:80>

        ServerSignature Off
        Redirect /phpmyadmin [url]https://[/url]|DOMAIN|/phpmyadmin
        Redirect /squirrelmail [url]https://[/url]|DOMAIN|/squirrelmail
        Redirect /webmail [url]https://[/url]|DOMAIN|/webmail
        Redirect /phpMyAdmin [url]https://[/url]|DOMAIN|/phpmyadmin

	<IfModule peruser.c>
		# this must match a Processor
		ServerEnvironment |USER| |GROUP|
		# these are optional - defaults to the values specified above
		MinSpareProcessors 4
		MaxProcessors 20
	</IfModule>

|CUSTOM|

        |?CGI=ScriptAlias /cgi-bin/ `DOCROOT`/cgi-bin/|
        ServerName [url]www.[/url]|DOMAIN|
        ServerAlias [url]www.[/url]|DOMAIN| |DOMAIN| |SERVER_ALIASES|
        ServerAdmin |ADMIN|
        DocumentRoot |DOCROOT|
        |CGI|

        |USECANONICALNAME|

        SuexecUserGroup |USER| |GROUP|
        CustomLog /var/log/httpd/domains/|DOMAIN|.bytes bytes
        CustomLog /var/log/httpd/domains/|DOMAIN|.log combined
        ErrorLog /var/log/httpd/domains/|DOMAIN|.error.log

        <Directory |DOCROOT|>
                Options +Includes -Indexes
                php_admin_flag engine |PHP|
                php_admin_flag safe_mode |SAFE_MODE|
                php_admin_value sendmail_path '/usr/sbin/sendmail -t -i -f |USER|@|DOMAIN|'
        </Directory>

|HANDLERS|
|MIMETYPES|

        php_admin_value open_basedir /tmp/:/usr/local/lib/php/:|HOME|/:/var/www/html/

</VirtualHost>

Next, you need to tell DA to rewrite the templates now you've modified them:

Code:
echo "action=rewrite&value=httpd" >> /usr/local/directadmin/data/task.queue


Finally, restart Apache:
Code:
apachectl restart

Tada! If everything goes hideously wrong, as it may well, remember to check your Apache error_log for info.

Please add to this thread and we'll make a list of reported successes etc and help out where possible.

Enjoy :)
Matt
 
Last edited:
There's a spangly how-to even if I do say so myself. Please remember to use the latest version of the customapache build patch (above), as I've just updated it to version 0.1.1.
 
If something goes wrong, just clean out the customapache directory and rebuild Apache as normal with the unpatched build script. Of course you'll need to remove the changes to the config files :)

Matt
 
I guess I can't try lol, made too much configuration to the apache conf file..
 
Syntax error on line 10 of /usr/local/directadmin/data/users/user/httpd.conf:
Trying to use more server environments than NumServers. Increase NumServers in your config file.

What to do?
 
Last edited:
From the PerChild (a similar MPM module) docs:

The NumServers directive determines the number of children alive at the same time. This number should be large enough to handle the requests for the entire site. To increase this value beyond the value of 8, it is necessary to change the value of the ServerLimit directive and stop and re-start the server. See the section above for a configuration example.

From: http://httpd.apache.org/docs/trunk/mod/perchild.html

I'd say try adding that under the <IfModule peruser.c> section and trying out different values.

HTH,
Matt
 
Code:
root@london:/usr/local/directadmin/customapache# patch -p1 < DirectAdmin-build-httpd-peruser-mpm.patch
missing header for unified diff at line 3 of patch
can't find file to patch at input line 3
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- build.orig Tue Apr  4 11:06:21 2006
|+++ build.new  Wed Apr  5 08:47:14 2006
--------------------------
File to patch:

Any ideas?
 
I have managed to fix that but now every site gets

Code:
Not Found

The requested URL / was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

Any ideas :\
 
Taken me a few hours to figure it out, When you specify a home directory with the |USER| |GROUP| it trys to use /home/user/home/user.

By default it will use /home/user without |HOME|

Remove it or you will get errors cannot find..
 
Hi Charlie,

I'm not sure I follow; which bit needs removing in the configuration? Can you quote the line?

Have you got this MPM running quite stably?
 
You need to remove

Processor |USER| |GROUP| |HOME|
ServerEnvironment |USER| |GROUP| |HOME|

And replace it with

Processor |USER| |GROUP|
ServerEnvironment |USER| |GROUP|

Otherwise it will try to use the wrong directory, and bring up errors.

Yes I have got it running nice and stable, VERY SECURE!

It's running on Ubuntu Server which uses Debian. So you can put down at the top of your readme.

I might add to your readme it is realy hard to follow and the patch didn't work for me.

Manualy for the win!
 
Just found a small bug, I did killall -9 httpd as I was installing something new

and I booted it back up seemed fine but didnt load pages. I checked error_log and it shows

[emerg] (28)No space left on device: Couldn't create accept lock

after googling for one second I managed to free the locks, Not sure what caused this yet. I think its because I did killall -9 httpd and not the proper apache stop

Maybe someone else might know
 
Yeah it'll have been the killall -9, as that would kill of all the processes uncleanly.

I'll tidy up my howto somewhat :)
 
Back
Top