Here is the solution I came up with:
services.httpd.enable = true;
services.httpd.adminAddr = "webmaster@example.org";
services.httpd.virtualHosts.localhost = {
extraConfig = ''
ScriptAlias /cgi-bin/ /var/cgi/scripts/
<Directory /var/cgi/scripts>
DirectoryIndex index.pl
Require all granted
</Directory>
'';
};
If you want a perfectly (one time) reproducible solution you can test in a NixOS VM take the above and add this very dirty hack:
systemd.tmpfiles.rules =
let
script = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] ''
#! ${pkgs.perl}/bin/perl
print "Content-type: text/html\n\n";
print "<html><body><h1>Hello World!";
print "</h1></body></html>\n";
'';
in
[
"d /var/cgi"
"d /var/cgi/scripts"
"f /var/cgi/scripts/index.pl 0755 - - - ${script}"
];
From here:
~> curl localhost:80/cgi-bin/
<html><body><h1>Hello World!</h1></body></html>
In summary:
- make sure
index.pl
(or whatever yourcgi
program is) has executable bit set - make sure your scripts directory has an
apache
<Directory>
directive withRequire all granted
(or equivalent, depending on your needs) - under no situation ever should you or anyone use the
systemd.tmpfiles.rules
hack I have written here, other than for a disposable VM test if theapache
configuration alone I provided doesn’t work
Let me know if you have any issues.