On a Ubuntu 20.04.2 TLS server, I have a need to start a service after another one has fully started up. Specifically, the openvpn-server service creates a tun0 interface with the IP address 10.87.0.1 to which the rinetd service then binds. So the rinetd service should only be started after the openvpn-server service has created that interface.
rinetd comes with a sysvinit service script /etc/init.d/rinetd saying:
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslogThis causes rinetd to be started during system startup before openvpn-server has created the interface. It then emits the log message:
rinetd[792]: couldn't bind to address 10.87.0.1 port 873 (Cannot assign requested address)and does not accept connections until I manually restart it with sudo systemctl restart rinetd, after which it then runs just fine.
According to sudo systemctl status the openvpn server process is run by a systemd service named .
Extending the Required-Start line in /etc/init.d/rinetd to say:
# Required-Start: $remote_fs $syslog openvpn-server@serveris duly translated by systemd-sysv-generator to an additional line
After=in /run/systemd/.
But systemd ignores that. rinetd still shows the same log message and malfunction, proving that it is still started before openvpn-server is up.
How can I get systemd to reliably start the rinetd service only after the openvpn-server service has done its part and created the interface?
2 Answers
If we first take systemd, I think it's better if you address the interface directly. Devices in the dev and sysfs tree are exposed to systemd and can be used to make dependencies to other units.
Start by masking the original startup script.
systemctl mask --now rinetd.serviceWith an instantiated .service, e.g., rinetd-daemon@.service, you can start one or several instances if needed, if we were, to have more than one device (provided rinetd can bind to several interfaces).
[Unit]
Description=Rinetd connection forwarding service (%I) After=sys-subsystem-net-devices-%i.device
BindsTo=sys-subsystem-net-devices-%i.device
[Service]
Type=forking
ExecStart=/usr/sbin/rinetd
PIDFile=/var/run/rinetd.pid
ExecReload=kill -HUP $MAINPID
[Install]
WantedBy=sys-subsystem-net-devices-%i.deviceYou can then instantiate the service together with a device name:
systemctl enable --now 2 The new .service file probably needs
[Unit]
After=
Requires=The options can be confusing, but there are a ton of other resources that cover similar ground.
2