php.services.default: init

This commit is contained in:
Aaron Andersen 2025-08-02 18:47:07 -04:00
parent c46afef909
commit 487e725463
5 changed files with 266 additions and 0 deletions

View File

@ -21,6 +21,7 @@ let
_file = "${__curPos.file}:${toString __curPos.line}";
options = {
"<imports = [ pkgs.ghostunnel.services.default ]>" = fakeSubmodule pkgs.ghostunnel.services.default;
"<imports = [ pkgs.php.services.default ]>" = fakeSubmodule pkgs.php.services.default;
};
};
in

View File

@ -13,6 +13,10 @@ in
imports = [ ./fpm.nix ];
_module.args.php = php';
};
fpm-modular = runTest {
imports = [ ./fpm-modular.nix ];
_module.args.php = php';
};
httpd = runTest {
imports = [ ./httpd.nix ];
_module.args.php = php';

View File

@ -0,0 +1,71 @@
{ lib, php, ... }:
{
name = "php-${php.version}-fpm-modular-nginx-test";
meta.maintainers = with lib.maintainers; [
aanderse
];
nodes.machine =
{ config, pkgs, ... }:
{
environment.systemPackages = [ php ];
services.nginx = {
enable = true;
virtualHosts."phpfpm" =
let
testdir = pkgs.writeTextDir "web/index.php" "<?php phpinfo();";
in
{
root = "${testdir}/web";
locations."~ \\.php$".extraConfig = ''
fastcgi_pass unix:${config.system.services.php-fpm.php-fpm.settings.foobar.listen};
fastcgi_index index.php;
include ${config.services.nginx.package}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
locations."/" = {
tryFiles = "$uri $uri/ index.php";
index = "index.php index.html index.htm";
};
};
};
system.services.php-fpm = {
imports = [ php.services.default ];
php-fpm = {
package = php;
settings = {
foobar = {
"user" = "nginx";
"listen.group" = "nginx";
"listen.mode" = "0600";
"listen.owner" = "nginx";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.max_requests" = 500;
"pm.max_spare_servers" = 3;
"pm.min_spare_servers" = 1;
"pm.start_servers" = 2;
};
};
};
};
};
testScript =
{ ... }:
''
machine.wait_for_unit("nginx.service")
machine.wait_for_unit("php-fpm.service")
# Check so we get an evaluated PHP back
response = machine.succeed("curl -fvvv -s http://127.0.0.1:80/")
assert "PHP Version ${php.version}" in response, "PHP version not detected"
# Check so we have database and some other extensions loaded
for ext in ["json", "opcache", "pdo_mysql", "pdo_pgsql", "pdo_sqlite", "apcu"]:
assert ext in response, f"Missing {ext} extension"
machine.succeed(f'test -n "$(php -m | grep -i {ext})"')
'';
}

View File

@ -387,6 +387,10 @@ let
in
php;
inherit ztsSupport;
services.default = {
imports = [ ./service.nix ];
};
};
meta = with lib; {

View File

@ -0,0 +1,186 @@
{
options,
config,
pkgs,
lib,
...
}:
let
cfg = config.php-fpm;
format = pkgs.formats.iniWithGlobalSection { };
configFile = format.generate "php-fpm.conf" {
globalSection = lib.filterAttrs (_: v: !lib.isAttrs v) cfg.settings;
sections = lib.filterAttrs (_: lib.isAttrs) cfg.settings;
};
poolOpts =
{ name, ... }:
{
freeformType =
with lib.types;
attrsOf (oneOf [
str
int
bool
]);
options = {
listen = lib.mkOption {
type =
with lib.types;
oneOf [
path
port
str
];
default = "/run/php-fpm/${name}.sock";
description = ''
The address on which to accept FastCGI requests. Valid syntaxes are: `ip.add.re.ss:port`, `port`, `/path/to/unix/socket`.
'';
};
pm = lib.mkOption {
type = lib.types.enum [
"static"
"ondemand"
"dynamic"
];
description = ''
Choose how the process manager will control the number of child processes.
`static` - the number of child processes is fixed (`pm.max_children`).
`ondemand` - the processes spawn on demand (when requested, as opposed to `dynamic`, where `pm.start_servers` are started when the service is started).
`dynamic` - the number of child processes is set dynamically based on the following directives: `pm.max_children`, `pm.start_servers`, pm.min_spare_servers, `pm.max_spare_servers`.
'';
};
"pm.max_children" = lib.mkOption {
type = lib.types.int;
description = ''
The number of child processes to be created when `pm` is set to `static` and the maximum
number of child processes to be created when `pm` is set to `dynamic`.
This option sets the limit on the number of simultaneous requests that will be served.
'';
};
user = lib.mkOption {
type = lib.types.str;
description = ''
Unix user of FPM processes.
'';
};
};
};
in
{
_class = "service";
options.php-fpm = {
package = lib.mkPackageOption pkgs "php" {
example = ''
php.buildEnv {
extensions =
{ all, ... }:
with all;
[
imagick
opcache
];
extraConfig = "memory_limit=256M";
}
'';
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType =
with lib.types;
attrsOf (oneOf [
str
int
bool
(submodule poolOpts)
]);
options = {
log_level = lib.mkOption {
type = lib.types.enum [
"alert"
"error"
"warning"
"notice"
"debug"
];
default = "notice";
description = ''
Error log level.
'';
};
};
};
default = { };
example = lib.literalExpression ''
{
log_level = "debug";
log_limit = 2048;
mypool = {
"user" = "php";
"group" = "php";
"listen.owner" = "caddy";
"listen.group" = "caddy";
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.start_servers" = 10;
"pm.min_spare_servers" = 5;
"pm.max_spare_servers" = 20;
"pm.max_requests" = 500;
}
}
'';
description = ''
PHP FPM configuration. Refer to [upstream documentation](https://www.php.net/manual/en/install.fpm.configuration.php) for details on supported values.
'';
};
};
config = {
php-fpm.settings = {
error_log = "syslog";
daemonize = false;
};
process.argv = [
"${cfg.package}/bin/php-fpm"
"-y"
configFile
];
}
// lib.optionalAttrs (options ? systemd) {
systemd.service = {
after = [ "network.target" ];
documentation = [ "man:php-fpm(8)" ];
serviceConfig = {
Type = "notify";
ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
RuntimeDirectory = "php-fpm";
RuntimeDirectoryPreserve = true;
Restart = "always";
};
};
}
// lib.optionalAttrs (options ? finit) {
finit.service = {
conditions = [ "service/syslogd/ready" ];
reload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
notify = "systemd";
};
};
meta.maintainers = with lib.maintainers; [
aanderse
];
}