When systemd Unit Files Don’t Pick Up Changes: Using systemctl daemon-reload and reload-or-restart Wisely

When systemd Unit Files Don’t Pick Up Changes

You tweak a unit file, hit systemctl, and nothing happens.
That’s the classic “I changed the file, but systemd still runs the old version” problem.
The daemon is still holding the old config in memory. systemd keeps a cache of unit files; it only rereads them after a daemon‑reload. If you skip that step, the changes stay invisible until you reboot or reload manually.


Why the Cache Exists

At boot, systemd parses every unit file once and keeps the data in RAM.
Re‑parsing on every request would be slow and could introduce race conditions.
The cache also acts as a security boundary: a compromised unit file can’t silently alter its own behavior without an explicit reload.


The Right Sequence

  1. Edit the unit file (or drop a drop‑in in /etc/systemd/system/.../override.conf).
  2. Validate the syntax – a stray typo can silently fail.
    systemd-analyze verify /etc/systemd/system/myapp.service
    
  3. Reload the daemon so systemd sees the new file.
    sudo systemctl daemon-reload
    
  4. Apply the change to the running service.
    • If the unit has a Reload= directive, use:
      sudo systemctl reload myapp.service
      
    • Otherwise or if you want a full restart, use:
      sudo systemctl restart myapp.service
      

reload-or-restart is handy when you’re not sure whether the unit supports reload.
It tries reload; if that fails, it falls back to restart.

sudo systemctl reload-or-restart myapp.service

Common Pitfalls

SymptomLikely CauseFix
Service still uses old configDaemon not reloadedsystemctl daemon-reload
systemctl reload fails with “Reload not supported”No Reload= lineAdd Reload=... or use restart
Unit file syntax errorMissed typosystemd-analyze verify
Service restarts on every reloadRestart=alwaysConsider Restart=on-failure or remove the directive

Security‑Friendly Practices

  • Least‑privilege for unit files – always set User= and Group= explicitly. A rogue reload that restarts a privileged service can be mitigated by running the unit as a non‑root user.
  • Audit unit changes – systemctl status --no-pager shows the active configuration. For critical services, keep a signed checksum of the unit file and verify it before reloading.
  • Avoid restart on production services unless necessary – a full restart can expose a window where the service is unavailable. Prefer reload when the application supports it.

Real‑World Example

I added an Environment= variable to nginx.service to enable a custom log format.

sudo tee /etc/systemd/system/nginx.service.d/env.conf <<EOF
[Service]
Environment="NGINX_LOG_FORMAT=combined"
EOF

Validate, reload, and restart:

sudo systemctl daemon-reload
sudo systemctl reload-or-restart nginx.service

Check the effective environment:

systemctl show nginx.service --property=Environment

You’ll see the new variable applied without a full reboot.


When to Skip daemon-reload

  • Transient units (created with systemctl start myapp@.service) – they’re parsed on each start.
  • Drop‑in files added to an already loaded unit – systemd re‑reads drop‑ins on the next start, but a daemon‑reload guarantees consistency.

Quick Reference

# Edit unit
sudo nano /etc/systemd/system/myapp.service

# Verify syntax
systemd-analyze verify /etc/systemd/system/myapp.service

# Reload daemon
sudo systemctl daemon-reload

# Apply change
sudo systemctl reload-or-restart myapp.service

Follow this pattern and you’ll avoid the “nothing changed” headache.
The extra reload step is a tiny cost for predictable, auditable service behavior.


See also