A couple of days ago I submitted a small patch for Wireguard, to define
a Wireguard service without automatically starting it:
https://issues.guix.gnu.org/76637

Thinking about this some more, I wonder if there's a better way to do
this than hard-coding this specific option. This seems like a more
general issue, where someone wants to modify a "hidden" shepherd service
in some way that's specific to their system.

I can think of three more general ways that we could encode something
like this. The first two are patterns that individual services would
have to implement, so I'll mention them specifically relating to the
problem that my patch is attempting to solve.

1. Add a `shepherd-service-template` field, which the Wireguard service
then inherits from. This lets me change the "default" value for each
field, but if the service provides an explicit value then it will be used.

2. Add a `shepherd-service-constructor` field, which contains a function
that the Wireguard service uses to create its shepherd service. This is
kind of the inverse of the first option. It lets the service specify the
default value, and allows me to change it if I want.

3. Add a new concept of "finalizers" to root-shepherd-service-type to
allow my configuration to arbitrarily modify shepherd-services. This is
a generalisation of (2) which would let me write something vaguely like
this to stop the service from auto starting:

--8<---------------cut here---------------start------------->8---
(simple-service 'dont-auto-start-wireguard shepherd-root-service-type
                (list (shepherd-finalizer
                       (matcher (lambda (x) (eq? 
(shepherd-service-canonical-name x) 'wireguard-wg0)))
                       (action (lambda (service)
                                 (shepherd-service
                                  (inherit service)
                                  (auto-start? #f)))))))
--8<---------------cut here---------------end--------------->8---

The patch that I've submitted is much simpler than these ideas, and it
solves an immediate problem that I have, so it could still be worth
merging as-is. I just figured it could be worth raising as a more
general problem as well.

As fuel for thought, we have https://issues.guix.gnu.org/27155 from 2017
which creates a finalization mechanism for any service type, but it
built on the idea of explicit extension points which would limit what a
finalizer can do to whatever a service writer has made available.

As a potentially-useful extra piece of information, NixOS makes this
pretty easy with their "big ball of attributes" model of configuration.
I can modify a systemd service by just setting attributes under
systemd.services.<service-name>.wantedBy. For a Wireguard network that
might look like this:

--8<---------------cut here---------------start------------->8---
{
  networking.wg-quick.interfaces.wg0 = { ... };
  systemd.services.wg-quick-wg0.wantedBy = lib.mkForce [ ];
}
--8<---------------cut here---------------end--------------->8---

I feel like this is somewhere where Guix's more structured approach to
service definition makes things harder. It would be nice to make this
easier without having to add a bunch of configuration options to
anything that extends shepherd-root-service-type.

Carlo

Reply via email to