Emergency server help: get in touch

DirectAdmin 503 PHP-FPM Errors: Log Checks

Diagnosing 503 errors from PHP-FPM sites on DirectAdmin now that pool logs go to the systemd journal, covering exhausted workers, socket permission faults, per-user pool settings and the CustomBuild override that makes fixes survive rebuilds.

Published Updated 6 min read

A 503 from a PHP site on DirectAdmin means the web server accepted the request and could not hand it to PHP-FPM: the socket was missing, refused the connection, or every worker in the pool was busy. Since CustomBuild moved PHP-FPM logging into the systemd journal in 1.689, administrators used to reading /usr/local/php84/var/log/php-fpm.log sometimes conclude there are no logs at all. There are, and they explain the failure quickly once you know the service and pool names.

Short answer: Since 1.689 each PHP version logs to the systemd journal, so run journalctl -u php-fpm84 --since '30 min ago' alongside the domain’s web-server error log. A max_children message means the user’s pool is exhausted and needs a larger limit via their package or the custom template; a connect() to unix:... failed message means the pool did not start or the socket permissions are wrong; a 503 on every site right after a rebuild needs systemctl daemon-reload, a unit restart and da build rewrite_confs.

Find the logs

Each PHP version runs as its own systemd unit, named after the version without the dot. Recent errors for PHP 8.4 are one command away:

systemctl status php-fpm84
journalctl -u php-fpm84 --since '30 min ago'

The web server’s own error log is the other half of the picture. For Apache the global log is /var/log/httpd/error_log and the per-domain log is /var/log/httpd/domains/example.com.error.log; for nginx substitute /var/log/nginx/. The pairing of a journal line and a web-server line usually names the cause outright.

Slow-request logs, if enabled in the pool, also go to the journal, and pm.status_path gives a live view when configured.

Cause one: the pool ran out of workers

The journal line reads something like server reached pm.max_children setting, consider raising it. The pool for that user has every worker occupied, and the web server times out waiting. Check the pool’s settings:

grep -E 'pm\.|pm =' /usr/local/directadmin/data/users/USER/php/php-fpm84.conf

DirectAdmin generates one pool per user from the template in /usr/local/directadmin/data/templates/php-fpm.conf, and applies the user’s package settings for the maximum children. Raising the limit for one user is done through their package or from the user’s PHP settings page in Evolution, then rewritten:

da build rewrite_confs

Raising it globally means the template. Copy it to /usr/local/directadmin/data/templates/custom/php-fpm.conf and edit there, or the next CustomBuild update reverts it. The right value depends on memory: each worker holds roughly the site’s peak memory usage, so a WordPress site with 80 MB per request and twenty children needs about 1.6 GB reserved for that pool alone.

Also check whether the workers are stuck rather than busy. A database that stopped answering leaves every worker waiting on a query; the fix is on the database side, and MySQL too many connections describes the same chain on any panel.

Cause two: the socket does not exist or is not readable

The web-server log says connect() to unix:/usr/local/php84/sockets/USER.sock failed (2: No such file or directory) or (13: Permission denied). The first means the pool did not start, and the journal says why, usually a syntax error in a custom pool file or a PHP version that was removed from CustomBuild while the domain still selected it. The second is ownership on the socket directory, which occasionally breaks after a manual chmod on /usr/local/php84.

ls -l /usr/local/php84/sockets/
da build rewrite_confs
systemctl restart php-fpm84

If the user’s domain selects a PHP version that is no longer installed, the socket for that version never appears. Check the domain’s setting and the installed set with da build options | grep php and correct the mismatch, either by installing the version or moving the domain.

Cause three: rebuild left a stale unit

After a da build php that upgraded PHP, the old unit sometimes lingers while the new one is enabled but not started. The symptom is a 503 on every site of that version immediately after a rebuild. A restart of the unit and a configuration rewrite resolves it:

systemctl daemon-reload
systemctl restart php-fpm84
da build rewrite_confs

Common pitfall: editing the generated pool file

The obvious fix for a single user is to edit /usr/local/directadmin/data/users/USER/php/php-fpm84.conf directly. It works until the next rewrite, which regenerates the file from the template and the user’s settings. Every rewrite, including the one triggered by adding a domain, silently undoes the change and the 503 returns days later. Make the change through the package or the custom template so it persists, and reserve direct edits for confirming a hypothesis.

Verify

Load the site and confirm a 200, then confirm the pool is healthy and the worker count is below the limit:

curl -sI https://example.com/ | head -1
journalctl -u php-fpm84 --since '5 min ago' | grep -c 'max_children'

The second command should return zero after the fix. For an ongoing view, enable pm.status_path = /fpm-status in the custom template and restrict it to localhost in the web server, then poll it from your monitoring. Our server security audit script includes a check for world-writable socket directories, which is one of the permission faults above in waiting.

DirectAdmin 503 PHP-FPM at a glance

DirectAdmin 503 PHP-FPM Errors summary card: Since 1.689 each PHP version logs to the systemd journal, so run journalctl -u php-fpm84 --since '30 min ago' alongside…
In short: Since 1.689 each PHP version logs to the systemd journal, so run journalctl -u php-fpm84 –since ’30 min ago’ alongside the domain’s web-server error log.

Official documentation: DirectAdmin documentation, Linux man pages.

Related guides: Running Node.js and Python apps with Nginx Unit and per-user Redis on DirectAdmin · Choosing a web stack in CustomBuild: Apache, nginx_apache, OpenLiteSpeed or LiteSpeed · Choosing a VPS for a cPanel or DirectAdmin server in 2026.

Frequently asked questions

Does raising pm.max_children in the user’s php-fpm84.conf fix the 503 permanently?

No. That file is regenerated from the template on every rewrite, including when a domain is added, so the change disappears; set the limit through the user’s package or a copy of the template under data/templates/custom instead.

How long should the journal be searched after a 503?

Start with the last thirty minutes, because the failure is usually recent, then widen with –since to the last rebuild or restart if the errors are intermittent.

Can a 503 on DirectAdmin be caused by the database rather than PHP-FPM?

Yes. If MariaDB stops answering, every worker waits on a query and the pool fills; the journal still shows max_children, but the fix is on the database side, so check connections and slow queries before raising pool limits.

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.