@@ -139,12 +139,139 @@ HTTP/2 has `huge speed improvements <https://www.troyhunt.com/i-wanna-go-fast-ht
139139Tune PHP-FPM
140140------------
141141
142- The default configuration of PHP-FPM is extremely conservative. You might notice
143- excessive load times on the web interface or even sync issues. Each simultaneous
144- request is handled by a separate PHP-FPM process, so even on a small installation you
145- should allow more processes to run in parallel to handle requests .
142+ PHP-FPM is required for Nginx setups and is widely used with Apache as well. Its default
143+ configuration is extremely conservative: the default pool has `` pm.max_children = 5 ``, which
144+ limits Nextcloud to five simultaneous PHP requests and is a common cause of gateway timeouts,
145+ slow page loads, and sync client errors under any real load .
146146
147- `This link <https://spot13.com/pmcalculator/ >`_ can help you calculate the optimal values for your system.
147+ Process manager modes
148+ ^^^^^^^^^^^^^^^^^^^^^
149+
150+ The ``pm `` directive controls how PHP-FPM manages its worker processes:
151+
152+ .. list-table ::
153+ :header-rows: 1
154+ :widths: 15 85
155+
156+ * - Mode
157+ - Behaviour
158+ * - ``dynamic ``
159+ - Keeps between ``pm.min_spare_servers `` and ``pm.max_spare_servers `` idle workers alive,
160+ up to a ceiling of ``pm.max_children ``. Good default for most Nextcloud installations:
161+ balances RAM efficiency with burst capacity. Set ``pm.min_spare_servers `` high enough
162+ that sync-client poll bursts do not stall waiting for new processes to spawn.
163+ * - ``static ``
164+ - Always keeps exactly ``pm.max_children `` processes running. Highest memory use,
165+ lowest latency. Use on dedicated servers with predictable load. Always set
166+ ``pm.max_requests `` to recycle workers and prevent memory leaks.
167+ * - ``ondemand ``
168+ - Spawns a worker only when a request arrives; kills idle workers after
169+ ``pm.process_idle_timeout `` (default ``10s ``). Lowest memory use but adds
170+ cold-start latency on every burst. Not recommended for Nextcloud: desktop and
171+ mobile clients poll every 30 seconds, repeatedly triggering cold starts.
172+
173+ Key parameters
174+ ^^^^^^^^^^^^^^
175+
176+ ``pm.max_children ``
177+ Maximum (or fixed, under ``static ``) number of simultaneous worker processes.
178+ This is the most important value to tune. If all workers are busy, new requests
179+ queue up; a full queue produces 502/504 errors.
180+
181+ Estimate it from available RAM::
182+
183+ pm.max_children = floor(available_RAM_for_PHP / average_worker_RSS)
184+
185+ Measure the average RSS of a running pool::
186+
187+ ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1} END {print sum/NR/1024 " MB"}'
188+
189+ A typical Nextcloud worker uses **50–100 MB ** (more if Imagick or LDAP is loaded).
190+ Leave headroom for the OS, web server, database, and cache. Setting ``pm.max_children ``
191+ too high causes swapping, which is worse than queuing.
192+
193+ ``pm.start_servers `` *(dynamic only) *
194+ Workers started at FPM boot. Defaults to
195+ ``(pm.min_spare_servers + pm.max_spare_servers) / 2 `` if not set.
196+
197+ ``pm.min_spare_servers `` / ``pm.max_spare_servers `` *(dynamic only) *
198+ Range of idle workers kept warm. For Nextcloud, keep ``pm.min_spare_servers ``
199+ high enough to absorb a sync-client burst without spawning new processes::
200+
201+ pm.min_spare_servers = 4 # adjust upward for many connected clients
202+ pm.max_spare_servers = 16
203+
204+ ``pm.max_requests ``
205+ Recycle a worker after this many requests. ``0 `` means never recycle.
206+ Setting a value of ``500 ``–``1000 `` guards against slow memory growth from
207+ leaky extensions (Imagick, LDAP, SAML XML parsers). Essential under ``static ``
208+ mode.
209+
210+ ``pm.process_idle_timeout `` *(ondemand only) *
211+ How long an idle worker lives before being killed. Default: ``10s ``.
212+
213+ Example configuration
214+ ^^^^^^^^^^^^^^^^^^^^^
215+
216+ A starting point for ``dynamic `` mode on a server with 2 GB of RAM dedicated to PHP
217+ (adjust ``pm.max_children `` based on your measured worker RSS):
218+
219+ .. code-block :: ini
220+
221+ pm = dynamic
222+ pm.max_children = 30
223+ pm.start_servers = 8
224+ pm.min_spare_servers = 4
225+ pm.max_spare_servers = 16
226+ pm.max_requests = 500
227+
228+ Use the `PHP-FPM process calculator <https://spot13.com/pmcalculator/ >`_ as a
229+ cross-check for your values.
230+
231+ Slow log
232+ ^^^^^^^^
233+
234+ Enable the slow log to identify PHP scripts that are taking too long:
235+
236+ .. code-block :: ini
237+
238+ slowlog = /var/log/php-fpm-slow.log
239+ request_slowlog_timeout = 5s
240+
241+ Each entry records the full PHP backtrace of the slow request. This is the
242+ fastest way to find the root cause of gateway timeouts and sluggish pages.
243+
244+ Troubleshooting
245+ ^^^^^^^^^^^^^^^
246+
247+ **502 Bad Gateway **
248+ All ``pm.max_children `` workers are busy. Increase ``pm.max_children `` if RAM
249+ allows. Enable the slow log to check whether a slow query is tying up workers.
250+ Also check that a ``request_terminate_timeout `` is not killing workers mid-request.
251+
252+ **504 Gateway Timeout **
253+ A worker is running but not responding within the web server's upstream timeout
254+ (nginx ``fastcgi_read_timeout ``, Apache ``ProxyTimeout ``). Common Nextcloud causes:
255+ large file operations, slow database queries during sync, or PROPFIND over large
256+ directory trees. Use the slow log to identify the bottleneck.
257+
258+ **Memory grows over time **
259+ Workers are leaking memory (Imagick and XML parsers are common sources).
260+ Set ``pm.max_requests = 500 `` to recycle them before they grow too large.
261+
262+ **Slow first request after idle **
263+ ``pm = ondemand `` or ``pm.min_spare_servers `` too low. Switch to ``pm = dynamic ``
264+ and raise ``pm.min_spare_servers ``.
265+
266+ After any configuration change, reload PHP-FPM — changes do not take effect until you do:
267+
268+ .. code-block :: bash
269+
270+ sudo systemctl reload php8.3-fpm # Debian/Ubuntu — adjust version as needed
271+ sudo systemctl reload php-fpm # RHEL/Fedora
272+
273+ For pool configuration details (environment variables, upload sizes, Unix socket vs TCP),
274+ see :ref: `php_fpm_tips_label ` in the installation guide.
148275
149276Enable PHP OPcache
150277------------------
0 commit comments