S&M at lug.org.uk

Submitted by hrm on 26 March, 2008 - 19:24

Something I've wanted to do for some time (and have been talking about for far too long) is to get a "static and managed" service running on lug.org.uk's system. This will allow us to provision web applications for users in a way where we (lug.org.uk admins) control the installed app -- so we can do upgrades when necessary, and have them rolled out over the whole service.

The VM has been around for some time – it's called snm (Static 'n' Managed), and is referred to colloquially as S&M. I've finally got a couple of web apps up and running on it in the way I want. Here's how...

First, we need some groundwork with Apache to make things easier for us. This involves mpm-itk, and mod_macro.

mpm-itk is an Apache "multi-processing module" – the thing that handles incoming requests. It differs from the usual ones in that it can run as a different uid/gid for each virtual host. This allows us to separate the file permissions of the different users, so that a compromise of one web app installation is less likely to affect the others.

mod_macro is a very handy module that does exactly what it sounds like it does – it allows you to define and use macros in your Apache config files. We use it to set up completely standardised configurations that can be rolled out with a single line of config for each user we provision.

We also want to prevent the users from installing and running their own web applications – this would rather defeat the point of having the S&M server in the first place.

So...

We have a macro which defines the "base" configuration for all S&M provisioned services:

<Macro BaseVH $group_name>
   ServerName $group_name.lug.org.uk
   ServerAdmin admin@lug.org.uk

   DocumentRoot /home/groups/$group_name/public_html/

   # Set up global options
   <Directory />
      # Prevent accidental mapping of files outside DocumentRoot
      Order Deny,Allow
      Deny from All
      # Prevent use of .htaccess
      AllowOverride None
      Options Indexes
   </Directory>

   # Set up the base home directory
   <Directory /home/groups/$group_name/public_html>
      Order Deny,Allow
      Allow from All

      Options +MultiViews

      # Permit more control over authentication through .htaccess
      AllowOverride AuthConfig
   </Directory>

   # Set up the CGI bin
   ScriptAlias /cgi-bin/ /usr/local/lib/cgi-bin/
   <Directory /usr/local/lib/cgi-bin/>
      Order Deny,Allow
      Allow from All

      # We need only this option, and no others here
      Options ExecCGI
      # Don't do funny path-extension tricks
      AcceptPathInfo Off
      # Run as CGI
      SetHandler cgi-script
   </Directory>

   # Forbid PHP from running unless we tell it otherwise
   php_admin_flag engine off

   # Set UID/GID to run this VH under
   AssignUserID $group_name $group_name

   # Logging
   LogLevel warn
   ErrorLog /var/log/apache2/$group_name-error.log
   CustomLog /var/log/apache2/$group_name-access.log combined
   ServerSignature On
</Macro>

The important bits here are the AssignUserID directive to tell mpm-itk what to run the VH as, the AllowOverride directives that stop people from doing weird things in .htaccess files, and the php_admin_flag engine off directive, which turns PHP off globally. It will be turned on again for very specific directories, where it's needed.

The users only get write access to their own directories, so the cgi-bin directory is controlled by us. Again, this gives us the ability to manage everything that gets executed on this machine centrally. (Muahahahaha! The power!)

Now for the individual applications: The first app we're providing is DokuWiki.

<Macro DokuWiki $group_name>
   Alias /wiki/ /usr/local/share/dokuwiki/
   <Directory /usr/local/share/dokuwiki/>
      Order Deny,Allow
      Allow from All

      Options +MultiViews +FollowSymLinks +Indexes

      php_admin_flag engine on
      php_admin_value open_basedir /home/groups/$group_name/:/usr/local/share/dokuwiki/
      php_admin_value doc_root /home/groups/$group_name/public_html/
      SetEnv WIKI_NAME $group_name
      SetEnv WIKI_DATA /home/groups/$group_name/dokuwiki-data/
   </Directory>
</Macro>

This does a bunch of different things:

  • it maps the central DokuWiki installation into the /wiki/ path,
  • it turns the PHP engine on, but only for paths under that installation
  • it defines a set of directories (open_basedir) that PHP will be allowed to read files from – attempt to read anything outside that list, and PHP will throw an error
  • it defines a couple of system variables that we can use to find the per-user data directory for this instance of the package
  • it defines a bunch of rewrite rules (not shown) for DokuWiki's "pretty URL" feature, if anyone wants to use it

Finally, we define a bunch of macros for the actual provisioning. These look something like this:

<Macro VHDokuWiki $group_name>
   NameVirtualHost *:80
   <VirtualHost *:80>
      Use BaseVH $group_name
      Use DokuWiki $group_name
   </VirtualHost>
</Macro>

There are (or will be) similar macros for other web applications and combinations, such as "DokuWiki plus [forum]". To provision a given configuration for a LUG, the only thing you need to put in the Apache configuration is:

Use VHDokuWiki lugname

That's all for the Apache configuration. Configuring and patching DokuWiki will come in part two