When running Nginx on CentOS 7 with systemd, you might encounter this error during boot:
2014/08/04 17:27:34 [emerg] 790#0: bind() to a.b.c.d:443 failed (99: Cannot assign requested address)
This typically occurs when Nginx attempts to bind to a specific IP address before the network interface is fully initialized. The service starts too early in the boot sequence.
In systemd, service dependencies are managed through unit file directives. The key ones for this scenario are:
After=
- Specifies services that should be started before this oneRequires=
- Hard dependency (service won't start if dependency fails)Wants=
- Soft dependency (service will start even if dependency fails)
Modern systemd systems use target units rather than individual services for network readiness. The relevant targets are:
network-online.target - Waits for all network interfaces to be configured
network.target - Less strict, indicates networking is available but interfaces might still be coming up
Here's how to modify the Nginx service to wait for network availability:
# Create an override directory if it doesn't exist
sudo mkdir -p /etc/systemd/system/nginx.service.d
# Create an override file
sudo tee /etc/systemd/system/nginx.service.d/override.conf << 'EOF'
[Unit]
After=network-online.target
Wants=network-online.target
EOF
# Reload systemd configuration
sudo systemctl daemon-reload
For a more streamlined approach, you can use:
sudo systemctl edit nginx.service
Then add the same [Unit] section content as above. This automatically creates the proper directory structure.
After implementing the changes, verify the service dependencies:
systemctl show -p After -p Wants nginx.service
You should see network-online.target
in both the After and Wants lists.
For more complex scenarios, you might need to:
- Create custom systemd services for specific network interfaces
- Use
ExecStartPre=
with a script to verify IP availability - Adjust Nginx's own configuration to retry binding
Here's an example of a more robust solution with a pre-check script:
[Unit]
After=network-online.target
Wants=network-online.target
[Service]
ExecStartPre=/usr/bin/sleep 5
ExecStartPre=/usr/bin/bash -c 'until ping -c1 google.com; do sleep 1; done'
The error message you're seeing typically occurs when Nginx attempts to bind to a specific IP address before that network interface is actually available. In systemd-based systems like CentOS 7, service startup order is crucial for services that depend on network availability.
Modern systemd systems don't use the traditional "network.service" you might expect. Instead, they use:
systemctl list-unit-files | grep -i network
You'll likely find "network.target" or "network-online.target" which represent different network readiness states.
Edit your nginx.service unit file (usually located at /usr/lib/systemd/system/nginx.service):
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
For more complex scenarios, you might want to delay Nginx startup until the network is truly ready:
[Service]
ExecStartPre=/bin/sleep 5
This adds a 5-second delay before Nginx starts.
After making changes:
systemctl daemon-reload
systemctl restart nginx
Check the dependencies with:
systemctl list-dependencies nginx.service
To verify network target states:
systemctl show -p SubState network.target
systemctl show -p SubState network-online.target
This helps identify if the network is actually ready when Nginx starts.
For more precise control when binding to specific IPs:
[Unit]
After=network-online.target
Requires=network-online.target
ConditionPathExists=/sys/class/net/eth0
This ensures the eth0 interface exists before starting.