It is not that simplistic like you make it out to be either. I am making a new guide on how to set up Lokinet on Qubes right now and I just ran into a perfect example of why using the /rw/config/rc.local
file is not proper.
For context:
- Lokinet wants DNS to be managed by
resolvconf.
resolvconf
works by symlinking/run/resolvconf/resolv.conf
/etc/resolv.conf
qubes-network-uplink
overrides this by adding its own/etc/resolv.conf
.
So what is the solution to this? We need to run the following after qubes-network-uplink.service
finishes starting up:
rm -rf /etc/resolv.conf
ln -s /run/resolvconf/resolv.conf /etc/resolv.conf
With a systemd service, this is very simple to do: Just use After=qubes-network-uplink.service
as a start condition for the service that will run those commands. Nice, simple, easy and with guarantees that it will only be started AFTER qubes-network-uplink.service
has started successfully.
What about the rc.local file?
It is started by qubes-post-misc.service
, which has the following conditions:
After=network-pre.target
After=qubes-mount-dirs.service
After=qubes-network.service
After=qubes-firewall.service
These start conditions do not guarantee that the commands will be executed qubes-network-uplink.service
has started. In fact, if you were to make a systemd service with these conditions, it will run before qubes-network-uplink.service
, and have its resolv.conf
overwritten by qubes-network-uplink.service
.
The only reason this suggestion with rc.local
even works is that qubes-post-misc.service
also invokes:
. /usr/lib/qubes/functions
/usr/lib/qubes/update-proxy-configs
These happen to take long enough to run that the commands in rc.local
get executed after qubes-network-uplink.service
. It’s just pure luck.
This is not how proper dependency resolution works on any system that’s supposed to be reliable. You should not be engineering something that relies on luck like this to run. Stuff like this are why rc.local
is deprecated almost everywhere.