A recent thread on the misc@ mailing list reminded me of the obstacles faced when installing Perl CGI applications in the default OpenBSD httpd(8) chroot. Here is a brief guide at how I approached the problem by using mod_perl to import the necessary modules at execution.

Finding any Perl CGIs in the ports/www tree is the proverbial needle in a haystack. The obstacles facing chrooted CGIs are well documented. Simpler alternatives (read: php) have led to a lack of creative solutions, even at the expense of security holes and poor design practices.

I mentioned previously that I'd managed to overcome this problem for some of my own software. I talked with some colleagues about this leading up to c2k8, and we agreed that it should work as long as OpenBSD does privilege separation after mod_perl compiles its libraries and modules. This would mean that any external Perl modules an application needs could be imported when Apache is started. Fortunately for us, this is exactly what happens with OpenBSD's httpd(8).

Setting up Hatchet to use this method was incredibly simple. Beyond a few typical mod_perl directives, I just had to tell it where to find the file containing the list of modules I needed to import ( startup.pl ). Here is the example I include in README.OpenBSD :

<VirtualHost _default_:80> DocumentRoot /var/www/hatchet PerlModule Apache::PerlRun <Location /cgi/> SetHandler perl-script PerlHandler Apache::PerlRun PerlRequire /var/www/hatchet/cgi/startup.pl Options ExecCGI PerlSendHeader On allow from all </Location> </VirtualHost>

The PerlModule and PerlRequire directives are analogous to Perl's use() and require() functions, respectively. The SetHandler and PerlHandler directives tell Apache that mod_perl should handle the content generation phase for any Perl scripts in this Location .

Because the startup.pl file is PerlRequire 'd, it must return true. Any modules that your application use() 's should be included in here for importing:

use CGI (); use DBI (); use DBD::SQLite (); use HTML::Template (); use Time::Local (); use Data::Dumper (); 1;

The final line guarantees that the file returns true. Parentheses following each package cause everything in that package's namespace to be imported. Because Perl is an interpreted language and mod_perl compiles your source code at startup, Apache must be restarted whenever there are changes to any affected source code. Once this is complete and configured properly, not only should your application work properly in the httpd chroot, but it will benefit from mod_perl's significant speed increase over native Perl CGI.

This article was not intended to be a comprehensive introduction to mod_perl. Rather, I hope that this motivates others to research mod_perl for themselves and see how it can be used to make their Perl applications shine on OpenBSD. Please refer to the official documentation for more information.