1

I have a 'dummy' network interface setup with systemd-networkd; by default the interface is left 'down'.

There is a service unit which runs an application that binds to the address on that interface (using a non-local-bind so that it can bind even when the interface is down). If, and only if, the service is operating, the network interface should be 'up'.

The result I'm hoping for is that if the service is restarted, or crashes and can't be brought back up, the interface will be left 'down', and the routing daemon on the machine (bird2 using OSPF) will stop broadcasting a route to that address, and thus requests for the service will be routed to other available instances.

I could use ExecStartPost and ExecStopPost to run 'ip link set up/down' or 'networkctl up/down' commands (and in fact that was my first attempt), but the unit file for this service runs it in a very tightly sandboxed environment as an unprivileged user, so those commands can't be executed because they will be run in an environment without CAP_NET_ADMIN. An example of the service unit file is here.

I've also tried creating a separate service to just run these commands, which will run normally as 'root' and not be restricted in this way. However, I haven't found a combination of dependency specs that will cause the second service to follow the state of the first service.

If I use After= and BindsTo= in service B, pointing to service A, then service B is properly started after service A during system startup. If service A is stopped, service B is stopped. If service A is restarted by systemd, then service B is also restarted.

However, if service A is stopped, and then started again, service B is not started.

The only other option I can think of is to make a new target which combines both services, and somehow restrict service A so that it cannot be manually started and in that way remind the admin that they need start the target and not the service. It's not clear to me how I could make this new target be automatically depended-on by multi-user.target though.

1

1 Answer 1

1

OK, using bits from the other answer, here's what I ended up with:

For systemd versions 248 and lower

anycast-dns.target:

[Unit]
Description=Manage anycast DNS resolver and its network link

[Install]
WantedBy=multi-user.target

dns-link-manager.service:

[Unit]
BindsTo=pdns-recursor.service
After=pdns-recursor.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/networkctl up dns
ExecStop=/usr/bin/networkctl down dns

[Install]
WantedBy=anycast-dns.target

pdns-recursor.service.d/anycast-dns.conf:

[Unit]
RefuseManualStart=yes

[Install]
WantedBy=
RequiredBy=anycast-dns.target

systemctl enable was run for each of them.

This has the desired result:

  • At startup, anycast-dns.target starts pdns-recursor.service; if that is successful then dns-link-manager.service brings up the network link.

  • If pdns-recursor.service is stopped (manually, or it crashes and can't be restarted), then dns-link-manager.service takes down the network link.

  • The admin can't manually start (or restart) pdns-recursor.service, they have to start anycast-dns.target as a proxy to ensure that the network link will also be brought up.

For systemd versions 249 and higher

dns-link-manager.service:

[Unit]
Requisite=pdns-recursor.service
After=pdns-recursor.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/networkctl up dns
ExecStop=/usr/bin/networkctl down dns

pdns-recursor.service.d/anycast-dns.conf:

[Unit]
Upholds=dns-link-manager.service
PropagatesStopTo=dns-link-manager.service

This has the desired result:

  • At startup, multi-user.target starts pdns-recursor.service; if that is successful then dns-link-manager.service brings up the network link (due to the Upholds dependency)

  • If pdns-recursor.service is stopped (manually, or it crashes and can't be restarted), then dns-link-manager.service takes down the network link (due to the PropagatesStopTo dependency).

  • The admin can't manually start dns-link-manager.service unless pdns-recursor.service is running (in which case dns-link-manager.service will already be running).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.