From 5e0c688e1dab677701c75ef31592937fba962417 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Tue, 19 May 2026 16:25:25 +0200 Subject: [PATCH 1/3] docs: expand PHP-FPM tuning section in server_tuning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the two-sentence stub with real content covering: - pm modes (dynamic/static/ondemand) with trade-offs and Nextcloud guidance (ondemand not recommended; sync clients cause repeated cold starts) - Key parameters: pm.max_children, start/min/max spare servers, pm.max_requests, pm.process_idle_timeout — with the RAM-based sizing formula and how to measure actual worker RSS - Example dynamic config for 2 GB PHP RAM - Slow log setup (slowlog + request_slowlog_timeout) - Troubleshooting section: 502, 504, memory growth, cold-start lag - Cross-reference to source_installation.rst for pool/env-var detail Fixes #11591 Signed-off-by: skjnldsv --- admin_manual/installation/server_tuning.rst | 137 +++++++++++++++++++- 1 file changed, 132 insertions(+), 5 deletions(-) diff --git a/admin_manual/installation/server_tuning.rst b/admin_manual/installation/server_tuning.rst index 94248210e5a..a3ecf3da8df 100644 --- a/admin_manual/installation/server_tuning.rst +++ b/admin_manual/installation/server_tuning.rst @@ -139,12 +139,139 @@ HTTP/2 has `huge speed improvements `_ can help you calculate the optimal values for your system. +Process manager modes +^^^^^^^^^^^^^^^^^^^^^ + +The ``pm`` directive controls how PHP-FPM manages its worker processes: + +.. list-table:: + :header-rows: 1 + :widths: 15 85 + + * - Mode + - Behaviour + * - ``dynamic`` + - Keeps between ``pm.min_spare_servers`` and ``pm.max_spare_servers`` idle workers alive, + up to a ceiling of ``pm.max_children``. Good default for most Nextcloud installations: + balances RAM efficiency with burst capacity. Set ``pm.min_spare_servers`` high enough + that sync-client poll bursts do not stall waiting for new processes to spawn. + * - ``static`` + - Always keeps exactly ``pm.max_children`` processes running. Highest memory use, + lowest latency. Use on dedicated servers with predictable load. Always set + ``pm.max_requests`` to recycle workers and prevent memory leaks. + * - ``ondemand`` + - Spawns a worker only when a request arrives; kills idle workers after + ``pm.process_idle_timeout`` (default ``10s``). Lowest memory use but adds + cold-start latency on every burst. Not recommended for Nextcloud: desktop and + mobile clients poll every 30 seconds, repeatedly triggering cold starts. + +Key parameters +^^^^^^^^^^^^^^ + +``pm.max_children`` + Maximum (or fixed, under ``static``) number of simultaneous worker processes. + This is the most important value to tune. If all workers are busy, new requests + queue up; a full queue produces 502/504 errors. + + Estimate it from available RAM:: + + pm.max_children = floor(available_RAM_for_PHP / average_worker_RSS) + + Measure the average RSS of a running pool:: + + ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1} END {print sum/NR/1024 " MB"}' + + A typical Nextcloud worker uses **50–100 MB** (more if Imagick or LDAP is loaded). + Leave headroom for the OS, web server, database, and cache. Setting ``pm.max_children`` + too high causes swapping, which is worse than queuing. + +``pm.start_servers`` *(dynamic only)* + Workers started at FPM boot. Defaults to + ``(pm.min_spare_servers + pm.max_spare_servers) / 2`` if not set. + +``pm.min_spare_servers`` / ``pm.max_spare_servers`` *(dynamic only)* + Range of idle workers kept warm. For Nextcloud, keep ``pm.min_spare_servers`` + high enough to absorb a sync-client burst without spawning new processes:: + + pm.min_spare_servers = 4 # adjust upward for many connected clients + pm.max_spare_servers = 16 + +``pm.max_requests`` + Recycle a worker after this many requests. ``0`` means never recycle. + Setting a value of ``500``–``1000`` guards against slow memory growth from + leaky extensions (Imagick, LDAP, SAML XML parsers). Essential under ``static`` + mode. + +``pm.process_idle_timeout`` *(ondemand only)* + How long an idle worker lives before being killed. Default: ``10s``. + +Example configuration +^^^^^^^^^^^^^^^^^^^^^ + +A starting point for ``dynamic`` mode on a server with 2 GB of RAM dedicated to PHP +(adjust ``pm.max_children`` based on your measured worker RSS): + +.. code-block:: ini + + pm = dynamic + pm.max_children = 30 + pm.start_servers = 8 + pm.min_spare_servers = 4 + pm.max_spare_servers = 16 + pm.max_requests = 500 + +Use the `PHP-FPM process calculator `_ as a +cross-check for your values. + +Slow log +^^^^^^^^ + +Enable the slow log to identify PHP scripts that are taking too long: + +.. code-block:: ini + + slowlog = /var/log/php-fpm-slow.log + request_slowlog_timeout = 5s + +Each entry records the full PHP backtrace of the slow request. This is the +fastest way to find the root cause of gateway timeouts and sluggish pages. + +Troubleshooting +^^^^^^^^^^^^^^^ + +**502 Bad Gateway** + All ``pm.max_children`` workers are busy. Increase ``pm.max_children`` if RAM + allows. Enable the slow log to check whether a slow query is tying up workers. + Also check that a ``request_terminate_timeout`` is not killing workers mid-request. + +**504 Gateway Timeout** + A worker is running but not responding within the web server's upstream timeout + (nginx ``fastcgi_read_timeout``, Apache ``ProxyTimeout``). Common Nextcloud causes: + large file operations, slow database queries during sync, or PROPFIND over large + directory trees. Use the slow log to identify the bottleneck. + +**Memory grows over time** + Workers are leaking memory (Imagick and XML parsers are common sources). + Set ``pm.max_requests = 500`` to recycle them before they grow too large. + +**Slow first request after idle** + ``pm = ondemand`` or ``pm.min_spare_servers`` too low. Switch to ``pm = dynamic`` + and raise ``pm.min_spare_servers``. + +After any configuration change, reload PHP-FPM — changes do not take effect until you do: + +.. code-block:: bash + + sudo systemctl reload php8.3-fpm # Debian/Ubuntu — adjust version as needed + sudo systemctl reload php-fpm # RHEL/Fedora + +For pool configuration details (environment variables, upload sizes, Unix socket vs TCP), +see :ref:`php_fpm_tips_label` in the installation guide. Enable PHP OPcache ------------------ From df99ddc48f0b143c2716dd88f73de90721c001d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Wed, 20 May 2026 06:48:06 +0200 Subject: [PATCH 2/3] fix: replace overflowing list-table with definition list for pm modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The list-table with widths 15/85 caused horizontal overflow in the rendered HTML. Definition list avoids the issue and is more idiomatic RST for key-value mode descriptions. Signed-off-by: John Molakvoæ (skjnldsv) --- admin_manual/installation/server_tuning.rst | 36 +++++++++------------ 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/admin_manual/installation/server_tuning.rst b/admin_manual/installation/server_tuning.rst index a3ecf3da8df..0ea4dae284c 100644 --- a/admin_manual/installation/server_tuning.rst +++ b/admin_manual/installation/server_tuning.rst @@ -149,26 +149,22 @@ Process manager modes The ``pm`` directive controls how PHP-FPM manages its worker processes: -.. list-table:: - :header-rows: 1 - :widths: 15 85 - - * - Mode - - Behaviour - * - ``dynamic`` - - Keeps between ``pm.min_spare_servers`` and ``pm.max_spare_servers`` idle workers alive, - up to a ceiling of ``pm.max_children``. Good default for most Nextcloud installations: - balances RAM efficiency with burst capacity. Set ``pm.min_spare_servers`` high enough - that sync-client poll bursts do not stall waiting for new processes to spawn. - * - ``static`` - - Always keeps exactly ``pm.max_children`` processes running. Highest memory use, - lowest latency. Use on dedicated servers with predictable load. Always set - ``pm.max_requests`` to recycle workers and prevent memory leaks. - * - ``ondemand`` - - Spawns a worker only when a request arrives; kills idle workers after - ``pm.process_idle_timeout`` (default ``10s``). Lowest memory use but adds - cold-start latency on every burst. Not recommended for Nextcloud: desktop and - mobile clients poll every 30 seconds, repeatedly triggering cold starts. +``dynamic`` + Keeps between ``pm.min_spare_servers`` and ``pm.max_spare_servers`` idle workers alive, + up to a ceiling of ``pm.max_children``. Good default for most Nextcloud installations: + balances RAM efficiency with burst capacity. Set ``pm.min_spare_servers`` high enough + that sync-client poll bursts do not stall waiting for new processes to spawn. + +``static`` + Always keeps exactly ``pm.max_children`` processes running. Highest memory use, + lowest latency. Use on dedicated servers with predictable load. Always set + ``pm.max_requests`` to recycle workers and prevent memory leaks. + +``ondemand`` + Spawns a worker only when a request arrives; kills idle workers after + ``pm.process_idle_timeout`` (default ``10s``). Lowest memory use but adds + cold-start latency on every burst. Not recommended for Nextcloud: desktop and + mobile clients poll every 30 seconds, repeatedly triggering cold starts. Key parameters ^^^^^^^^^^^^^^ From 4e40d5717ab84bb8c14c63de608e64e4f93c7e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6?= Date: Thu, 21 May 2026 09:21:40 +0200 Subject: [PATCH 3/3] fix(admin): adjust php fpm command and workers memory leak comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: John Molakvoæ Signed-off-by: John Molakvoæ --- admin_manual/installation/server_tuning.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin_manual/installation/server_tuning.rst b/admin_manual/installation/server_tuning.rst index 0ea4dae284c..354195de369 100644 --- a/admin_manual/installation/server_tuning.rst +++ b/admin_manual/installation/server_tuning.rst @@ -180,7 +180,7 @@ Key parameters Measure the average RSS of a running pool:: - ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1} END {print sum/NR/1024 " MB"}' + ps --no-headers -o rss -C php-fpm | awk '{sum+=$1; count++} END {if (count>0) print sum/count/1024 " MB"; else print "No php-fpm processes found"}' A typical Nextcloud worker uses **50–100 MB** (more if Imagick or LDAP is loaded). Leave headroom for the OS, web server, database, and cache. Setting ``pm.max_children`` @@ -252,7 +252,7 @@ Troubleshooting directory trees. Use the slow log to identify the bottleneck. **Memory grows over time** - Workers are leaking memory (Imagick and XML parsers are common sources). + Memory leaks can occur in worker processes. Common culprits include libraries that manage external resources (like Imagick for image processing). Use the slow log and RSS monitoring to identify which requests cause growth. Set ``pm.max_requests = 500`` to recycle them before they grow too large. **Slow first request after idle**