Site down after a crash? Make Nginx and PHP-FPM restart on their own

If Nginx crashes or is killed when the server runs out of memory, it stays down. Your site is offline until someone logs in and starts it again, even at 3 a.m. One small setting tells the system to start it again by itself.

We tested this guide on Ubuntu 24.04 (Nginx 1.24, PHP 8.3) and Debian 13 (Nginx 1.26, PHP 8.4), each in a fresh container with systemd. We "crashed" each service by force-killing it (kill -9, the same signal the out-of-memory killer uses) and watched what happened. The Apache line was checked on Ubuntu only.

1. What happens today?

Each service has a Restart setting. See yours (use your PHP version in place of 8.3):

systemctl show nginx php8.3-fpm mariadb -p Id -p Restart

This is what we found on fresh systems:

  • Nginx: Restart=no on both. After a crash it stayed failed and the site was down.
  • PHP-FPM: no on Ubuntu 24.04, so PHP pages gave errors after a crash. Debian 13 already has on-failure, and it came back.
  • MariaDB: on-abnormal on both. It came back by itself after a crash. Leave it as it is.
  • Redis: always. Apache (Ubuntu): on-abort.

Small crashes are already handled. When one Nginx or PHP-FPM worker dies, the main process starts a new one, and we saw the site keep working. This guide is about the main process dying.

2. Turn on automatic restart

sudo systemctl edit nginx

An editor opens. Type these three lines in the empty space near the top, between the two comment lines:

[Service]
Restart=on-failure
RestartSec=5s

Save and close. The system saves it in /etc/systemd/system/nginx.service.d/override.conf and uses it straight away. Package updates won't overwrite it.

  • on-failure: start again after a crash or an error, but not when you stop it yourself with systemctl stop. We checked that too.
  • RestartSec=5s: wait 5 seconds first, so a broken service doesn't restart in a tight loop.

Do the same for PHP-FPM on Ubuntu:

sudo systemctl edit php8.3-fpm

Check that it took:

systemctl show nginx -p Restart -p RestartUSec
Restart=on-failure
RestartUSec=5s

3. Test it

Do this at a quiet time. The site is down for about 5 seconds:

sudo kill -9 $(systemctl show -p MainPID --value nginx)
systemctl is-active nginx

Right after the kill it says activating. Wait a few seconds and ask again: active. In our test the site answered again after about 5 seconds. Without the setting, it stayed failed.

4. Notice when it happens

An automatic restart hides the problem. It doesn't fix it. So check now and then:

journalctl -u nginx | grep "Scheduled restart"
systemctl show nginx -p NRestarts

A line like nginx.service: Scheduled restart job, restart counter is at 1. means it crashed and came back. If you see it, find out why. Memory is the usual cause: see out of memory and the OOM killer. For outside checks that email you when the site is down, see uptime monitoring.

If the config is broken, it keeps trying. We broke the Nginx config and crashed it. It tried again every 5 seconds, stayed down, and came back by itself as soon as we fixed the file. So a restart loop in the log usually means a config or startup problem: see Nginx won't start.

If something goes wrong

  • "Cannot edit units if not on a tty": you ran systemctl edit from a script. Run it in a normal SSH session.
  • Undo it: sudo systemctl revert nginx removes your override and goes back to the package's settings.
  • See everything that applies: systemctl cat nginx shows the package file and your override below it.
  • Still down after a reboot? Check it starts at boot: systemctl is-enabled nginx should say enabled. If not: sudo systemctl enable nginx.

Official sources

Next steps: for all the logs in one place, see where are the logs. For 502 errors while PHP-FPM is down, see 502 and 504 errors.

ServerNest is being built to notice crashed services and restarts, and tell you why they happened. Join early access to try it first.

← Back to the security blog