How to set systemd service dependencies?

During CentOS 7 system boot nginx start fails with the following error:

2014/08/04 17:27:34 [emerg] 790#0: bind() to a.b.c.d:443 failed (99: Cannot assign requested address)

I suspect this is happening due to the network interfaces not being up yet before attempting to bind to that IP address for serving a vhost over SSL.

My guess is I need to specify the network.service as a requirement for the nginx.service, but I can't find the network service in /etc/systemd/ at all.

How can I configure the service order or dependencies in systemd?


Solution 1:

You need, at minimum, After=network.target in the [Unit] section of your unit file, to ensure that the network is up before starting nginx. I have no idea why your unit file doesn't have it.

Here is a complete example from my handy Fedora system, as shipped by Fedora:

[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Solution 2:

From the error log, it looks like your nginx config. file has a listen directive with an explicit ip address:

listen a.b.c.d:443

This means that nginx won't start unless your network interface is up and the IP a.b.c.d has been assigned to the interface.

You have two options:

  • change the listen directive to: listen 443; (bind to all ip addresses)
  • make nginx depend on network-online.target

As described in http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ the network.target only indicates that the network management stack is up [...] Whether any network interfaces are already configured when it is reached is undefined.

If you want to make sure that the IP address is already assigned and the interface is up, you need to add the network-online.target to your nginx's systemd unit file.

Your /etc/systemd/system/multi-user.target.wants/nginx.service file should have network-online.target in the After= and Requires= lines.

[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target network-online.target
Requires=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target