Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Start/stop OpenRC services based on Internet availability?
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Networking & Security
View previous topic :: View next topic  
Author Message
ChadJoan
n00b
n00b


Joined: 17 Oct 2010
Posts: 38

PostPosted: Thu Mar 07, 2024 9:35 pm    Post subject: Start/stop OpenRC services based on Internet availability? Reply with quote

On a system using OpenRC (not systemd) and NetworkManager (not dhcpcd, dhclient, netifrc, or others), how do I get services (e.g. /etc/init.d) to start and stop whenever networking+DNS+internet is available on any networking interface?

I ran into this problem because my /etc/init.d/ntp-client service is trying to start too early at boot and creating the following error in /var/log/rc.log:
Code:

 * Setting clock via the NTP client 'ntpdate' ...
Exiting, name server cannot be used: Temporary failure in name resolution (-3) * Failed to set clock
 [ !! ]
 * ERROR: ntp-client failed to start


Following that, I experience various kinds of mischief whenever the system ends up with the wrong time set on its clock (ex: browser can't visit websites because SSL/TLS won't work without correctly synchronized clock). As a workaround, I run /etc/init.d/ntp-client start by hand everytime I boot the system. But oof, there must be a better way!

I already tried the net-misc/chrony package mentioned in this thread.

It did not work. (And I'm not sure why it would? It didn't have any logic, that I could see, for delaying ntp-client until network+DNS is available.)

My /etc/conf.d/ntp-client file has rc_use="dns" set in it. But this does not help.

Now I want to point out that this is not just an ntp-client problem.

I have experienced a generalization of this problem when trying to make my system automatically make an SSH connection to another machine. That was intended to open a reverse-tunnel that I can use to access my laptop-or-whatever from any network that doesn't block outbound SSH connections. (I used custom /etc/init.d script to do this, but it never worked right, because...)

That endeavor met the Same Problem: I had no way to start the service once networking became available (DNS or not), or stop it gracefully when network access disappears.

And beyond NTP and SSH tunnels, I can imagine how this might cause problems for other services I might want to run. I start to wonder how many things on my system only work because they just "happened to" come up late enough, or maybe aren't working at all because they failed the same way but were silent about their failure (and thus lead to diffuse, hard-to-troubleshoot, problems/symptoms in other programs/apps/etc).

I tried looking for ways to introduce networking as a dependency in initscripts.

This Flameeyes' blog post from 2012 suggested that this was still an Open Problem at that time.

rc_hotplug in /etc/rc.conf looks promising, but nothing I've read explains what it really does: Will services dependent on the named service be started/restarted, or just the service itself? How does it know when some hardware has been plugged/unplugged? Is it just looking at the existence of device nodes? If so, how do I specify which ones? And even if so, maybe this still isn't the right way to do this thing, because it doesn't work with any software that checks for internet connectivity based on successful pings/requests/etc? Or does it actually do deep connectivity checks for network connections, and if so, how does it distinguish that case from other, non-networking, hardware-availability issues? (If rc_hotplug isn't the answer, then I don't really expect all those questions answered. These are all rhetorical: I just can't find such information anywhere. And it doesn't seem worth it to run experiments, because I doubt it's actually checking for internet connectivity.)

I noticed the /etc/init.d/net-online service. That looks potentially helpful. But I'm not sure how to make other services depend on it (edit "rc_" values in rc.conf? edit depend() in /etc/init.d/<scriptname>?), or ensure that it starts+stops services outside of runlevel execution (or maybe I misunderstand how initscripts are processed, and it's more dynamic than I expect). I still don't understand what rc_need, rc_use, rc_after, rc_before, rc_depend_strict, or any others do, or why I'd want to use one over the other. (And does the existence of rc_depend_strict imply the existence of rc_depend?) I can find documents that mention these things (example), but I can't find a list of definitions for them.

So now I really want to know: what is the proper mechanism is for solving the start-and-stop-services-based-on-internet-availability problem?

My internet searches are coming up empty-handed. :(
Back to top
View user's profile Send private message
alamahant
Advocate
Advocate


Joined: 23 Mar 2019
Posts: 3879

PostPosted: Fri Mar 08, 2024 11:10 am    Post subject: Reply with quote

Quote:

I ran into this problem because my /etc/init.d/ntp-client service is trying to start too early at boot and creating the following error in /var/log/rc.log:

Plz enable it @default NOT @boot runlevel.
You may add rc hooks like
Code:

# You can also enable the above commands here for each service. Below is an
# example for service foo.
#rc_foo_config="/etc/foo"
#rc_foo_need="openvpn"
#rc_foo_after="clock"


in /etc/rc.conf
or in
/etc/conf.d/<service>
_________________
:)
Back to top
View user's profile Send private message
ChadJoan
n00b
n00b


Joined: 17 Oct 2010
Posts: 38

PostPosted: Fri Mar 08, 2024 4:39 pm    Post subject: Reply with quote

Quote:
Plz enable it @default NOT @boot runlevel.


I'm afraid it won't be that easy. It's already in @default:

Code:

cdj-desktop /etc # rc-status
Runlevel: default
 syslog-ng                       [  started  ]
 iwd                             [  started  ]
 NetworkManager                  [  started  ]
 ntp-client   .................  [  started  ]  <----
 cronie                          [  started  ]
 sshd                            [  started  ]
 netmount                        [  started  ]
 cupsd                           [  started  ]
 firewalld                       [  started  ]
 sensord                         [  started  ]
 local                           [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed/wanted
 display-manager-setup           [  started  ]
 dbus                            [  started  ]
 avahi-daemon                    [  started  ]
 display-manager                 [  started  ]
Dynamic Runlevel: manual
cdj-desktop /etc # rc-update show
       NetworkManager |      default                           
               binfmt | boot                                   
             bootmisc | boot                                   
              cgroups |                                 sysinit
               cronie |      default                           
                cupsd |      default                           
                devfs |                                 sysinit
                dmesg |                                 sysinit
              elogind | boot                                   
            firewalld |      default                           
                 fsck | boot                                   
             hostname | boot                                   
              hwclock | boot                                   
                  iwd |      default                           
              keymaps | boot                                   
            killprocs |                        shutdown       
    kmod-static-nodes |                                 sysinit
                local |      default nonetwork                 
           localmount | boot                                   
             loopback | boot                                   
              modules | boot                                   
             mount-ro |                        shutdown       
                 mtab | boot                                   
             netmount |      default                           
           ntp-client |      default   <---------------
               procfs | boot                                   
                 root | boot                                   
         save-keymaps | boot                                   
    save-termencoding | boot                                   
            savecache |                        shutdown       
              seedrng | boot                                   
              sensord |      default                           
                 sshd |      default                           
                 swap | boot                                   
               sysctl | boot                                   
                sysfs |                                 sysinit
            syslog-ng |      default                           
 systemd-tmpfiles-setup | boot                                   
 systemd-tmpfiles-setup-dev |                                 sysinit
         termencoding | boot                                   
                 udev |                                 sysinit
         udev-trigger |                                 sysinit
cdj-desktop /etc #


No runlevel is good enough (including @default) because none of them guarantee internet availability, or even correlate with network status (e.g. the default runlevel doesn't stop() when network interfaces become unavailable, nevermind internet connectivity; and it shouldn't ;) ).

Quote:
You may add rc hooks like ...


That does look promising, but I'm still stuck because I can't find the right documentation for it:
What are all of the possible options, exhaustively? What do they do? Why would I use one over the other?

Then once I've figured out rc hooks, what service do I use as a dependency? net-online would be my first guess, but I'd like to know what the best option is, if anyone knows.

Then it's back to rc hook syntax: How do I name the service in the rc_something="<service>" line? Is it the name of the file in /etc/init.d? Or is it the string that shows up in the provide <name> line in the depend() block of the service's init.d file? Or something else?

Then the biggie: how do I know which services to add rc_hooks for? I just got blindsided and I'd like to root-cause this thing.

Thank you for the help!
Back to top
View user's profile Send private message
flexibeast
Guru
Guru


Joined: 04 Apr 2022
Posts: 324
Location: Naarm/Melbourne, Australia

PostPosted: Fri Mar 15, 2024 3:10 am    Post subject: Reply with quote

Does the openrc-run(8) man page, and in particular the DEPENDENCIES section, go some way to providing the sort of information you're after?
Back to top
View user's profile Send private message
ChadJoan
n00b
n00b


Joined: 17 Oct 2010
Posts: 38

PostPosted: Sat Mar 16, 2024 7:14 pm    Post subject: Reply with quote

Quote:

Does the openrc-run(8 ) man page, and in particular the DEPENDENCIES section, go some way to providing the sort of information you're after?


So far, that is quite helpful! I have made progress.

Thank you, flexibeast.

Unfortunately, after some experimentation, I get the feeling that there are still things about it that I do not understand :(

Right now, I have worked around the problem by adding this line to /etc/rc.conf:
Code:

# We need DNS+Internet for talking to the NTP server.
rc_ntp_client_need="NetworkManager"


That gets ntp-client to come up at the correct time.

I also added this (also in /etc/rc.conf) in an attempt to make ntp-client stop when the network goes down (or NetworkManager is stopped with rc-service NetworkManager stop), and have it start again (rc-service NetworkManager start) whenever the network comes back up:
Code:

rc_ntp_client_after="NetworkManager"


This approach also has the promise of delegating the "internet availability detection" responsibility to the NetworkManager service. NetworkManager seems to have reliable logic for this (notable reading), and its rc service will have an "inactive" status when there is no connectivity. By causality that still isn't clear to me, this also seems to include DNS functionality. Fun fact: /etc/NetworkManager/dispatcher.d/10-openrc-status has some special logic in it that helps the NetworkManager service reflect network availability.

However, it doesn't work.

Right now, stopping NetworkManager will also stop the ntp-client service, but starting NetworkManager will not bring ntp-client back up. ntp-client's behavior is mirrored by the netmount service.

I am also very confused by the dns service. Numerous services seem to depend on it, but none seem to provide it:
Code:

cdj-desktop /etc # grep -RPin "\bdns\b" /etc/init.d
/etc/init.d/wg-quick:10:        use dns
/etc/init.d/bacula-fd:12:       use dns
/etc/init.d/openvpn:16: use dns
/etc/init.d/openvpn:78: # which configures our DNS if any and marks us as up.
/etc/init.d/openvpn:96:         # Warn about the inability to change ip/route/dns information when
/etc/init.d/openvpn:101:                        ewarn "or DNS configuration."
/etc/init.d/mdadm:6:    use logger dns net
/etc/init.d/apache2:36: use dns entropy logger mysql netmount postgresql
/etc/init.d/bacula-dir:15:      use dns bacula-fd bacula-sd
/etc/init.d/sshd:27:    use logger dns entropy
/etc/init.d/ntpd:13:    use net dns logger
/etc/init.d/netmount:27:        use dns
/etc/init.d/apcupsd:19: use dns
/etc/init.d/rdate:8:    use dns
/etc/init.d/nfs:28:     use ypbind net dns rpc.rquotad rpc.idmapd rpc.svcgssd
/etc/init.d/nfsclient:18:       use ypbind dns
/etc/init.d/sntp:10:    use dns logger
/etc/init.d/iwd:12:     before dns dhcpcd net
/etc/init.d/ntp-client:8:       use dns logger
/etc/init.d/dhcpd:14:   use logger dns
/etc/init.d/ddclient:15:        use dns logger
/etc/init.d/glusterfsd:25:      use dns
/etc/init.d/bacula-sd:12:       use dns


At an earlier point in my investigation, my workaround involved creating the dns service in a file /etc/init.d/dns with these contents:
Code:

name="dns"
description="Stub for dependency management of DNS on NetworkManager system."

depend() {
   need NetworkManager
   after NetworkManager
}

start() {
   return 0
}

stop() {
   return 0
}


... and then having ntp-client "need" the dns service via rc_ntp_client_need in /etc/rc.conf. (Oddly enough, the "use dns ..." in /etc/init.d/ntp-client is not sufficient, even with the above dns added to the default runlevel, and adding "after dns" isn't sufficient either, so it has to be "needed" specifically!) But I don't necessarily recommend doing this, because I have no idea how the dns is actually supposed to be defined (maybe I am missing a package, or misconfigured something else, or I-don't-know-what).

My understanding of how openrc manages dependencies is definitely incomplete!

So I feel like we're getting closer (I have a workaround that accomplishes SOME of the desired outcome), but not quite to SOLVED yet, because I can't make things come up/down in sync with the network.
Back to top
View user's profile Send private message
grknight
Retired Dev
Retired Dev


Joined: 20 Feb 2015
Posts: 1662

PostPosted: Sat Mar 16, 2024 8:45 pm    Post subject: Reply with quote

ChadJoan wrote:
I am also very confused by the dns service. Numerous services seem to depend on it, but none seem to provide it:
Code:

cdj-desktop /etc # grep -RPin "\bdns\b" /etc/init.d
/etc/init.d/wg-quick:10:        use dns
/etc/init.d/bacula-fd:12:       use dns
/etc/init.d/openvpn:16: use dns
/etc/init.d/openvpn:78: # which configures our DNS if any and marks us as up.
/etc/init.d/openvpn:96:         # Warn about the inability to change ip/route/dns information when
/etc/init.d/openvpn:101:                        ewarn "or DNS configuration."
/etc/init.d/mdadm:6:    use logger dns net
/etc/init.d/apache2:36: use dns entropy logger mysql netmount postgresql
/etc/init.d/bacula-dir:15:      use dns bacula-fd bacula-sd
/etc/init.d/sshd:27:    use logger dns entropy
/etc/init.d/ntpd:13:    use net dns logger
/etc/init.d/netmount:27:        use dns
/etc/init.d/apcupsd:19: use dns
/etc/init.d/rdate:8:    use dns
/etc/init.d/nfs:28:     use ypbind net dns rpc.rquotad rpc.idmapd rpc.svcgssd
/etc/init.d/nfsclient:18:       use ypbind dns
/etc/init.d/sntp:10:    use dns logger
/etc/init.d/iwd:12:     before dns dhcpcd net
/etc/init.d/ntp-client:8:       use dns logger
/etc/init.d/dhcpd:14:   use logger dns
/etc/init.d/ddclient:15:        use dns logger
/etc/init.d/glusterfsd:25:      use dns
/etc/init.d/bacula-sd:12:       use dns

"use dns" means "If there is a service added in a runlevel that is either named dns or 'provide dns', start that first. If it doesn't exist or not added, don't consider it" Scripts like dnsmasq, named or unbound "provide dns"
Back to top
View user's profile Send private message
ChadJoan
n00b
n00b


Joined: 17 Oct 2010
Posts: 38

PostPosted: Mon Mar 18, 2024 5:55 am    Post subject: Reply with quote

Quote:

"use dns" means "If there is a service added in a runlevel that is either named dns or 'provide dns', start that first. If it doesn't exist or not added, don't consider it"

Great! This is what I expected, and I'm glad you clarified how the names work. Thanks!

Quote:

Scripts like dnsmasq, named or unbound "provide dns"

Cool; thanks for the examples!

...

I think the thing boggling me about it is that I'm on a system with perfectly working DNS, and no service that "provide(s) dns" or any named that (until I added a stub by hand).

Is there some way I'm supposed to get the NetworkManager package to provide the dns RC initscript? (And without installing+integrating dnsmasq, because I don't need it: my DNS already works fine.)

Though now I'm noticing that dnsmasq, named, and unbound are all DNS servers. So now I am wondering about this: could the dns service be intended to correlate with a DNS server instead of a DNS client? If it's for a server, then I am possibly worrying about nothing, as I don't need a server. I just want to make sure other services know that DNS lookup functionality is available.

Strongly related question: is the net service supposed to include DNS functionality? (I could see this easily being the case if the dns service is about DNS servers, rather than clients. Or it could be redundant.)

I had expected that the net service just guarantees that there is a network interface UP, but not that there is any DNS availability or actual connectivity (ex: eth0 might be UP, but it's plugged into a connectionless router). That would be in line with my earlier-in-life experiences with Netifrc, where I would ln -s /etc/init.d/net.lo /etc/init.d/net.<interface_name> (as described in the wiki). But now I am questioning that assumption/expectation, and maybe I don't really understand just what the net service is supposed to be (or do).
Back to top
View user's profile Send private message
grknight
Retired Dev
Retired Dev


Joined: 20 Feb 2015
Posts: 1662

PostPosted: Mon Mar 18, 2024 12:34 pm    Post subject: Reply with quote

Yes, "use dns" is to ensure any DNS server, often used for local caching, starts before other services that may utilize it.

If you want to guarantee network availability before a service starts, then look into the net-online service (after configuring it in conf.d) and have services depend on that (using "need" or "want" statements, see man openrc-run for the difference) in either rc.conf or their respective conf.d files.

Note that OpenRC is not continuously aware of network status on its own. Only when invoked can it check state of any service, otherwise it is stateless.
Back to top
View user's profile Send private message
pa4wdh
l33t
l33t


Joined: 16 Dec 2005
Posts: 812

PostPosted: Mon Mar 18, 2024 6:34 pm    Post subject: Reply with quote

ChadJoan wrote:

So now I really want to know: what is the proper mechanism is for solving the start-and-stop-services-based-on-internet-availability problem?

I don't think there is a ready made solution.

One thing that comes to mind is this:
Use the default runlevel to only start items that don't need network/internet connectivity. Create a new runlevel (named "online" for example) and place all services that require internet connectivity there.
Now, create a script that checks network/internet connectivity that simply changes runlevel based on the result of this check. This also allows you to define what "internet available" means to you. Is it good enough to be able to ping something? Do you want to check if DNS resolution works? Anything else?

An other option:
I know you mentioned you use network manager and not one of the dhcp daemons. Be aware that at least dhcpcd can run hooks(scripts) on different events dhcp related events which might help with your use case.
_________________
The gentoo way of bringing peace to the world:
USE="-war" emerge --newuse @world

My shared code repository: https://code.pa4wdh.nl.eu.org
Music, Free as in Freedom: https://www.jamendo.com
Back to top
View user's profile Send private message
szatox
Advocate
Advocate


Joined: 27 Aug 2013
Posts: 3139

PostPosted: Mon Mar 18, 2024 7:36 pm    Post subject: Reply with quote

Quote:
[..]I noticed the /etc/init.d/net-online service. That looks potentially helpful. But I'm not sure how to make other services depend on it (edit "rc_" values in rc.conf? edit depend() in /etc/init.d/<scriptname>?), or ensure that it starts+stops services outside of runlevel execution (or maybe I misunderstand how initscripts are processed, and it's more dynamic than I expect). I still don't understand what rc_need, rc_use, rc_after, rc_before, rc_depend_strict[...]


If you put this in /etc/conf.d/<service>
Code:

depend () {
need net-online
# or maybe should it be called for a specific interface instead:
need net-online.eth0
}

it should result in your service waiting for net-online to come up, and also your service should be stopped when you take net down.
"use net-online" should result in your service waiting for net-online but not stopping when net goes down.
Now, i haven't checked what exactly does net-online do, but it belongs to openrc and _not_ netifrc, so there is a chance it will work with other tools too.


Finally, one last tip from me, if you run any network servers on your machine, it's a good idea to create a virtual interface with an IP address instead of assigning that IP to a physical interface. I've been using a bridge I'd enslave NIC with, but it could also be a dummy - possibly behind DNAT.
The point is to disconnect service's IP address from the physical link, which allows you to reconfigure network without restarting your servers. This enables your server to start as soon as that virtual interface is up and has an IP address assigned, even before the whole machine comes online. Of course the service still won't be not be accessible until network gets ready, but at least it won't corrupt server's state (like sockets not binding on startup).
_________________
Make Computing Fun Again
Back to top
View user's profile Send private message
grknight
Retired Dev
Retired Dev


Joined: 20 Feb 2015
Posts: 1662

PostPosted: Mon Mar 18, 2024 7:39 pm    Post subject: Reply with quote

szatox wrote:
If you put this in /etc/conf.d/<service>
Code:

depend () {
need net-online
# or maybe should it be called for a specific interface instead:
need net-online.eth0
}
This is better expressed as rc_need="net-online" (or similar) in a conf.d file.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Networking & Security All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum