unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#63758] home-dicod-service-type
@ 2023-05-27 17:29 Mitchell Schmeisser via Guix-patches via
  2023-05-29 17:28 ` [bug#63758] home-dicod-service-type gnu/service patch Mitchell Schmeisser via Guix-patches via
  0 siblings, 1 reply; 3+ messages in thread
From: Mitchell Schmeisser via Guix-patches via @ 2023-05-27 17:29 UTC (permalink / raw)
  To: 63758

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: 0001-home-add-gnu-home-services-dict.scm-and-home-dicod-s.patch --]
[-- Type: text/x-patch, Size: 4537 bytes --]

From ed111e39aa2d188a146e73251aff63156698bb54 Mon Sep 17 00:00:00 2001
From: Mitchell Schmeisser <mitchellschmeisser@librem.one>
Date: Sat, 27 May 2023 13:22:32 -0400
Subject: [PATCH] home: add gnu/home/services/dict.scm and
 home-dicod-service-type

* gnu/home/services/dict.scm: Add home-dicod-service-type
---
 gnu/home/services/dict.scm | 84 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 gnu/home/services/dict.scm

diff --git a/gnu/home/services/dict.scm b/gnu/home/services/dict.scm
new file mode 100644
index 0000000000..2d745baa5d
--- /dev/null
+++ b/gnu/home/services/dict.scm
@@ -0,0 +1,84 @@
+(define-module (gnu home services dict)
+  #:use-module (srfi srfi-1)
+  #:use-module (guix gexp)
+  #:use-module (guix least-authority)
+  #:use-module (gnu build linux-container)
+  #:use-module (gnu home services)
+  #:use-module (gnu home services shepherd)
+  #:use-module (gnu packages dictionaries)
+  #:use-module (gnu services dict)
+  #:use-module (gnu system file-systems)
+
+  #:export (%home-dicod-database:gcide
+            %home-dicod-configuration
+            home-dicod-service-type))
+
+(define dico-run-time-dir "/tmp/dico")
+
+(define %home-dicod-database:gcide
+  (dicod-database
+   (name "gcide")
+   (handler "gcide")
+   (options (list #~(string-append "dbdir=" #$gcide "/share/gcide")
+                  #~(string-append "idxdir=" #$dico-run-time-dir)))))
+
+(define %home-dicod-configuration
+  (dicod-configuration
+   (databases (list %home-dicod-database:gcide))))
+
+(define %home-dicod-activation
+  #~(begin
+      (use-modules (guix build utils))
+      (mkdir-p #$dico-run-time-dir)))
+
+(define (home-dicod-shepherd-service config)
+  (let* ((dicod.conf ((@@ (gnu services dict) dicod-configuration-file) config))
+         (interfaces ((@@ (gnu services dict) dicod-configuration-interfaces) config))
+         (dicod      (least-authority-wrapper
+                      (file-append
+                       ((@@ (gnu services dict) dicod-configuration-dico) config) "/bin/dicod")
+                      #:name "dicod"
+                      #:mappings (list (file-system-mapping
+                                        (source dico-run-time-dir)
+                                        (target source)
+                                        (writable? #t))
+                                       (file-system-mapping
+                                        (source "/dev/log")
+                                        (target source))
+                                       (file-system-mapping
+                                        (source dicod.conf)
+                                        (target source)))
+                      #:namespaces (delq 'net %namespaces))))
+    (list (shepherd-service
+           (provision '(dicod))
+           (documentation "Run the dicod daemon.")
+           (start #~(if (and (defined? 'make-inetd-constructor)
+                             #$(= 1 (length interfaces))) ;XXX
+                        (make-inetd-constructor
+                         (list #$dicod "--inetd" "--foreground"
+                               (string-append "--config=" #$dicod.conf))
+                         (addrinfo:addr
+                          (car (getaddrinfo #$(first interfaces) "dict")))
+                         #:service-name-stem "dicod")
+                        (make-forkexec-constructor
+                         (list #$dicod "--foreground"
+                               (string-append "--config=" #$dicod.conf)))))
+           (stop #~(if (and (defined? 'make-inetd-destructor)
+                            #$(= 1 (length interfaces))) ;XXX
+                       (make-inetd-destructor)
+                       (make-kill-destructor)))
+           (actions (list (shepherd-configuration-action dicod.conf)))))))
+
+(define home-dicod-service-type
+  (service-type
+   (name 'home-dicod)
+   (extensions (list (service-extension home-shepherd-service-type
+                                        home-dicod-shepherd-service)
+                     (service-extension home-activation-service-type
+                                        (const %home-dicod-activation))))
+   (default-value %home-dicod-configuration)
+   (description
+    "Run @command{dicod}, the dictionary server of
+@uref{https://www.gnu.org/software/dico, GNU Dico}.  @command{dicod}
+implements the standard DICT protocol supported by clients such as
+@command{dico} and GNOME Dictionary as a user.")))
-- 
2.39.1


[-- Attachment #2: Type: text/plain, Size: 7411 bytes --]


Here is a patch to add dicod service type to Guix Home,
and here are some things I wrote about the process.

---------------------------------

#+title: Extending Guix Home
#+author: Mitchell Schmeisser <mitchellschmeisser@librem.one>

I recently learned of a new [[https://www.masteringemacs.org/article/wordsmithing-in-emacs][Emacs feature]] ~M-x dictionary~ which
allows you to connect to a dictionary server using a special protocol.
Out of the box Emacs can reach out to places like [[https://dictionary.com][dictionary.com]]
to look up the definition of words.
This is convenient, but it is a [[https://www.gnu.org/philosophy/who-does-that-server-really-serve.en.html][Service as a Software Substitute]].
There is no reason why I cannot run my own dictionary server and
protect my privacy.  After all, you never know when the NSA will try
to change the definitions of words to make you look foolish.

It is very easy to run one of these servers in a freedom respecting way,
simply get your hands on a copy of GNU Dico and your dictionary of choice
and run ~dicod~. Most people like to run ~dicod~ as a service which is
managed by the init system.

To my dismay every tutorial and blog post required the user to
use ~sudo~ to install programs and modify the init system.
This is less than desirable.

A wonderful, often under-rated, feature of GNU Guix is /unprivileged/
package management. An even more under-rated feature of GNU Guix
is /unprivileged/ service management provided by [[https://guix.gnu.org/en/blog/2022/keeping-ones-home-tidy/][Guix Home]].

* Guix Home Services

Guix Home allows you to extend the declarative Guix model to your home
environment.
You can install packages and dot files transactionally, making migration
to a new machine painless and consistent.

Unfortunately, at the time of writing there are very few Guix Home services
and most of them simply generate dot files for this or that shell.

Or are there?

* System Services are Home Services

GNU Guix has a ~dico-service-type~ which is very easy to use.
Unfortunately this service type requires system-wide modifications and
requires root.  It is also out of reach for people running Guix on a
foreign distribution where ~guix system reconfigure~ is not an option.

Below is the definition of the ~dicod-service-type~ designed for the
Guix System.
#+BEGIN_SRC scheme
  ;; from gnu/services/dict.scm
  (define dicod-service-type
    (service-type
     (name 'dict)
     (extensions
      (list (service-extension account-service-type
			       (const %dicod-accounts))
	    (service-extension activation-service-type
			       (const %dicod-activation))
	    (service-extension shepherd-root-service-type
			       dicod-shepherd-service)))
     (default-value (dicod-configuration))
     (description
      "Run @command{dicod}, the dictionary server of
    @uref{https://www.gnu.org/software/dico, GNU Dico}.  @command{dicod}
    implements the standard DICT protocol supported by clients such as
    @command{dico} and GNOME Dictionary.")))
#+END_SRC

Here is the definition of the ~home-dicod-service-type~.
The only difference between them is for Guix Home we want to run
all processes as the user and cannot create new accounts.

#+BEGIN_SRC scheme
  (define home-dicod-service-type
    (service-type
     (name 'home-dict)
     (extensions (list (service-extension home-shepherd-service-type
					  home-dicod-shepherd-service)
		       (service-extension home-activation-service-type
					  (const %home-dicod-activation))))
     (default-value %home-dicod-configuration)
     (description
      "Run @command{dicod}, the dictionary server of
  @uref{https://www.gnu.org/software/dico, GNU Dico}.  @command{dicod}
  implements the standard DICT protocol supported by clients such as
  @command{dico} and GNOME Dictionary as a user.")))
#+END_SRC

In general, this is the only difference between a Home Service and a System Service.
System services will generally insist on an account specifically for running a process
and take some steps to create an environment where that account has just enough permissions
to do the job.  Home services all run as the user and so the the user
needs to have enough permissions to do the job. =/var/run= becomes =$XDG_RUNTIME_DIR= or
=/run/user/$(uid)/=.

* Unprivileged, Containerized, dictionary server

Using the code below I can finally look up the definitions of words in
complete, unprivileged, freedom!  This service spawns a ~dicod~ server
isolated from the system using ~least-authority-wrapper~.  It shares
the network namespace and can see it's run-time directory and
read-only configuration file and that is it.

This is nice, but could it be nicer?

#+BEGIN_SRC scheme
  ;; A new database is defined which places the idxdir argument
  ;; in a place writable by the user.
  ;; /tmp was chosen over XDG_RUNTIME_DIR or /run/user/
  ;; because I do not know when this is evaluated.
  ;; guix pull time or guix home reconfigure time.
  ;; I think these are the same in most cases but maybe they're not?
  (define runtime-dir "/tmp/dico")

  (define %home-dicod-database:gcide
    (dicod-database
     (name "gcide")
     (handler "gcide")
     (options (list #~(string-append "dbdir=" #$gcide "/share/gcide")
		    #~(string-append "idxdir=" #$runtime-dir)))))

  (define %home-dicod-configuration
    (dicod-configuration
     (databases (list %home-dicod-database:gcide))))

  (define %home-dicod-activation
    #~(begin
	(use-modules (guix build utils))
	(mkdir-p #$runtime-dir)))

  (define (home-dicod-shepherd-service config)
    (let* ((dicod.conf ((@@ (gnu services dict) dicod-configuration-file) config))
	   (interfaces ((@@ (gnu services dict) dicod-configuration-interfaces) config))
	   (dicod      (least-authority-wrapper
			(file-append
			 ((@@ (gnu services dict) dicod-configuration-dico) config) "/bin/dicod")
			#:name "dicod"
			#:mappings (list (file-system-mapping
					  (source runtime-dir)
					  (target source)
					  (writable? #t))
					 (file-system-mapping
					  (source "/dev/log")
					  (target source))
					 (file-system-mapping
					  (source dicod.conf)
					  (target source)))
			#:namespaces (delq 'net %namespaces))))
      (list (shepherd-service
	     (provision '(dicod))
	     (documentation "Run the dicod daemon.")
	     (start #~(if (and (defined? 'make-inetd-constructor)
			       #$(= 1 (length interfaces))) ;XXX
			  (make-inetd-constructor
			   (list #$dicod "--inetd" "--foreground"
				 (string-append "--config=" #$dicod.conf))
			   (addrinfo:addr
			    (car (getaddrinfo #$(first interfaces) "dict")))
			   #:service-name-stem "dicod")
			  (make-forkexec-constructor
			   (list #$dicod "--foreground"
				 (string-append "--config=" #$dicod.conf)))))
	     (stop #~(if (and (defined? 'make-inetd-destructor)
			      #$(= 1 (length interfaces))) ;XXX
			 (make-inetd-destructor)
			 (make-kill-destructor)))
	     (actions (list (shepherd-configuration-action dicod.conf)))))))

#+END_SRC

* Is =gnu/home/services= an Anti-Pattern?

The code above is almost identical to the code located in
=gnu/services/dict.scm=.  The only difference, as a mentioned, is the
account information.  With this in mind, does it make sense to define
Home Services along side their system counter parts in =gnu/services=?

I believe many services in =gnu/services= can run from Guix Home with
only minor modifications.

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [bug#63758] home-dicod-service-type gnu/service patch
  2023-05-27 17:29 [bug#63758] home-dicod-service-type Mitchell Schmeisser via Guix-patches via
@ 2023-05-29 17:28 ` Mitchell Schmeisser via Guix-patches via
  2023-08-07  9:48   ` [bug#63758] home-dicod-service-type Ludovic Courtès
  0 siblings, 1 reply; 3+ messages in thread
From: Mitchell Schmeisser via Guix-patches via @ 2023-05-29 17:28 UTC (permalink / raw)
  To: 63758

[-- Attachment #1: 0001-gnu-services-dict.scm-Add-home-dicod-service-type.patch --]
[-- Type: text/x-patch, Size: 7758 bytes --]

From 45c8efc0dbf321cb4cd59ed7f509f241ae8034ce Mon Sep 17 00:00:00 2001
From: Mitchell Schmeisser <mitchellschmeisser@librem.one>
Date: Mon, 29 May 2023 13:21:46 -0400
Subject: [PATCH] gnu/services/dict.scm: Add home-dicod-service-type

---
 gnu/services/dict.scm | 71 +++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 16 deletions(-)

diff --git a/gnu/services/dict.scm b/gnu/services/dict.scm
index 5a61085..88493ae 100644
--- a/gnu/services/dict.scm
+++ b/gnu/services/dict.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2016 Sou Bunnbu <iyzsong@gmail.com>
-;;; Copyright © 2016, 2017, 2018, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016, 2017, 2018, 2020, 2022, 2023 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2017 Huang Ying <huang.ying.caritas@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -26,6 +26,8 @@ (define-module (gnu services dict)
   #:use-module (guix least-authority)
   #:use-module (gnu services)
   #:use-module (gnu services shepherd)
+  #:use-module (gnu home services)
+  #:use-module (gnu home services shepherd)
   #:use-module (gnu system shadow)
   #:use-module ((gnu packages admin) #:select (shadow))
   #:use-module (gnu packages dico)
@@ -37,10 +39,12 @@ (define-module (gnu services dict)
   #:use-module (ice-9 match)
   #:export (dicod-service  ; deprecated
             dicod-service-type
+            home-dicod-service-type
             dicod-configuration
             dicod-handler
             dicod-database
-            %dicod-database:gcide))
+            %dicod-database:gcide
+            %home-dicod-database:gcide))
 
 \f
 ;;;
@@ -56,7 +60,9 @@ (define-record-type* <dicod-configuration>
   (handlers    dicod-configuration-handlers       ;list of <dicod-handler>
                (default '()))
   (databases   dicod-configuration-databases      ;list of <dicod-database>
-               (default (list %dicod-database:gcide))))
+               (default (list %dicod-database:gcide)))
+  (guix-home?  dicod-configuration-guix-home?
+               (default #f)))
 
 (define-record-type* <dicod-handler>
   dicod-handler make-dicod-handler
@@ -80,6 +86,13 @@ (define %dicod-database:gcide
    (options (list #~(string-append "dbdir=" #$gcide "/share/gcide")
                   "idxdir=/var/run/dicod"))))
 
+(define %home-dicod-database:gcide
+  (dicod-database
+   (name "gcide")
+   (handler "gcide")
+   (options (list #~(string-append "dbdir=" #$gcide "/share/gcide")
+                  "idxdir=/tmp/dicod"))))
+
 (define %dicod-accounts
   (list (user-group
          (name "dicod")
@@ -137,23 +150,30 @@ (define configuration->text
 
   (apply mixed-text-file "dicod.conf" (configuration->text config)))
 
-(define %dicod-activation
+(define (dicod-activation config)
   #~(begin
       (use-modules (guix build utils))
-      (let ((user   (getpwnam "dicod"))
-            (rundir "/var/run/dicod"))
+      (let* ((guix-home? #$(dicod-configuration-guix-home? config))
+             (user   (if guix-home?
+                         (getuid) (getpwnam "dicod")))
+             (rundir (if guix-home?
+                         "/tmp/dicod"
+                         "/var/run/dicod")))
         (mkdir-p rundir)
-        (chown rundir (passwd:uid user) (passwd:gid user)))))
+        (unless guix-home?
+          (chown rundir (passwd:uid user) (passwd:gid user))))))
 
-(define (dicod-shepherd-service config)
-  (let* ((dicod.conf (dicod-configuration-file config))
+(define* (dicod-shepherd-service config)
+  (let* ((guix-home? (dicod-configuration-guix-home? config))
+         (rt-dir (if guix-home? "/tmp/dicod" "/var/run/dicod"))
+         (dicod.conf (dicod-configuration-file config))
          (interfaces (dicod-configuration-interfaces config))
          (dicod      (least-authority-wrapper
                       (file-append (dicod-configuration-dico config)
                                    "/bin/dicod")
                       #:name "dicod"
                       #:mappings (list (file-system-mapping
-                                        (source "/var/run/dicod")
+                                        (source rt-dir)
                                         (target source)
                                         (writable? #t))
                                        (file-system-mapping
@@ -165,21 +185,28 @@ (define (dicod-shepherd-service config)
                       #:namespaces (delq 'net %namespaces))))
     (list (shepherd-service
            (provision '(dicod))
-           (requirement '(user-processes))
+           (requirement (if guix-home? '() '(user-processes)))
            (documentation "Run the dicod daemon.")
            (start #~(if (and (defined? 'make-inetd-constructor)
                              #$(= 1 (length interfaces))) ;XXX
                         (make-inetd-constructor
                          (list #$dicod "--inetd" "--foreground"
                                (string-append "--config=" #$dicod.conf))
-                         (addrinfo:addr
-                          (car (getaddrinfo #$(first interfaces) "dict")))
-                         #:user "dicod" #:group "dicod"
+                         (list (endpoint
+                                (addrinfo:addr
+                                 (car (getaddrinfo #$(first interfaces)
+                                                   "dict")))))
+                         #:requirements '#$requirement
+                         #$@(if guix-home?
+                                '()
+                                '(#:user "dicod" #:group "dicod"))
                          #:service-name-stem "dicod")
                         (make-forkexec-constructor
                          (list #$dicod "--foreground"
                                (string-append "--config=" #$dicod.conf))
-                         #:user "dicod" #:group "dicod")))
+                         #$@(if guix-home?
+                                '()
+                                '(#:user "dicod" #:group "dicod")))))
            (stop #~(if (and (defined? 'make-inetd-destructor)
                             #$(= 1 (length interfaces))) ;XXX
                        (make-inetd-destructor)
@@ -193,7 +220,7 @@ (define dicod-service-type
     (list (service-extension account-service-type
                              (const %dicod-accounts))
           (service-extension activation-service-type
-                             (const %dicod-activation))
+                             dicod-activation)
           (service-extension shepherd-root-service-type
                              dicod-shepherd-service)))
    (default-value (dicod-configuration))
@@ -203,6 +230,18 @@ (define dicod-service-type
 implements the standard DICT protocol supported by clients such as
 @command{dico} and GNOME Dictionary.")))
 
+(define home-dicod-service-type
+  (service-type
+   (inherit dicod-service-type)
+   (extensions (list (service-extension home-shepherd-service-type
+                                        dicod-shepherd-service)
+                     (service-extension home-activation-service-type
+                                        dicod-activation)))
+   (default-value (dicod-configuration
+                   (guix-home? #t)
+                   (databases (list %home-dicod-database:gcide))))))
+
+
 (define-deprecated (dicod-service #:key (config (dicod-configuration)))
   dicod-service-type
   "Return a service that runs the @command{dicod} daemon, an implementation
-- 
2.39.1


[-- Attachment #2: Type: text/plain, Size: 453 bytes --]

Here is an alternate patch which modifies gnu/services/dict.scm to
provide home-dicod-service-type.

This seems better than the code in gnu/home/services/dict.scm which
makes use of a lot of ~(@@ (gnu services dict))~ accessors to parse the
configuration data. I think having home services defined along side
their system counter parts makes it more likely people studying the code
while writing new services will include a home implementation as well.

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [bug#63758] home-dicod-service-type
  2023-05-29 17:28 ` [bug#63758] home-dicod-service-type gnu/service patch Mitchell Schmeisser via Guix-patches via
@ 2023-08-07  9:48   ` Ludovic Courtès
  0 siblings, 0 replies; 3+ messages in thread
From: Ludovic Courtès @ 2023-08-07  9:48 UTC (permalink / raw)
  To: Mitchell Schmeisser; +Cc: 63758

Hi Mitchell,

Mitchell Schmeisser <mitchellschmeisser@librem.one> skribis:

> Here is an alternate patch which modifies gnu/services/dict.scm to
> provide home-dicod-service-type.

Please check out <https://issues.guix.gnu.org/65119>, which is an
attempt to provide a consistent and simple way to “port” System services
to Home, including dicod.

Ludo’.




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-08-07  9:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-27 17:29 [bug#63758] home-dicod-service-type Mitchell Schmeisser via Guix-patches via
2023-05-29 17:28 ` [bug#63758] home-dicod-service-type gnu/service patch Mitchell Schmeisser via Guix-patches via
2023-08-07  9:48   ` [bug#63758] home-dicod-service-type Ludovic Courtès

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).