Hilton Chain <hako@ultrarare.space> writes:

> On Wed, 02 Apr 2025 23:46:51 +0800,
> Rutherther wrote:
>>
>>
>> Hello Hilton,
>>
>> Hilton Chain <hako@ultrarare.space> writes:
>>
>> >
>> > 2. Need of manually exposing interfaces.  e.g. those from shepherd-service.
>> >
>>
>> I feel like this has been a topic mentioned multiple times in the last
>> few weeks on this mailing list. Here I have e-mail from Carlo Zancanaro
>> in mind, "Configuring shepherd services belonging to system services" (I
>> don't know how to 'mention' e-mails in a good way, if you have tips,
>> please do share them),
>> where also this patch https://issues.guix.gnu.org/27155 has been
>> mentioned.
>>
>> I think it's a pity we don't have a generic solution merged yet,
>> especially given the patch that is 8 years old and Ludo mentions in it
>> "It was long overdue.", I agree.
>> The general finalizer approach would allow for exposing further
>> procedures that would alter the services after they are made, things
>> like this would become possible to do easily and we could build on it
>> further, functions like '(finalize-shepherd-service "service" (lambda
>> (config) (.. (inherit (config)))))' and more specific ones like
>> (shepherd-override-auto-start? #f)'.
>>
>> Regards,
>> Rutherther
>
> What I want is to have a consistent configuration interface, this is what
> currently in my mind, it's not conflict with the finalizer approach.  But I
> haven't got time to implemented it yet.
>
> --8<---------------cut here---------------start------------->8---
> (iwd-configuration
>  (alist-config
>   `(;; Interface for Guix services, shepherd, postgresql-role, user etc.
>     (shepherd
>      . ((iwd
>          . ((provision . (networking iwd))
>             (requirement . ())
>             (auto-start? . #f)))))
>     ;; For serializers.
>     (config
>      . ((iwd
>          . ((General
>              . ((EnableNetworkConfiguration . #t)
>                 (ControlPortOverNL80211 . #t)))
>             (Network
>              . ((EnableIPv6 . #t))))))))))
> --8<---------------cut here---------------end--------------->8---


Instead of alist, I tried to use the current configuration interface,
but with service extensions exposed.  I'll see how to add serializers in
later and experiment with more services.

Configuration interface:
--8<---------------cut here---------------start------------->8---
(service caddy-service-type
  (caddy-configuration
   (caddyfile (plain-file "test" "test"))))
--8<---------------cut here---------------end--------------->8---

--8<---------------cut here---------------start------------->8---
(service caddy-service-type
  (let ((base (caddy-configuration (caddyfile (plain-file "test" "test")))))
    (caddy-configuration
     (inherit base)
     (shepherd
      (map (lambda (s)
             (if (member 'caddy (shepherd-service-provision s))
                 (shepherd-service
                   (inherit s)
                   (documentation "test test"))
                 s))
           (caddy-configuration-shepherd base))))))
--8<---------------cut here---------------end--------------->8---

Service definicion:
--8<---------------cut here---------------start------------->8---
(define-record-type* <caddy-configuration>
  caddy-configuration make-caddy-configuration
  caddy-configuration?
  this-caddy-configuration
  (caddy              caddy-configuration-caddy
                      (default caddy))
  (caddyfile          caddy-configuration-caddyfile)
  ;; Extensions
  (accounts           caddy-configuration-accounts
                      (default (%caddy-accounts
                                this-caddy-configuration))
                      (thunked))
  (privileged-program caddy-configuration-privileged-program
                      (default (%caddy-privileged-program
                                this-caddy-configuration))
                      (thunked))
  (activation         caddy-configuration-activation
                      (default (%caddy-activation
                                this-caddy-configuration))
                      (thunked))
  (shepherd           caddy-configuration-shepherd
                      (default (%caddy-shepherd
                                this-caddy-configuration))
                      (thunked)))

(define (%caddy-accounts config)
  (list (user-group (name "caddy") (system? #t))
        (user-account
          (name "caddy")
          (group "caddy")
          (system? #t)
          (comment "Caddy user")
          (home-directory "/var/lib/caddy"))))

(define %caddy-privileged-program
  (match-record-lambda <caddy-configuration>
      (caddy)
    (list (privileged-program
           (program (file-append caddy "/bin/caddy"))
           (capabilities "cap_net_bind_service=+ep")))))

(define %caddy-activation
  (match-record-lambda <caddy-configuration>
      (caddyfile)
    (with-imported-modules
        (source-module-closure '((guix build utils)
                                 (gnu build activation)))
      #~(begin
          (use-modules (srfi srfi-26)
                       (guix build utils)
                       (gnu build activation))
          (let* ((config-dir "/etc/caddy")
                 (data-dir "/var/lib/caddy")
                 (config-file (in-vicinity config-dir "Caddyfile"))
                 (user (getpwnam "caddy")))
            (for-each (cut mkdir-p/perms <> user #o750)
                      (list config-dir data-dir))
            (copy-file #$caddyfile config-file)
            (for-each
             (lambda (file)
               (chown file (passwd:uid user) (passwd:gid user)))
             (find-files data-dir #:directories? #t)))))))

(define (%caddy-shepherd config)
  (list (shepherd-service
          (provision '(caddy))
          (requirement '(user-processes loopback))
          (start
           #~(make-forkexec-constructor
              (list "/run/privileged/bin/caddy" "run"
                    "--environ" "--config" "/etc/caddy/Caddyfile")
              #:user "caddy"
              #:group "caddy"
              #:directory "/var/lib/caddy"
              #:log-file "/var/log/caddy.log"
              #:resource-limits '((nofile 1048576 1048576))
              #:environment-variables '("HOME=/var/lib/caddy")))
          (stop
           #~(make-kill-destructor)))))

(define caddy-service-type
  (service-type
   (name 'caddy)
   (extensions
    (list (service-extension account-service-type
                             caddy-configuration-accounts)
          (service-extension privileged-program-service-type
                             caddy-configuration-privileged-program)
          (service-extension activation-service-type
                             caddy-configuration-activation)
          (service-extension shepherd-root-service-type
                             caddy-configuration-shepherd)))
   (default-value #f)
   (description "")))
--8<---------------cut here---------------end--------------->8---

Reply via email to