Files
Sovran_SystemsOS/modules/php.nix
T
naturallaw777 6151c78dc5 php: drop duplicate filter-test backport that breaks the php-filter build
flake.lock pins nixpkgs a8e753600fb4, which already ships php85 8.5.12
(81513f3640) and upstream's `filter` test fix (a5fc1be5b6).  Both commits
are ancestors of the pin, so the local backport in this module was dead
weight at best:

  * pkgs/development/interpreters/php/default.nix at the pin already says
    php85 = 8.5.12, so the `lib.versionAtLeast` guard was never false and
    the `.override { version / phpSrc }` branch never ran;
  * pkgs/top-level/php-packages.nix at the pin already carries the
    oom_filter_*.phpt substitution.

patchFilterTests appended that same substituteInPlace a second time:

  --replace-fail "'-n'," "'-n', '-d', 'extension=$PWD/modules/filter.so',"

The replacement text still contains the `'-n',` it searches for, so the
second pass matched and injected the extension flag twice.  php-cgi then
emitted `Module "filter" is already loaded` (E_CORE_WARNING) into the
output the OOM tests capture, all three oom_filter_*.phpt failed against
their --EXPECTF-- section, `make test` exited non-zero and the builder
died with exit code 2:

  error: Cannot build '...-php-filter-8.5.12.drv'.
  Reason: builder failed with exit code 2.

which then cascaded into php-extra-init-8.5.12.ini, php-with-extensions
and man-paths ("1 dependency failed").

Use the stock pkgs.php85 and let nixpkgs own the extension patches.  The
CVE-2026-109618 / CVE-2026-109619 floor is kept, but as an assert, so a
rolled-back pin fails loudly instead of silently rebuilding a version
under another release's extension recipes.
2026-10-26 21:19:55 -05:00

139 lines
6.0 KiB
Nix
Executable File

{ config, pkgs, lib, ... }:
# ── Shared PHP for Nextcloud + WordPress ──────────────────────────────────────
#
# One interpreter (with one extension set and one php.ini) is shared by the
# phpfpm-nextcloud and phpfpm-wordpress pools, the Nextcloud cron job and the
# occ / wp-cli helper scripts. Every consumer must reference
# config.sovran_systemsOS.phpPackage (or /run/current-system/sw/bin/php) so
# that the CLI and the FPM pools always run the *same* PHP.
#
# Version policy (September 2026):
# • Nextcloud 35 supports PHP 8.3 / 8.4 / 8.5 and recommends 8.5. Its setup
# check flags 8.3 as "deprecated since Nextcloud 35" and warns that
# Nextcloud 36 may require at least 8.4.
# • WordPress 6.9 / 7.0 fully support PHP 8.4 and 8.5.
# • PHP 8.3 has been security-only since 2025-12-31; PHP 8.4 leaves active
# support on 2026-12-31; PHP 8.5 is actively supported until 2027-12-31.
#
# To fall back to PHP 8.4, change only the `phpBase` line below (and drop the
# security floor to the matching 8.4.x release).
#
# Security floor (October 2026):
# CVE-2026-109618 (RCE via OOM corruption) and CVE-2026-109619 (RCE via
# stale global state) are critical, unauthenticated flaws in PHP itself,
# CVSS v4.0 9.2 each, fixed in 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 on
# 2026-10-21. PHP-FPM is named as susceptible in both advisories, so the
# pools below are in scope; updating is the only complete mitigation.
#
# nixpkgs bumped php85 to 8.5.12 in 81513f364091c759812f716cef3c175109d07342
# and fixed the `filter` extension tests in
# a5fc1be5b6c2d0c934143b57363aef9a15cce508. flake.lock pins nixpkgs
# a8e753600fb48f8f0dd882cc5ad284438241f85a, which is *after* both of them
# (verified: pkgs/development/interpreters/php/default.nix at that rev says
# php85 = 8.5.12, and pkgs/top-level/php-packages.nix already carries the
# oom_filter_*.phpt patch). So the stock package is used as-is and the
# floor below is only an assertion that catches a rolled-back pin.
#
# Do NOT re-apply the `filter` test fix locally. It uses
# --replace-fail "'-n'," "'-n', '-d', 'extension=$PWD/modules/filter.so',"
# and the replacement text still contains the `'-n',` it searches for, so a
# second application silently injects `-d extension=.../filter.so` twice.
# PHP then emits `Module "filter" is already loaded` (Zend/zend_API.c,
# E_CORE_WARNING) into the php-cgi output the tests capture, all three
# oom_filter_*.phpt fail on the unexpected line, `make test` exits non-zero
# and the builder dies with exit code 2 — the exact failure the patch was
# meant to prevent.
let
# The first 8.5.x release that carries the fixes above. Bump only upward.
phpSecurityFloor = "8.5.12";
# Stock nixpkgs package: correct version, correct extension recipes and
# upstream's own test fixes. `.override { version = ...; phpSrc = ...; }`
# is deliberately *not* used here — rewriting the version while keeping the
# extension recipes of another release is how you end up with test (or
# ABI) failures that look like packaging bugs.
phpBase = pkgs.php85;
custom-php = phpBase.buildEnv {
# `enabled` is nixpkgs' default extension set. It already contains every
# module Nextcloud lists as required or recommended (ctype, curl, dom,
# fileinfo, gd, intl, mbstring, openssl, posix, session, simplexml,
# xmlreader, xmlwriter, zip, zlib, pdo_pgsql, pdo_mysql, bcmath, gmp,
# exif, sodium, sysvsem, pcntl, filter, ...). OPcache is compiled into
# PHP >= 8.5 and no longer appears as a separate extension.
extensions = { enabled, all }: enabled ++ (with all; [
bz2 # Nextcloud: bz2 archive support
apcu # Nextcloud: memcache.local (apc.enable_cli=1 below is mandatory for occ + cron)
redis # Nextcloud: memcache.distributed / file locking once a Redis server is configured
imagick # Nextcloud: previews + theming (nixpkgs ImageMagick is built with SVG support)
memcached # WordPress object-cache plugins (legacy option for Nextcloud)
]);
extraConfig = ''
; ── Error handling (production) ─────────────────────────────────
display_errors = Off
display_startup_errors = Off
log_errors = On
; ── Limits ──────────────────────────────────────────────────────
max_execution_time = 10000
max_input_time = 3000
memory_limit = 1G
post_max_size = 3G
upload_max_filesize = 3G
; ── OPcache (Nextcloud "Server tuning" recommendations) ─────────
opcache.enable = 1
opcache.memory_consumption = 512
opcache.interned_strings_buffer = 192
opcache.max_accelerated_files = 20000
opcache.revalidate_freq = 240
opcache.save_comments = 1
; ── APCu ────────────────────────────────────────────────────────
apc.enable_cli = 1
; ── phpredis session locking (only used with session.save_handler = redis)
redis.session.locking_enabled = 1
redis.session.lock_retries = -1
redis.session.lock_wait_time = 10000
'';
};
in
assert lib.assertMsg (lib.versionAtLeast phpBase.version phpSecurityFloor) ''
sovran_systemsOS: the pinned nixpkgs ships PHP ${phpBase.version}, below the
security floor ${phpSecurityFloor} (CVE-2026-109618 / CVE-2026-109619).
Update the nixpkgs input in flake.lock instead of pinning a version here.
'';
{
options.sovran_systemsOS.phpPackage = lib.mkOption {
type = lib.types.package;
default = custom-php;
description = "Shared PHP package with all extensions for Sovran_SystemsOS services";
};
config = {
users.users = {
php = {
isSystemUser = true;
createHome = false;
uid = 7777;
};
};
users.users.php.group = "php";
users.groups.php = {};
environment.systemPackages = with pkgs; [
custom-php
];
};
}