Secure shared web hosting on Ubuntu Server, part 2

Continuing from part 1, here are the nuts and bolts:

Ubuntu 8.10 Server

root@theo:~# apt-get install apache2 libapache2-mod-chroot

For each domain, create a virtual host config like /etc/apache2/sites-available/example.com:

<VirtualHost *:80>
  ServerAdmin webmaster@example.com
  ServerName example.com
  ServerAlias www.example.com
  ProxyPass / http://localhost:8080/
  ProxyPassReverse / http://localhost:8080/
  <Proxy *>
    Allow from all
  </Proxy>
  ErrorLog /var/www/example.com/logs/error.log
  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel warn
  CustomLog /var/www/example.com/logs/access.log combined
</VirtualHost>

This will be used by the Apache proxy, which is the normal system apache2 running as the default “www-data” user. This proxy handles name-based virtual hosts, and proxies the requests to a second process, running at localhost on port 8080.

Note that the logs are configured here and not in the user’s Apache process, for two reasons:

  1. keep logs pristine in the event of a break-in on a user site (for example via a buggy or malicious PHP script)
  2. single system-wide log file analysis process instead of per-user

Next, create a user account for each domain:

root@theo:~# mkdir /var/www/example.com
root@theo:~# cd /var/www/example.com/
root@theo:/var/www/example.com# useradd -d `pwd`/htdocs example.com
root@theo:/var/www/example.com# mkdir htdocs logs conf
root@theo:/var/www/example.com# chown www-data:www-data logs
root@theo:/var/www/example.com# chown example.com:example.com htdocs/

Create the following in /var/www/example.com/conf/apache2.conf:

ServerRoot "/var/www/example.com/"
RequestHeader set Host example.com
LockFile /var/www/example.com/conf/accept.lock
PidFile /conf/apache2.pid
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
User example.com
Group example.com
AccessFileName .htaccess
<Files ~ "^\.ht">
  Order allow,deny
  Deny from all
</Files>

DefaultType text/plain
HostnameLookups Off
ErrorLog /var/www/example.com/conf/error.log
LogLevel warn
LoadFile /lib/libnss_dns.so.2
LoadModule chroot_module /usr/lib/apache2/modules/mod_chroot.so
Include /etc/apache2/mods-enabled/*.load
Include /etc/apache2/mods-enabled/*.conf
Listen 8080
DocumentRoot /htdocs
ChrootDir /var/www/example.com/

Start up the user Apache process:

root@theo:~# apache2 -f /var/www/example.com/conf/apache2.conf -k start

Everything should now work, but you may notice some problems with PHP or CGI scripts. Generally this means that you will need to make parts of the system available in the chroot; however making copies takes up a lot of space and can quickly get out of date, which is a security risk.

One workaround is to provide needed directories using the “mount -o bind” option, which will remount an existing, mounted part of the file hierarchy somewhere else. For example, this will provide all of “/usr” inside the chroot:

root@theo:~# mkdir /usr /var/www/example.com/usr
root@theo:~# mount -o bind,ro /usr /var/www/example.com/usr

PHP sessions require /tmp to exist inside the chroot; there is no benefit to sharing this one, an empty directory is fine.

That’s pretty much it! Testing, getting startup right etc. is left as an exercise for the reader, since we’re venturing a bit out of the standard Ubuntu Apache setup. Entries in /etc/fstab and creating an init script to handle user Apache processes is probably the best way to go.

In part 3 we’ll cover take a more general look at the pros and cons to this setup, as well as possible future directions.

UPDATE link to secure shared hosting on ubuntu server part 3

EDIT 2009-Oct-03 2:25 PM Pacific – create dir before cding into it; add read-only (ro) option to usr mount; override “host” header in user Apache process

EDIT 2009-Oct-05 4:41 PM Pacific – load resolver library and install caching proxy dns server, needed by popular wordpress anti-spam plugin Akismet

3 Responses to “Secure shared web hosting on Ubuntu Server, part 2”

  1. AnyHosting » Blog Archive » Secure shared web hosting on Ubuntu Server, part 3 Says:

    [...] « Secure shared web hosting on Ubuntu Server, part 2 centralized logging with syslog-ng [...]

  2. AnyHosting » Blog Archive » limiting I/O and CPU on Linux with nice and ionice Says:

    [...] one of my earlier posts about web hosting with Ubuntu Server, I left the startup script for the user-owned Apache instances [...]

  3. AnyHosting » Blog Archive » Secure shared web hosting on Ubuntu Server, part 1 Says:

    [...] « AnyHosting launched! Secure shared web hosting on Ubuntu Server, part 2 [...]

Leave a Reply