[bug#76963] home: Add home-snuik-service.

Message ID 7f43764f98a45b92cce1be2e7d352e3c791cebf8.1741729617.git.janneke@gnu.org
State New
Headers
Series [bug#76963] home: Add home-snuik-service. |

Commit Message

Janneke Nieuwenhuizen March 11, 2025, 9:54 p.m. UTC
  * gnu/home/services/messaging.scm (<home-snuik-configuration>): New type.
(home-snuik-services, home-snuik-service-type): New procedures.
* doc/guix.texi (Messaging Home Services): Document it.

Change-Id: I1e278e7d8ed04efcb1a2ce9e12e69cb6a31a9fa4
---
 doc/guix.texi                   | 58 ++++++++++++++++++++++++-
 gnu/home/services/messaging.scm | 77 ++++++++++++++++++++++++++++++++-
 2 files changed, 132 insertions(+), 3 deletions(-)


base-commit: d685a45edf0f89e5876ffc9d880068d8610e5f8a
  

Comments

Maxim Cournoyer March 12, 2025, 12:47 p.m. UTC | #1
Hi Janneke!

Janneke Nieuwenhuizen <janneke@gnu.org> writes:

> * gnu/home/services/messaging.scm (<home-snuik-configuration>): New type.
> (home-snuik-services, home-snuik-service-type): New procedures.
> * doc/guix.texi (Messaging Home Services): Document it.
>
> Change-Id: I1e278e7d8ed04efcb1a2ce9e12e69cb6a31a9fa4
> ---
>  doc/guix.texi                   | 58 ++++++++++++++++++++++++-
>  gnu/home/services/messaging.scm | 77 ++++++++++++++++++++++++++++++++-

Wouldn't such a service be a more natural match for a system service?
It seems like something I'd like running on a headless server.

>  2 files changed, 132 insertions(+), 3 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index d109877a32..f35e156376 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -36,7 +36,7 @@
>  Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Efraim Flashner@*
>  Copyright @copyright{} 2016 John Darrington@*
>  Copyright @copyright{} 2016, 2017 Nikita Gillmann@*
> -Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Janneke Nieuwenhuizen@*
> +Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Janneke Nieuwenhuizen@*

Maybe use 2016-2025 :-).

>  Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Julien Lepiller@*
>  Copyright @copyright{} 2016 Alex ter Weele@*
>  Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Christopher Baines@*
> @@ -49714,6 +49714,62 @@ Messaging Home Services
>  @end table
>  @end deftp
>  
> +@cindex snuik
> +The @uref{https://gitlab.com/janneke/snuik, Snuik IRC bot} can be run as
> +a daemon to aid talking to users that are currently off-line.  With the
> +@code{(gnu home services messaging)} service, you can configure Snuik to
> +run upon login.

nitpick: I've only ever seen 'offline' spelled as a single word.

[...]

> +
> +;;;
> +;;; Snuik.
> +;;;
> +(define-record-type* <home-snuik-configuration>
> +  home-snuik-configuration make-home-snuik-configuration
> +  home-snuik-configuration?
> +  (snuik         home-snuik-snuik       ;file-like
> +                 (default snuik))
> +  (server        home-snuik-server      ;string
> +                 (default #f))
> +  (port          home-snuik-port        ;integer
> +                 (default #f))
> +  (nick          home-snuik-nick        ;string
> +                 (default #f))
> +  (password      home-snuik-password    ;string
> +                 (default #f))
> +  (password-file home-snuik-password-file ;string
> +                 (default #f))
> +  (channels      home-snuik-channels    ;list of string
> +                 (default '()))
> +  (extra-options home-snuik-extra-options ;list of string
> +                 (default '())))

I'd use define-configuration/no-serialization from (gnu services configuration), which
will type-check the field values and produce useful errors in case of a
mistake, which is more useful than a comment in the source file :-).

> +(define (home-snuik-services config)
> +  "Return a <shepherd-service> for snuik with CONFIG."
> +  (match-record config
> +      <home-snuik-configuration>
> +      (snuik server port nick password password-file channels extra-options)
> +    (let* ((snuik (file-append snuik "/bin/snuik"))
> +           (command #~'(#$snuik
> +                        #$@(if server
> +                               #~("--server" #$server)
> +                               #~())
> +                        #$@(if port
> +                               #~("--port" (number->string port))
> +                               #~())
> +                        #$@(if nick
> +                               #~("--nick" nick)
> +                               #~())
> +                        #$@(if password
> +                               #~("--password" password)
> +                               #~())
> +                        #$@(if password-file
> +                               #~("--password-file" password-file)
> +                               #~())
> +                        #$@(if (pair? channels)
> +                               #~("--channels" (string-join channels ","))
> +                               #~())
> +                        #$@extra-options))
> +           (log-file #~(string-append %user-log-dir "/snuik.log")))
> +      (list (shepherd-service
> +             (documentation "Run the snuik IRC bot.")
> +             (provision '(snuik))
> +             (modules '((shepherd support))) ;for '%user-log-dir'
> +             (start #~(make-forkexec-constructor #$command
> +                                                 #:log-file #$log-file))
> +             (stop #~(make-kill-destructor)))))))

Can home services use the least-authority-wrapper to containerize the
processes?  If yes, that'd be nice to use it.
  
Janneke Nieuwenhuizen March 12, 2025, 3:40 p.m. UTC | #2
Maxim Cournoyer writes:

Hi Maxim,

> Janneke Nieuwenhuizen <janneke@gnu.org> writes:
>
>> * gnu/home/services/messaging.scm (<home-snuik-configuration>): New type.
>> (home-snuik-services, home-snuik-service-type): New procedures.
>> * doc/guix.texi (Messaging Home Services): Document it.
>>
>> Change-Id: I1e278e7d8ed04efcb1a2ce9e12e69cb6a31a9fa4
>> ---
>>  doc/guix.texi                   | 58 ++++++++++++++++++++++++-
>>  gnu/home/services/messaging.scm | 77 ++++++++++++++++++++++++++++++++-
>
> Wouldn't such a service be a more natural match for a system service?
> It seems like something I'd like running on a headless server.

I suppose you're right.  I've been thinking about that but am not too
thrilled of running snuik v0.2 as root.  I'll make it a system service
and use (for-home ...) to provide a home service.  Using the
least-authority-wrapper should (thanks for mentioning that, I wasn't
aware of this feature!) address my concerns about taking this route.

>>  2 files changed, 132 insertions(+), 3 deletions(-)
>>
>> diff --git a/doc/guix.texi b/doc/guix.texi
>> index d109877a32..f35e156376 100644
>> --- a/doc/guix.texi
>> +++ b/doc/guix.texi
>> @@ -36,7 +36,7 @@
>>  Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Efraim Flashner@*
>>  Copyright @copyright{} 2016 John Darrington@*
>>  Copyright @copyright{} 2016, 2017 Nikita Gillmann@*
>> -Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Janneke Nieuwenhuizen@*
>> +Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Janneke Nieuwenhuizen@*
>
> Maybe use 2016-2025 :-).

Hmm.  I thought you needed to have a special exception in the README to
be able for that to hold up in court.  I've been postponing to look into
this mess (I used to be too heavily into copyright in my LilyPond years).
However, it seems today is the day :)

From <https://www.gnu.org/prep/maintain/html_node/Copyright-Notices.html>

--8<---------------cut here---------------start------------->8---
You can use a range (‘2008-2010’) instead of listing individual years
(‘2008, 2009, 2010’) if and only if: 1) every year in the range,
inclusive, really is a “copyrightable” year that would be listed
individually; and 2) you make an explicit statement in a README file
about this usage.
--8<---------------cut here---------------end--------------->8---

Sadly, the manual does not seem to give a template to use for this, and
I have learnt to stay away from authoring legal texts.  I just asked
gnu-prog-discuss about this.

I cannot find such a statement in the Guix README?  Ludo'?

>> +The @uref{https://gitlab.com/janneke/snuik, Snuik IRC bot} can be run as
>> +a daemon to aid talking to users that are currently off-line.  With the
>> +@code{(gnu home services messaging)} service, you can configure Snuik to
>> +run upon login.
>
> nitpick: I've only ever seen 'offline' spelled as a single word.

The numbers

--8<---------------cut here---------------start------------->8---
15:53:37 janneke@glimdal:~/src/guix/core-packages-team 
$ git grep off-line |wc -l
39
15:54:23 janneke@glimdal:~/src/guix/core-packages-team 
$ git grep offline |wc -l
448
--8<---------------cut here---------------end--------------->8---

are overwhelmingly in your favor, so I'll take your suggestion, thanks :)
 
>> +
>> +;;;
>> +;;; Snuik.
>> +;;;
>> +(define-record-type* <home-snuik-configuration>
>> +  home-snuik-configuration make-home-snuik-configuration
>> +  home-snuik-configuration?
>> +  (snuik         home-snuik-snuik       ;file-like
>> +                 (default snuik))
[..]

> I'd use define-configuration/no-serialization from (gnu services configuration), which
> will type-check the field values and produce useful errors in case of a
> mistake, which is more useful than a comment in the source file :-).

Ok.

>> +(define (home-snuik-services config)
[..]
>> +             (start #~(make-forkexec-constructor #$command
>> +                                                 #:log-file #$log-file))
>> +             (stop #~(make-kill-destructor)))))))
>
> Can home services use the least-authority-wrapper to containerize the
> processes?  If yes, that'd be nice to use it.

Looking at dicod-shepherd-service, it has (if home-service?...) and uses
the least-authority-wrapper.  I'm wondering how this works for read
access to the password-file and read/write access to snuik's database
store directory but I'll look into this.

Thanks for your very useful comments, I've got some homework! :)

I intend to send a v2 with system+home service and
least-authority-wrapper...but I need to learn a few things about bothe
these things and then also do some testing.

Greetings,
Janneke
  

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index d109877a32..f35e156376 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -36,7 +36,7 @@ 
 Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Efraim Flashner@*
 Copyright @copyright{} 2016 John Darrington@*
 Copyright @copyright{} 2016, 2017 Nikita Gillmann@*
-Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Janneke Nieuwenhuizen@*
+Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Janneke Nieuwenhuizen@*
 Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Julien Lepiller@*
 Copyright @copyright{} 2016 Alex ter Weele@*
 Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Christopher Baines@*
@@ -49714,6 +49714,62 @@  Messaging Home Services
 @end table
 @end deftp
 
+@cindex snuik
+The @uref{https://gitlab.com/janneke/snuik, Snuik IRC bot} can be run as
+a daemon to aid talking to users that are currently off-line.  With the
+@code{(gnu home services messaging)} service, you can configure Snuik to
+run upon login.
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-snuik-service-type
+        (home-snuik-configuration
+         (password-file ".password.snuik")
+         (channels '("#bootstrappable"
+                     "#dezyne"
+                     "#guix-risc-v"
+                     "#lilypond"))))
+@end lisp
+
+@defvar home-snuik-service-type
+This is the type of the Snuik home service, whose value is a
+@code{home-snuik-configuration} object.
+@end defvar
+
+@deftp {Data Type} home-snuik-configuration
+Available @code{home-snuik-configuration} fields are:
+
+@table @asis
+@item @code{snuik} (default: @code{snuik}) (type: file-like)
+The Snuik package to use.
+
+@item @code{server} (default: @code{"irc.libera.chat"})
+The IRC server to connect to.
+
+@item @code{port} (default: @code{6665})
+Port number used by the IRC server.
+
+@item @code{nick} (default: @code{"snuik"})
+The nickname for snuik to use.
+
+@item @code{password} (default: @code{#f})
+The password to use when logging in.
+
+@item @code{password-file} (default: @code{".password.<nick>})
+The file to read the password from to use when logging in.
+
+@item @code{channels} (default: @code{'("##botchat")})
+The channels for snuik to join, a list of strings.
+
+@item @code{extra-options} (default: @code{'()})
+Extra options will be passed to @command{snuik}, please run
+@command{snuik --help } for more information.
+
+@end table
+@end deftp
+
 @node Media Home Services
 @subsection Media Home Services
 
diff --git a/gnu/home/services/messaging.scm b/gnu/home/services/messaging.scm
index bd2f1bb23f..be2a3436ba 100644
--- a/gnu/home/services/messaging.scm
+++ b/gnu/home/services/messaging.scm
@@ -1,5 +1,5 @@ 
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
+;;; Copyright © 2023, 2025 Janneke Nieuwenhuizen <janneke@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -20,12 +20,15 @@  (define-module (gnu home services messaging)
   #:use-module (srfi srfi-26)
   #:use-module (gnu home services)
   #:use-module (gnu home services shepherd)
+  #:use-module (gnu packages irc)
   #:use-module (gnu packages messaging)
   #:use-module (gnu services configuration)
   #:use-module (gnu services shepherd)
   #:use-module (guix records)
   #:use-module (guix gexp)
-  #:export (home-znc-configuration
+  #:export (home-snuik-configuration
+            home-snuik-service-type
+            home-znc-configuration
             home-znc-service-type))
 
 ;;;
@@ -64,3 +67,73 @@  (define home-znc-service-type
    (description
     "Install and configure @command{znc}, an @acronym{IRC, Internet Relay
 Chat} bouncer, as a Shepherd service.")))
+
+
+;;;
+;;; Snuik.
+;;;
+(define-record-type* <home-snuik-configuration>
+  home-snuik-configuration make-home-snuik-configuration
+  home-snuik-configuration?
+  (snuik         home-snuik-snuik       ;file-like
+                 (default snuik))
+  (server        home-snuik-server      ;string
+                 (default #f))
+  (port          home-snuik-port        ;integer
+                 (default #f))
+  (nick          home-snuik-nick        ;string
+                 (default #f))
+  (password      home-snuik-password    ;string
+                 (default #f))
+  (password-file home-snuik-password-file ;string
+                 (default #f))
+  (channels      home-snuik-channels    ;list of string
+                 (default '()))
+  (extra-options home-snuik-extra-options ;list of string
+                 (default '())))
+
+(define (home-snuik-services config)
+  "Return a <shepherd-service> for snuik with CONFIG."
+  (match-record config
+      <home-snuik-configuration>
+      (snuik server port nick password password-file channels extra-options)
+    (let* ((snuik (file-append snuik "/bin/snuik"))
+           (command #~'(#$snuik
+                        #$@(if server
+                               #~("--server" #$server)
+                               #~())
+                        #$@(if port
+                               #~("--port" (number->string port))
+                               #~())
+                        #$@(if nick
+                               #~("--nick" nick)
+                               #~())
+                        #$@(if password
+                               #~("--password" password)
+                               #~())
+                        #$@(if password-file
+                               #~("--password-file" password-file)
+                               #~())
+                        #$@(if (pair? channels)
+                               #~("--channels" (string-join channels ","))
+                               #~())
+                        #$@extra-options))
+           (log-file #~(string-append %user-log-dir "/snuik.log")))
+      (list (shepherd-service
+             (documentation "Run the snuik IRC bot.")
+             (provision '(snuik))
+             (modules '((shepherd support))) ;for '%user-log-dir'
+             (start #~(make-forkexec-constructor #$command
+                                                 #:log-file #$log-file))
+             (stop #~(make-kill-destructor)))))))
+
+(define home-snuik-service-type
+  (service-type
+   (name 'home-snuik)
+   (default-value (home-snuik-configuration))
+   (extensions
+    (list (service-extension home-shepherd-service-type
+                             home-snuik-services)))
+   (description
+    "Install and configure the Snuik IRC bot so that it runs as a Shepherd
+service.")))