all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Modular home configuration
@ 2024-11-09 17:35 Ian Eure
  2024-11-09 19:09 ` Tomas Volf
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ian Eure @ 2024-11-09 17:35 UTC (permalink / raw)
  To: help-guix

Hi folks,

I’m trying to make my home configuration more modular, so I can 
better support system variances.  For example, I have a laptop I 
use interactively, and a headless machine that runs Cuirass.  It’s 
advantageous to share certain aspects of the home configuration 
between the two machines (shell prompt/environment, GPG agent, 
etc), but not others (anything X11/graphical stuff shouldn’t be on 
the build machine).  One approach to this is to define packages 
and services and reference them in the home configuration.  What I 
dislike about this is that many things require both packages and 
services, and I’d prefer to have a way to completely encapsulate 
that -- for example, the mpd-mpc package to control my music 
server, plus a home-environment-variables-service-type to set 
MPD_HOST.

I attempted to solve this by writing a procedure:

    (define (+mpd-client home-config)
      (home-environment
        (inherit home-config)
        (packages (cons mpd-mpc (home-environment-packages 
        home-config)))
        (services
          (cons
            (simple-service
              'mpd-environment-service
              home-environment-variables-service-type
              '(("MPD_HOST" . "audio.box")))
            (home-environment-services home-config)))))

Which I can then wrap around a home-environment to add the mpd-mpc 
package and environment variable it needs to work:

    (+mpc-client (home-environment ...))

Surprisingly, this doesn’t work -- it complains that there’s more 
than one "home" service type.  I’m not sure why that is, and I 
haven’t been able to see anything obviously wrong in the REPL -- 
though I haven’t been able to get my actual home configuration up 
in the Emacs-Guix REPL, due to #67290.

Does anyone have a suggestion for a workaround for this issue, 
explanation of how two home services are ending up in the config, 
or a better approach for building modular home configs?

Thanks,

  — Ian


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

* Re: Modular home configuration
  2024-11-09 17:35 Modular home configuration Ian Eure
@ 2024-11-09 19:09 ` Tomas Volf
  2024-11-09 19:30 ` Edouard Klein
  2024-11-09 19:30 ` Edouard Klein
  2 siblings, 0 replies; 4+ messages in thread
From: Tomas Volf @ 2024-11-09 19:09 UTC (permalink / raw)
  To: Ian Eure; +Cc: help-guix

[-- Attachment #1: Type: text/plain, Size: 8365 bytes --]


Hello,

Ian Eure <ian@retrospec.tv> writes:

> Hi folks,
>
> I’m trying to make my home configuration more modular, so I can better support
> system variances.  For example, I have a laptop I use interactively, and a
> headless machine that runs Cuirass.  It’s advantageous to share certain aspects
> of the home configuration between the two machines (shell prompt/environment,
> GPG agent, etc), but not others (anything X11/graphical stuff shouldn’t be on
> the build machine).  One approach to this is to define packages and services and
> reference them in the home configuration.  What I dislike about this is that
> many things require both packages and services, and I’d prefer to have a way to
> completely encapsulate that -- for example, the mpd-mpc package to control my
> music server, plus a home-environment-variables-service-type to set MPD_HOST.
>
> I attempted to solve this by writing a procedure:
>
>    (define (+mpd-client home-config)
>      (home-environment
>        (inherit home-config)
>        (packages (cons mpd-mpc (home-environment-packages         home-config)))
>        (services
>          (cons
>            (simple-service
>              'mpd-environment-service
>              home-environment-variables-service-type
>              '(("MPD_HOST" . "audio.box")))
>            (home-environment-services home-config)))))
>
> Which I can then wrap around a home-environment to add the mpd-mpc package and
> environment variable it needs to work:
>
>    (+mpc-client (home-environment ...))
>
> Surprisingly, this doesn’t work -- it complains that there’s more than one
> "home" service type.  I’m not sure why that is, and I haven’t been able to see
> anything obviously wrong in the REPL -- though I haven’t been able to get my
> actual home configuration up in the Emacs-Guix REPL, due to #67290.

It is the same as with operating-system.  While you are setting the
(services) field, the accessor is (home-environment-user-services).

(home-environment-services home) returns (at least as far I understand
it) something like (append (home-environment-user-services home)
(home-environment-essential-services home)).

Hence the "more that one home services type", you get it twice, once via
the (services) you set in +mpc-client (because it includes
essential-services), and once by the essential-services directly.

>
> Does anyone have a suggestion for a workaround for this issue, explanation of
> how two home services are ending up in the config,

See above.

> or a better approach for building modular home configs?

Not sure if better, but different.  I am using two variations of the
same approach.  One is to define a new service type that takes care of
adding all necessary bits into the home environment.  The following for
example defines home-keychain-service-type for starting keychain[0].

--8<---------------cut here---------------start------------->8---
(define-configuration/no-serialization home-keychain-configuration
  (keychain-package
   (package keychain)
   "Package to use keychain from.")
  (ssh-package
   (package openssh)
   "SSH package to add into the profile.")
  (gpg-package
   (package gnupg)
   "GPG package to add into the profile.")
  (ssh-keys
   (list-of-strings '())
   "Ensure the ssh-agent is started and register the listed keys into it.")
  (gpg-keys
   (list-of-strings '())
   "Ensure the gpg-agent is started and register the listed keys into it."))

(define (q s)
  "Quote string into a form suitable for shell."
  (string-append "'"
                 (string-replace-substring s "'" "'\\'")
                 "'"))

(define (home-keychain-configuration->file config)
  (let* ((ssh-keys (home-keychain-configuration-ssh-keys config))
         (ssh? (pair? ssh-keys))
         (gpg-keys (home-keychain-configuration-gpg-keys config))
         (gpg? (pair? gpg-keys))
         (agents (string-join (append (if ssh? '("ssh") '())
                                      (if gpg? '("gpg") '()))
                              ","))
         (keys (string-append (string-join (map q ssh-keys) " " 'suffix)
                              (string-join (map q gpg-keys) " " 'suffix))))
    (mixed-text-file "keychain-init"
                     "eval $("
                     keychain "/bin/keychain"
                     " --agents " agents
                     " --eval "
                     " --quiet "
                     " -Q "
                     keys
                     ")")))

(define (home-keychain-bash config)
  (home-bash-extension
   (bash-profile (list (home-keychain-configuration->file config)))))

(define (home-keychain-profile config)
  (list (home-keychain-configuration-ssh-package config)
        (home-keychain-configuration-gpg-package config)))

(define home-keychain-service-type
  (service-type
   (name 'home-keychain)
   (extensions (list (service-extension home-bash-service-type
                                        home-keychain-bash)
                     (service-extension home-profile-service-type
                                        home-keychain-profile)))
   (description "Start a keychain on login.")))
--8<---------------cut here---------------end--------------->8---

The interesting piece here is the `home-profile-service-type', which
allows a service to add additional packages into the home environment
(same as you would do with (package) field).

However the limitation is that some services do not support extensions,
so for those case I just have procedure or list (depending on whether
configuration is required) with the required services, and use (append).
Following is an example from my configuration:

--8<---------------cut here---------------start------------->8---
(define* (home-desktop-services #:key (mpv-config %default-mpv-config))
  (list (simple-service 'pkgs-desktop home-profile-service-type
                        %desktop-packages)
        (simple-service 'home-files home-files-service-type
                        `((".xinitrc" ,file/xinitrc)
                          (".Xresources" ,file/Xresources)))
        (simple-service
         'im-env-vars home-environment-variables-service-type
         '(("GTK_IM_MODULE" . "ibus")
           ("QT_IM_MODULE" . "ibus")
           ("XMODIFIERS" . "@im=ibus")
           ("GTK2_RC_FILES" . "$HOME/.config/gtk-2.0/gtkrc")
           ;; TODO: Are these still required?  If yes, try to get rid of them.
           ("GUIX_GTK2_IM_MODULE_FILE"
            . "$HOME/.guix-home/profile/lib/gtk-2.0/2.10.0/immodules-gtk2.cache")
           ("GUIX_GTK3_IM_MODULE_FILE"
            . "$HOME/.guix-home/profile/lib/gtk-3.0/3.0.0/immodules-gtk3.cache")))

        (simple-service 'desktop-xdg-config-files
                        home-xdg-configuration-files-service-type
                        `(("i3/config" ,file/i3/config)
                          ("gtk-2.0/gtkrc" ,file/gtk-2/gtkrc)
                          ("gtk-3.0/settings.ini" ,file/gtk-3/settings.ini)
                          ("gtk-3.0/gtk.css" ,file/gtk-3/gtk.css)
                          ("mpv/mpv.conf" ,(mpv-config->file mpv-config))))

        (service home-startx-command-service-type)

        (service home-dbus-service-type)))
--8<---------------cut here---------------end--------------->8---

And then my in my home environment:

--8<---------------cut here---------------start------------->8---
  (let ((home %basic-home))
    (home-environment
     (inherit home)

     (packages ...)
     (services
      (append
       (list ...)
       (home-desktop-services)
       (home-environment-user-services home)))))
--8<---------------cut here---------------end--------------->8---



I am not convinced this approach is the best, originally I had it the
same way you had in a functional style with a helper procedure, but
rewrote it to this model since Guix already has a concept of "services",
so I wanted to try to mirror it.

Maybe I will switch back to the functional style.  Not sure yet.


Hope this helps,
Tomas

0: https://www.funtoo.org/Funtoo:Keychain

-- 
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 853 bytes --]

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

* Re: Modular home configuration
  2024-11-09 17:35 Modular home configuration Ian Eure
  2024-11-09 19:09 ` Tomas Volf
@ 2024-11-09 19:30 ` Edouard Klein
  2024-11-09 19:30 ` Edouard Klein
  2 siblings, 0 replies; 4+ messages in thread
From: Edouard Klein @ 2024-11-09 19:30 UTC (permalink / raw)
  To: help-guix

I'm on mobile, so I'll give you a better answer soon, but I built a system around this exact idea:


<https://guix-hosting.com/docs/tuto/getting-started.html>

And I have ported it to home configurations


<https://gitlab.com/edouardklein/guix/-/blob/beaverlabs/beaver/home.scm?ref_type=heads>

You can poke around these links to get an idea, but i will write something better soon, sorry about the quick answer now.

Le 9 novembre 2024 18:35:10 GMT+01:00, Ian Eure <ian@retrospec.tv> a écrit :
>Hi folks,
>
>I’m trying to make my home configuration more modular, so I can better support system variances.  For example, I have a laptop I use interactively, and a headless machine that runs Cuirass.  It’s advantageous to share certain aspects of the home configuration between the two machines (shell prompt/environment, GPG agent, etc), but not others (anything X11/graphical stuff shouldn’t be on the build machine).  One approach to this is to define packages and services and reference them in the home configuration.  What I dislike about this is that many things require both packages and services, and I’d prefer to have a way to completely encapsulate that -- for example, the mpd-mpc package to control my music server, plus a home-environment-variables-service-type to set MPD_HOST.
>
>I attempted to solve this by writing a procedure:
>
>   (define (+mpd-client home-config)
>     (home-environment
>       (inherit home-config)
>       (packages (cons mpd-mpc (home-environment-packages        home-config)))
>       (services
>         (cons
>           (simple-service
>             'mpd-environment-service
>             home-environment-variables-service-type
>             '(("MPD_HOST" . "audio.box")))
>           (home-environment-services home-config)))))
>
>Which I can then wrap around a home-environment to add the mpd-mpc package and environment variable it needs to work:
>
>   (+mpc-client (home-environment ...))
>
>Surprisingly, this doesn’t work -- it complains that there’s more than one "home" service type.  I’m not sure why that is, and I haven’t been able to see anything obviously wrong in the REPL -- though I haven’t been able to get my actual home configuration up in the Emacs-Guix REPL, due to #67290.
>
>Does anyone have a suggestion for a workaround for this issue, explanation of how two home services are ending up in the config, or a better approach for building modular home configs?
>
>Thanks,
>
> — Ian
>

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

* Re: Modular home configuration
  2024-11-09 17:35 Modular home configuration Ian Eure
  2024-11-09 19:09 ` Tomas Volf
  2024-11-09 19:30 ` Edouard Klein
@ 2024-11-09 19:30 ` Edouard Klein
  2 siblings, 0 replies; 4+ messages in thread
From: Edouard Klein @ 2024-11-09 19:30 UTC (permalink / raw)
  To: help-guix

The magic is here <https://gitlab.com/edouardklein/guix/-/blob/beaverlabs/beaver/functional-home-services.scm?ref_type=heads>

Le 9 novembre 2024 18:35:10 GMT+01:00, Ian Eure <ian@retrospec.tv> a écrit :
>Hi folks,
>
>I’m trying to make my home configuration more modular, so I can better support system variances.  For example, I have a laptop I use interactively, and a headless machine that runs Cuirass.  It’s advantageous to share certain aspects of the home configuration between the two machines (shell prompt/environment, GPG agent, etc), but not others (anything X11/graphical stuff shouldn’t be on the build machine).  One approach to this is to define packages and services and reference them in the home configuration.  What I dislike about this is that many things require both packages and services, and I’d prefer to have a way to completely encapsulate that -- for example, the mpd-mpc package to control my music server, plus a home-environment-variables-service-type to set MPD_HOST.
>
>I attempted to solve this by writing a procedure:
>
>   (define (+mpd-client home-config)
>     (home-environment
>       (inherit home-config)
>       (packages (cons mpd-mpc (home-environment-packages        home-config)))
>       (services
>         (cons
>           (simple-service
>             'mpd-environment-service
>             home-environment-variables-service-type
>             '(("MPD_HOST" . "audio.box")))
>           (home-environment-services home-config)))))
>
>Which I can then wrap around a home-environment to add the mpd-mpc package and environment variable it needs to work:
>
>   (+mpc-client (home-environment ...))
>
>Surprisingly, this doesn’t work -- it complains that there’s more than one "home" service type.  I’m not sure why that is, and I haven’t been able to see anything obviously wrong in the REPL -- though I haven’t been able to get my actual home configuration up in the Emacs-Guix REPL, due to #67290.
>
>Does anyone have a suggestion for a workaround for this issue, explanation of how two home services are ending up in the config, or a better approach for building modular home configs?
>
>Thanks,
>
> — Ian
>

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

end of thread, other threads:[~2024-11-09 19:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-09 17:35 Modular home configuration Ian Eure
2024-11-09 19:09 ` Tomas Volf
2024-11-09 19:30 ` Edouard Klein
2024-11-09 19:30 ` Edouard Klein

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.