Flexible vhost lighty config

September 25th, 2006

Ian White

I've been trying to get a nice, flexible, solution for automagically configuring vhosts and subdomains. Here's my latest effort:

Subversion: http://svn.ardes.com/ardes/srv/local/etc/lightttpd

The solution is to meet the following desiderata:

  • Flexible: no enforcing of a particular lighty/rails setup for a particular vhost,
  • Flexible: no enforcing of a particular directory layout, and I want it to work for vhosts and subdomains, or a mixture of the two,
  • Flexible: I want a solution which is compatible with serving only some sites with lighty (via ProxyPass in Apache),
  • Set and forget: I don't want to have to edit my main lighttpd.conf file every time I add or remove a site.
  • Encapsulated: I want the config files for a site to reside in that site's directory.

How to

Assumptions

I'm using a plesk system, and wanted to make it compatible with that. But the following should work with any site layout you want. Here's an example site layout:

  /var/www/vhosts/example.com
  /var/www/vhosts/example.com/subdomains/blog

You want to serve both of the above using lighty, just static content from example.com, and a railsy blog from the blog.example.com subdomain.

Requirements and setup

First you need to get a copy of hosts.conf.rb. You should put this in your /etc/lighttpd directory and make it executable.

Then edit your lighttpd.conf file so that contains the line:

include_shell "/etc/lighttpd/hosts.conf.rb"

This will replace all of your host conditionals that configure your vhosts and subdomains. The configuration now goes into small files in the site directories (default is conf/lighttpd.conf, but this is configurable). Also, a var called host-root is set to the current path.

In /var/www/vhosts/example.com/conf/lighttpd.conf:

server.document-root = var.host-root + "/httpdocs"

In /var/www/vhosts/example.com/subdomains/blog/conf/lighttpd.conf:

var.rails-root = var.host-root + "/rails/typo"
var.fcgi-min-procs = 2
var.fcgi-max-procs = 4
  
include "rails.conf" # this script does all the rails stuff and should be
                     # placed in /etc/lighttpd

See rails.conf for the details of the above include script

Test

Now test this by running hosts.conf.rb from the command line. You should see the following output:

$HTTP["host"] =~ "(^|www\.)example\.com" {
  var.host-root = "/var/www/vhosts/example.com"
  server.document-root = var.host-root
}
$HTTP["host"] == "blog.example.com" {
  var.host-root = "/var/www/vhosts/ardes.com/subdomains/gtd"
  var.rails-root = var.host-root + "/rails/typo"
  var.fcgi-min-procs = 2
  var.fcgi-max-procs = 4

  include "rails.conf" # this script does all the rails stuff and should be
                       # placed in /etc/lighttpd
}

Notice the the vhost is configured to catch www.example.com and example.com. Notice also that you don't have to edit the main /etc/lighttpd.conf file. The idea being: you can add and remove conf files to vhost and subdomain paths, and when lighty is restarted, they'll automatically be picked up by the hosts.conf.rb script!

So once you've got the output of hosts.conf.rb working the way you like it, you should restart lighty.

A glitch

At this point, I encountered a small problem with lighttpd 1.4.11. It complained that SHELL wasn't set when I tried to use the 'include_shell' directive (kinda essential). This is no problem if you're manually starting lighty, but I'm using the init.d script. So I simply had to add the followng to /etc/init.d/lighttpd.

  export SHELL=/bin/sh

Restart lighty and test!

Other configurations

If you want to do this with a different layout, you just need to edit the config section of hosts.conf.rb. The syntax is quite flexible, here's the config for the above setup:

Config = {
  :vhost => {
    :path  => '/var/www/vhosts/:vhost:',
    :host  => '(^|www\.):vhost:'
  },
  :subdomain => {
    :path  => '/var/www/vhosts/:vhost:/subdomains/:subdomain:',
    :match => '==',
    :host  => ':subdomain:.:vhost:'
  }
}

The :path string can contain as many named variables as you like, they are surrounded by colons (e.g. :vhost:). The script simply searches the filesystem with these as glob wildcards. However the values are captured and stored by name for use in the host regexp specification. This is what makes it so easy to configure (the www example above is a good starting point).

Roundup

This is my first foray into lighty configuration. Please improve on this offering, or let me know if it doesn't work for you.

2 Responses to “Flexible vhost lighty config”

  1. Aaron Says:
    Thanks for this awesome combination of scripts. I was pulling my hair out when lighttpd was acting like it didn't know anything about my subdomains... Come to find out I forgot to make the hosts ruby script executable. Lighttpd didn't complain about nothing coming back from the include shell so it was hard to debug.
  2. Ian Says:
    Hi Aaron, glad you found this helpful. Thanks for the tip about making sure the include_shell scripts are executable - will add it to the article.

Leave a Reply