Hi Lorenzo,

On Wed, Oct 15, 2025 at 03:36:22PM +0200, Lorenzo wrote:
> Control: tags -1 +patch
> 
> initial version of the service is here

Thanks for adding this support to unblock my service directory
contributions!

I don't see a problem in principle with using a new service directory as
a dependency for services that require networking, but I think there's a
better way to the extent that I think we should not do a service
directory.

Let's remember that there is nothing philosophical or practical about
runit that means a service directory's dependency needs to be another
service, rather than another type of check that can be performed.

A lot of initscripts and systemd units historically claim dependence on
'networking' which are not strictly necessary, probably added as a form
of 'cargo culting' and, as the systemd documentation correctly points
out [1], there is no single right answer as to what counts as the
network being ready.

In my contributed service definitions I have entirely omitted network
checks that are not needed at all, even if $network was present in the
initscript. Instead, I have found out what the real underlying
requirement is and implemented that as minimally as possible.

If we take the examples of my two pending runit-services merge requests:

1. gerbera - requires global unicast IPv4 address.

In this case (quite wrongly in my opinion, via libupnp) the server will
not start properly without a global unicast IPv4 address. Neither a
global unicast IPv6 address nor a link-local unicast IPv4 address would
be sufficient, even though they should be. But actual conectivity is not
important.

So we can test for this with one line which checks specifically for
global unicast IPv4 addresses.

  [ -n "$(ip -f inet addr show scope global)" ] || exit 1

I don't think a runsv supervisor is necessary or beneficial for this. If
it actually caused the network to be configured when it wasn't, like
'default-syslog' does for logging, maybe it would have some merit.

2. xl2tpd - requires a non-loopback address to bind to.

We can test for this by looking for any address with wider scope than
loopback. If we do this numerically, we can catch scopes from unexpected
types of addressing family (in principle), so with (decreasing) scopes
going up numerically to 255 and loopback being 254:

  ip -oneline -Numeric addr show | grep -Evq ' scope 25[45]' || exit 1

So how can we do this generally?

First it is important not to look for things which could give us false
information, hence porcelain views of output data (like -oneline and
-Numeric help to give us) and certainly not checking interface type
names or especially not actual interface names.

We can't have one size fits all or we end up limiting services
unnecessarily. What if we needed xl2tpd to provide a tunneling service
so that gerbera could start (OK, not that exact situation because
gerbera needs IPv4, but you get the idea!)? So if you need multiple
checks you might end up with multiple fake services like network-is-up,
each with their own runsv. It doesn't really scale.

There may be other services with more stringent requirements.

I think the answer is to have a library of shell functions we can call
to check things. You could put this in invoke-run but I wonder if that
is getting a bit full. So maybe another file, either sourced from
invoke-run or directly from the run script.

Something like:

#...

. /lib/runit/network-checks

have_network_address scope=global family=inet || exit 1

#...

The implementation of have_network_address() could map scope=X onto a
scope number first, if specified, loop through supplied addresses and
discard any that are numerically higher than num(X). It can then discard
any that don't match the family=Y key if specified. Then return true if
there are any addresses left.

You could have an alternate implementation for Hurd. I wouldn't bother
with ifconfig on Linux - net-utils won't be present if iptroute2 is. On
Linux you could fall back to /proc/net/dev; I don't know if Hurd has
something equivalent.

>         for interf in $(ip addr | grep -Po '^\d+:\s+\K[^:]+') ; do

'ip -oneline' helps you do more robust parsing.

Andrew

[1] https://systemd.io/NETWORK_ONLINE/

Reply via email to