Nginx Forking Service Unit

Create a systemd unit file for Nginx as a forking daemon. Covers configuration testing with ExecStartPre, PIDFile tracking, graceful reload, and signal-based lifecycle management.

Infrastructure Services

Detailed Explanation

Running Nginx with systemd

Nginx traditionally runs as a forking daemon: the master process forks worker processes and the master writes its PID to a file. This is a classic Type=forking use case.

[Unit]
Description=Nginx HTTP Server
After=network.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target

Configuration Validation

ExecStartPre=/usr/sbin/nginx -t -q runs nginx -t (test configuration) before starting. The -q flag suppresses output unless there's an error. If the configuration is invalid, the service fails to start with a clear error instead of starting with a broken config.

Nginx Signal Handling

Nginx uses Unix signals for lifecycle management:

Signal Nginx Action systemd Directive
HUP Reload configuration ExecReload
QUIT Graceful shutdown ExecStop
TERM Fast shutdown (systemd default)
USR1 Reopen log files Custom
USR2 Binary upgrade Custom

Graceful Reload

systemctl reload nginx

This sends SIGHUP to the master process. Nginx:

  1. Tests the new configuration
  2. Starts new worker processes with the new config
  3. Gracefully shuts down old workers (finish current connections)
  4. No downtime — no connections dropped

File Descriptor Limits

Nginx worker processes need one file descriptor per connection, plus descriptors for log files and upstream connections. For a server handling 10,000 concurrent connections:

LimitNOFILE=65535

Also configure worker_rlimit_nofile in nginx.conf to match.

Graceful Stop with Timeout

ExecStop=/bin/kill -s QUIT $MAINPID sends SIGQUIT for graceful shutdown:

  • Workers finish processing current requests
  • No new connections accepted
  • TimeoutStopSec=30 gives 30 seconds for requests to complete
  • After timeout, systemd sends SIGKILL

Binary Upgrade (Zero-Downtime)

For upgrading the Nginx binary without downtime, use the USR2 signal:

kill -USR2 $(cat /run/nginx.pid)
# New master starts → old workers finish → kill old master
kill -QUIT $(cat /run/nginx.pid.oldbin)

This is typically scripted rather than managed through systemd directives.

Use Case

Deploying Nginx as a production web server or reverse proxy with configuration validation, graceful reloads for zero-downtime config changes, and proper signal-based lifecycle management.

Try It — Systemd Unit File Generator

Open full tool