At work we yestoday decided to update our internal url structure for our client test sites, issue management systems and such arround a bit. Seeing as we decided on purchasing a genuine signed ssl wildcard certificate, we needed to change our url’s a bit.
We used to have a url schema consisting of the following components:
[dev.|test.]<project-name>.<client-name>.companyname.tld
That made for very long url’s, and furthermore, the url’s would not be supported by a *.companyname.tld. Based on this infomation, and wanting to create a more generelized, nicer url schema, we choose to cross over to the following schema:
[dev-|test-]<project-name>.companyname.tld
Which besides from supporting a wildcard ssl certificate just fine, just, well, looks nicer.
Either way, me beeing in charge of the contents in /etc/, and getting a little sick of growing apache configuration files, I chooose to write some macros to configure our project sites.
We generally have 2 types of project sites. django based sites, and PHP based sites.
A typical django apache configuration consists of a VirtualHost and some mod_python settings inside a Location block. Lot’s of configuration, very little actual diffrence between the configration projects in between.
An example of a django based application running inside a apache VirtualHost, could look like this:
<VirtualHost *:80>
ServerName test-project.company.tld
<Location />
SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/path/to/project', '/other/path/to/inject']"
SetEnv DJANGO_SETTINGS_MODULE project.settings
</Location>
<Location /media/>
SetHandler none
</Location>
Alias /media/admin/ /path/to/django/contrib/admin/media/
Alias /media/ /path/to/project/media/
</VirtualHost>
And the on top of that comes SSL configuration, auth and such. 25 lines of configuration per django site. Now, I really wanted to acomplish two things.
- Make the configuration easier to maintain
- Enable other users to setup sites without knowing the depths of django and
mod_python
Now, apache configuration, meet mod_macro. The solution to my problem was very simple. Create a macro that handles all the django configuration, given 4 parameters. A server name (i.e. the url), the parent directory of the django site and the module name of the site.
So i started building my macro.
<Macro DjangoSite $servername $root $module>
<VirtualHost *:80>
ServerName $servername
<Location />
SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/common/path/to/inject', '$root']"
SetEnv DJANGO_SETTINGS_MODULE $modulename.settings
</Location>
<Location /media/>
SetHandler none
</Location>
Alias /media/admin/ /path/to/django/contrib/admin/media/
Alias /media/ $root/$module/media/
</VirtualHost>
</Macro>
mod_macro is really simple, it will do a longest-match search and replace on the macro’s content. So, if we had a django site in /path/to/djangosite/testsite/ the above macro could be used as:
Use DjangoSite www.example.org /path/to/djangosite/ testsite
Which would expand to:
<VirtualHost *:80>
ServerName www.example.org
<Location />
SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/common/path/to/inject', '/path/to/djangosite/']"
SetEnv DJANGO_SETTINGS_MODULE testsite.settings
</Location>
<Location /media/>
SetHandler none
</Location>
Alias /media/admin/ /path/to/django/contrib/admin/media/
Alias /media/ /path/to/djangosite/testsite/media/
</VirtualHost>
Hope you find this infomation a little useful. I actually like looking at our apache configuration file now.