I’m trying to use nixpkgs (not NixOS) to create a flake that packages Apache Httpd Server with the mod_perl module. I can see that both the server and the module are packaged in Nixpkgs, but I’m unclear on how I should use the two together.
Other frameworks like Python and PHP provide a functions like withPackages
or withExtensions
, but the apacheHttpd doesn’t seem to have anything similar.
I’ve looked at the NixOS implementation, and from what I can tell I need to:
- Override mod_perl to use the outPath of my apacheHttpd package in it’s build step
- Move or symlink the resulting
modules/mod_perl.so
file into my apacheHttpd package’s module directory
- Add a
LoadModule perl_module modules/mod_perl.so
line to my package’s httpd.conf
Unfortunately, I’m struggling with how to do these steps in a Flake, has anyone built something like this before?
What you’re saying is correct, though not necessarily easy as you have found.
As you have noticed we don’t explicitly support what you want because the way we compile httpd
plugins are .so
files which are generally referenced in config files.
But all is not lost …
My memory is rough on this but I’m fairly certain there is a reliable way to pass plugins via the command line in an extensible way. What we can do is create a wrapper around the package and passes the plugins via command line option. This is analogous (though not the same) to what we do with php
.
I’ll try to find a few minutes to write an example up for you.
Out of curiosity what is your intention with this? You’ll need a configuration file - how are you providing that?
Thank you! What you’re saying about the wrapper makes sense, I can take a look at the php example as well.
For my intention, I’m looking for a way to setup a LAMP stack that I can run on multiple machines/OS’s, without having to reinstall and configure everything from scratch.
For the config – one option would be to generate the config in the Nix derivation (like the nixOS module does), but I’m leaning towards keeping the project’s httpd.conf
in my project directory, and then starting apache with apachectl start -f httpd.conf
I didn’t actually load up a website, but after some minor tweaking this snippet really appears to do what you want:
{
description = "A very basic flake";
outputs = { self, nixpkgs }: {
packages.x86_64-linux.apache = with nixpkgs.legacyPackages.x86_64-linux;
let
mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = apacheHttpd.out; };
in
symlinkJoin {
name = "httpd-with-plugins";
paths = [ apacheHttpd ];
nativeBuildInputs = [ makeWrapper ];
postBuild = ''
wrapProgram $out/bin/httpd --add-flags -C --add-flags "'LoadModule perl_module ${mod_perl}/modules/mod_perl.so'"
'';
};
};
}
On a related note you may want to keep a close eye on system-manager which looks very promising from our amazing community friends at
Numtide
.
1 Like
Looks like that works! Need to test it with an actual example, but it does seem to load the module:
❯ ./result/bin/httpd -t -D DUMP_MODULES
Loaded Modules:
core_module (static)
so_module (static)
http_module (static)
**perl_module (shared)**
mpm_event_module (shared)
authn_file_module (shared)
...
System manager looks interesting, having NixOS modules on other systems w/ nixpkgs would be really useful. I’ll keep an eye onit
Great!
I’m curious about how well this will work for you. A few years back I made use of httpd
on NixOS to support a ton of fairly complicated mod_perl
applications with great success.
If you don’t mind let me know how it goes. 
There was one more piece missing – when I tried to actually run a perl script with the flake above, I got the following perl error:
[Sun Jul 02 11:42:47.730155 2023] [perl:error] [pid 28837:tid 6162722816] [client ::1:56920] failed to resolve handler `ModPerl::Registry’: Can’t locate ModPerl/Registry.pm in @INC (you may need to install the ModPerl::Registry module)
It looks like for this to run successfully, you need perl, apacheHttpd, and mod_perl all bundled together. I fixed this by adding pkg.perl.out
as an input to mod_perl, and then adding both perl
and mod_perl
to the symlinkJoin. So my final flake looked like this:
{
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils } :
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = pkgs.apacheHttpd.out; perl = pkgs.perl.out;};
in {
packages = with pkgs; rec {
apache = symlinkJoin {
name = "apache-with-perl";
paths = [apacheHttpd perl mod_perl];
nativeBuildInputs = [makeWrapper];
postBuild = ''
wrapProgram $out/bin/httpd --add-flags -C --add-flags "'LoadModule perl_module ${mod_perl}/modules/mod_perl.so'";
'';
};
default = apache;
};
}
);
}
Once I had this, i could now run the hello world example on the mod_perl docs
This is what I had done on NixOS:
{ config, pkgs, lib, ... }:
let
perlEnv = pkgs.perl.withPackages (perlPackages: with perlPackages; [
CGI
CGIMinimal
DataDumper
DBDmysql
DBDOracle
DBDsybase
DBI
HTTPMessage
ImageSize
IOSocketSSL
JSON
LWP
LWPProtocolHttps
MathBigInt
MIMEBase64
MIMELite
NetSFTPForeign
NetSNPP
URI
URIFind
];
in
{
config = {
services.httpd.extraConfig = ''
SetEnv PERL5LIB ${perlEnv}/lib/perl5/site_perl
'';
};
}
In your case I think you just add another argument, like so:
--add-flags -C --add-flags "'SetEnv PERL5LIB ${perlEnv}/lib/perl5/site_perl'"
1 Like