Restart Failed Linux Services Automatically with systemd
Stop babysitting crashed daemons. Learn systemd’s native restart policies, copy-paste unit overrides, and fix the three failure modes Australian site owners hit most—before you book remote help.
If a critical service on your VPS or office Linux box dies overnight and stays down until someone notices, this guide is for you. You will learn how systemd’s native process monitoring works, how to enable automatic restarts with real unit directives, and how to verify the setup on common Australian-hosted servers (Ubuntu, Debian, Rocky/Alma).
Homeowners running a small business site, sole traders on a single droplet, and local operators often discover outages only when customers complain. Fixwebnode provides direct remote Linux administration for this exact problem across Australia—not a freelance marketplace. If you want hands-on help after the DIY steps, start at Fixwebnode website repair Australia.
Why automatic service restarts matter on Linux
systemd is the init system on virtually every modern Linux distribution. It already supervises your units: it knows when a process exits, what exit code it returned, and whether the failure was clean or crash-like. Without a restart policy, a failed nginx, php-fpm, redis, or custom app unit simply stays inactive until a human runs systemctl start.
Native process monitoring is not a third-party watchdog. It is built into the service manager: StartLimitBurst, RestartSec, and Restart= control how aggressively systemd brings a unit back. Configured correctly, brief crashes recover in seconds. Configured poorly, you get restart loops, masked rate limits, or silent “failed” states that never recover.
This post stays on that architecture and the step-by-step enablement path—commands, drop-in overrides, and verification—so Australian operators can harden uptime without guessing.
How do I automatically restart a failed Linux service with systemd in Australia?
Add a systemd drop-in (or edit the unit) so Restart= is set to on-failure or always, pair it with RestartSec= and sensible start limits, then run daemon-reload and restart the unit. Confirm with systemctl show and a controlled kill test. If the service still flaps or hits StartLimit, escalate to a specialist rather than widening the restart window blindly.
| Symptom | Quick fix | When to call Fixwebnode |
|---|---|---|
| Service stays failed after crash | Set Restart=on-failure + RestartSec in a drop-in | Unit is vendor-locked or override ignored |
| Restart loop / StartLimit hit | Tune StartLimitBurst/Interval; fix root crash | App core-dumps or OOM every few minutes |
| Only main PID dies; dependents hang | Restart=always; check Type= and PIDFile | Complex multi-unit stacks (web + queue + DB) |
The architecture of native process monitoring
systemd tracks each service as a unit with a main process (and optionally control groups of children). When the main process exits, systemd classifies the result:
- success — clean exit code 0 (or success exit status list)
- failure — non-zero exit, signal kill, timeout, or watchdog miss
- abnormal — covered by broader policies such as
Restart=always
Key directives you will use:
Restart=—no(default for many units),on-success,on-failure,on-abnormal,on-watchdog,on-abort, oralwaysRestartSec=— delay before the next start attempt (e.g.5s)StartLimitIntervalSec=andStartLimitBurst=— rate limit to stop infinite crash loopsWatchdogSec=— optional hardware-style keepalive if the app supports sd_notify
Prefer drop-in overrides under /etc/systemd/system/<unit>.d/ instead of editing files in /lib/systemd/system/. Package upgrades overwrite vendor units; drop-ins survive.
Step-by-step: enabling automated service restarts
Prerequisites: SSH access with sudo, and the exact unit name (for example nginx.service or php8.3-fpm.service). These steps work on Ubuntu 22.04/24.04, Debian 12, and RHEL-family hosts commonly used by Australian small businesses.
Step 1 — Identify the unit and current restart policy
systemctl list-units --type=service --state=running
systemctl status nginx.service
systemctl show nginx.service -p Restart -p RestartSec -p StartLimitIntervalSec -p StartLimitBurst -p ActiveState -p SubState
Note whether Restart is already set. Many stock units use Restart=no or only restart on abnormal signals.
Step 2 — Create a drop-in override
sudo systemctl edit nginx.service
That opens an editor for /etc/systemd/system/nginx.service.d/override.conf. Paste a focused policy:
[Service]
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60s
StartLimitBurst=5
Use Restart=always only when you truly want restarts even after a clean stop-by-exit (rare for long-running daemons that exit 0 on purpose). For web stacks, on-failure is usually correct.
Step 3 — Reload systemd and apply
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
systemctl show nginx.service -p Restart -p RestartSec -p StartLimitBurst
Expected: Restart=on-failure and your timing values reflected.
Step 4 — Controlled failure test
# Find main PID
systemctl show nginx.service -p MainPID
# Simulate crash (SIGKILL) — service should return to active
sudo kill -9 $(systemctl show -p MainPID --value nginx.service)
sleep 6
systemctl status nginx.service --no-pager
Within roughly RestartSec, the unit should be active (running) again. Check the journal:
journalctl -u nginx.service -n 30 --no-pager
You should see a failure, then an automatic start.
Step 5 — Optional watchdog for notify-capable apps
If the service supports systemd notifications (Type=notify), you can add:
[Service]
WatchdogSec=30s
Restart=on-watchdog
Only enable this when documentation confirms sd_notify watchdog support; otherwise the unit will be killed for missing pings.
Step 6 — Persist documentation for your team
systemctl cat nginx.service
ls -la /etc/systemd/system/nginx.service.d/
Commit the override path to your runbook so the next admin does not “fix” a crash that was already auto-recovered.
Common issues with systemd automatic restarts
These are distinct failure modes Australian operators hit when enabling native monitoring—not generic “server is slow” complaints.
Issue 1 — Service exits failed and never comes back
Symptoms: systemctl status shows Active: failed; site or API is down until manual start; journal shows a crash or non-zero exit and no subsequent “Starting” line.
Issue 2 — Restart storm then permanent stop (StartLimit)
Symptoms: Rapid start/stop in the journal; finally start-limit-hit or Failed with result 'start-limit-hit'; further systemctl start is refused until reset.
Issue 3 — Override seems ignored; policy still Restart=no
Symptoms: You edited something, but systemctl show -p Restart still prints the old value; crash test does not auto-recover; confusion between user units and system units.
Issue 4 — Oneshot or forking Type= misconfiguration
Symptoms: Unit reports success immediately while the real daemon dies; or systemd tracks the wrong PID so restarts never fire when workers crash.
How to fix each issue
Fix issue 1 — Enable a real restart policy
Root cause is almost always missing or too-narrow Restart=.
- Confirm failure class in the journal:
journalctl -u your.service -b --no-pager | tail -n 50 - Create a drop-in with
sudo systemctl edit your.serviceand setRestart=on-failureplusRestartSec=3s(or 5s). - Reload and restart:
sudo systemctl daemon-reload sudo systemctl reset-failed your.service sudo systemctl restart your.service - Verify policy and state:
systemctl show your.service -p Restart -p NRestarts -p ActiveState - Repeat the SIGKILL test only on non-production first if you can; on production, schedule a short window.
If the process dies because of a bad config or missing socket, automatic restart only masks the outage for a few seconds—still fix the underlying error from the journal.
Fix issue 2 — Break restart loops and clear start limits
Root cause: the app crashes on boot (bad env, full disk, port in use, OOM), so systemd hits StartLimitBurst and gives up.
- Read why it crashes:
journalctl -u your.service -n 100 --no-pager dmesg | tail -n 40 - Check disk and memory pressure:
df -h free -m systemctl status your.service - Reset the counter after fixing the cause:
sudo systemctl reset-failed your.service sudo systemctl start your.service - Widen limits only slightly while you remediate—do not remove them:
[Service] Restart=on-failure RestartSec=10s StartLimitIntervalSec=120s StartLimitBurst=3 - If OOM is involved, inspect:
Then reduce workers or add memory—not endless restarts.journalctl -k | grep -i 'out of memory\|killed process'
Fix issue 3 — Make the drop-in actually apply
- Always use
systemctl edit your.service(system instance) rather than hand-creating files with wrong names. - Confirm the fragment path:
You must see your drop-in listed undersystemctl cat your.service# /etc/systemd/system/your.service.d/override.conf. - If you use lingering user services, edit the user manager instead:
systemctl --user edit your.service systemctl --user daemon-reload - Ensure sections are correct: restart directives belong under
[Service], not[Unit]. - After reload, re-check:
systemctl show your.service -p FragmentPath -p DropInPaths -p Restart
Fix issue 4 — Align Type=, PIDFile, and main process
- Inspect unit type:
systemctl show your.service -p Type -p PIDFile -p MainPID -p ExecStart - For classic forking daemons,
Type=forkingplus a validPIDFile=is required so systemd knows which PID to monitor. - Prefer
Type=notifyorsimple/execwhen you control the app—fewer PID races. - After corrections, daemon-reload, restart, and confirm MainPID matches the live process:
ps -fp $(systemctl show -p MainPID --value your.service)
When DIY is enough vs when to book Fixwebnode
DIY is enough when a single well-known unit crashes cleanly, the journal points to a clear config typo, and a drop-in with Restart=on-failure restores stability after one controlled test. Keep StartLimit in place so a bad deploy cannot hammer the CPU forever.
Book a specialist when multiple units depend on each other (nginx → php-fpm → redis → queue workers), when you see repeated OOM or core dumps, when overrides are ignored under orchestration (containers, custom prefixes), or when start-limit hits return after every deploy. Fixwebnode works as a direct remote provider for individuals, sole traders, and local operators in Australia—we diagnose the crash root cause, implement durable systemd policy, and verify recovery paths with you on the call. See coverage via Fixwebnode service areas, then continue on the repair landing page when you are ready to talk through the unit files.
Practical verification checklist
- Policy visible:
systemctl show … -p Restart - Drop-in on disk under
/etc/systemd/system/…d/ - Journal shows automatic “Scheduled restart” / new “Starting” after a kill test
NRestartsincrements but StartLimit is not exhausted in normal traffic- Application health check (curl localhost, or your reverse-proxy URL) succeeds after recovery
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1/
systemctl is-active nginx.service php8.3-fpm.service
Talk to Fixwebnode about systemd recovery
Automatic restarts are the safety net; root-cause fixes are the real cure. If you want a remote specialist to review unit overrides, journals, and interdependent services without marketplace bidding, open a conversation through https://fixwebnode.com.au/website-repair-australia. Bring the output of systemctl cat and a short journal slice—we will tell you whether a drop-in is enough or whether the service architecture needs a deeper pass.
Stable Linux services are achievable with systemd’s native monitoring when policy, limits, and process type agree. Use the steps above first; book Fixwebnode when the failure mode outgrows a single override.