<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Terracrypt</title><id>https://www.terracrypt.net/feeds/tags/guix.xml</id><subtitle>Tag: guix</subtitle><updated>2026-03-01T20:46:16Z</updated><link href="https://www.terracrypt.net/feeds/tags/guix.xml" rel="self" /><link href="https://www.terracrypt.net" /><entry><title>How I manage my Guix System configs</title><id>https://www.terracrypt.net/posts/guix-config.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2026-02-15T13:41:00Z</updated><link href="https://www.terracrypt.net/posts/guix-config.html" rel="alternate" /><content type="html">&lt;p&gt;I've been meaning to write up a post on how I manage my Guix System configurations for a while, because I've hit on a solution that feels kinda nice, inspired by how folks do things in NixOS.&lt;/p&gt;&lt;p&gt;In the NixOS world, there's a tool called &lt;code&gt;nixos-generate-config&lt;/code&gt; that automatically creates both a &lt;code&gt;configuration.nix&lt;/code&gt; and a &lt;code&gt;hardware-configuration.nix&lt;/code&gt; for you. The idea is that the hardware-specific bits (like your partition layout, initrd modules, and such) go into &lt;code&gt;hardware-configuration.nix&lt;/code&gt;, and the rest of your configuration goes into &lt;code&gt;configuration.nix&lt;/code&gt;. We don't have an equivalent of &lt;code&gt;nixos-generate-config&lt;/code&gt; in the Guix world to help automate this, but the general pattern seemed pretty nice, so I've roughly replicated it for my Guix config.&lt;/p&gt;&lt;p&gt;It ends up feeling a little messier in Guix than in Nix, because of some differences in how we build up our configs. But it's not &lt;em&gt;too&lt;/em&gt; bad. There's a couple different layers here, so let's start with my &lt;code&gt;config.scm&lt;/code&gt; for one of my machines. I'm omitting a few things for brevity but you can see the full file contents &lt;a href=&quot;https://codeberg.org/jfred/dotfiles/src/branch/master/guix/guix/system/machines/wired&quot;&gt;here&lt;/a&gt; if you're curious.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-module (system machines wired config)
  ...
  #:use-module (system machines wired hardware-configuration))

(define-public wired-operating-system
  (operating-system
   (inherit hardware-configuration)
   (locale &amp;quot;en_US.utf8&amp;quot;)
   (timezone &amp;quot;America/New_York&amp;quot;)
   (host-name &amp;quot;wired&amp;quot;)
   (users
    (cons*
     (user-account
       ...)
     (operating-system-users hardware-configuration)))
   (packages
    (append
     (list luanti-server
           minetest-game
           ...)
     (operating-system-packages hardware-configuration)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This defines the &lt;code&gt;operating-system&lt;/code&gt; that you would actually use in, for example, a &lt;code&gt;guix system reconfigure&lt;/code&gt;. A few things to note about this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;We're inheriting a lot of this config from something called &lt;code&gt;hardware-configuration&lt;/code&gt;, defined elsewhere.&lt;/li&gt;&lt;li&gt;In a few cases (&lt;code&gt;users&lt;/code&gt; and &lt;code&gt;packages&lt;/code&gt;), we're extending things that were defined in &lt;code&gt;hardware-configuration&lt;/code&gt;. One of the things I use this machine for is hosting a Luanti server, so I need Luanti installed on it - but of course that's not something I need on all my servers! If you can't already tell from this, &lt;code&gt;hardware-configuration&lt;/code&gt; is itself an &lt;code&gt;operating-system&lt;/code&gt; record, so we can pull out each of its fields via procedures like &lt;code&gt;operating-system-packages&lt;/code&gt;. If I just defined the list of packages in this file and didn't append to the packages from &lt;code&gt;hardware-configuration&lt;/code&gt;, I would overwrite the list - which isn't what I want, since I have a base set of packages elsewhere that I'd like to keep.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Okay, let's take a look at &lt;code&gt;hardware-configuration&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-module (system machines wired hardware-configuration)
  #:use-module (gnu)
  #:use-module (nongnu packages linux)
  #:use-module (system machines server-base))

(define-public hardware-configuration
  (operating-system
   (inherit jfred-server-base-system)
   (kernel linux)
   (firmware (list linux-firmware))
   (keyboard-layout (keyboard-layout &amp;quot;us&amp;quot;))

   (bootloader (bootloader-configuration
                (bootloader grub-efi-bootloader)
                (targets (list &amp;quot;/boot/efi&amp;quot;))
                (keyboard-layout keyboard-layout)))

   (mapped-devices (list (mapped-device
                          (source (uuid
                                   &amp;quot;a1775b70-cfc4-44d5-9fc3-0ddaff9eb694&amp;quot;))
                          (target &amp;quot;cryptroot&amp;quot;)
                          (type luks-device-mapping))))

   (file-systems (cons* (file-system
                         (mount-point &amp;quot;/boot/efi&amp;quot;)
                         (device (uuid &amp;quot;AF86-B19B&amp;quot;
                                       'fat32))
                         (type &amp;quot;vfat&amp;quot;))
                       (file-system
                         (mount-point &amp;quot;/&amp;quot;)
                         (device &amp;quot;/dev/mapper/cryptroot&amp;quot;)
                         (type &amp;quot;ext4&amp;quot;)
                         (dependencies mapped-devices)) %base-file-systems))

   (host-name #f)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is where all my disk layout stuff lives, and it's where I keep any hardware-specific quirks. For example, this machine is an Intel NUC, so I need some proprietary firmware for all the hardware to work properly. So I use &lt;code&gt;linux-firmware&lt;/code&gt; and the &lt;code&gt;linux&lt;/code&gt; kernel from Nonguix here.&lt;/p&gt;&lt;p&gt;How exactly to split up the config between files is a bit of a judgement call, because not everything feels like it cleanly falls into one camp or the other. I moved things around a few times as I was putting this together.&lt;/p&gt;&lt;p&gt;You might have also noticed that the &lt;code&gt;hardware-configuration&lt;/code&gt; itself inherits from another config (&lt;code&gt;jfred-server-base-system&lt;/code&gt;). Yeah, I have multiple layers of inheritance here! Here's that definition:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-module (system machines server-base)
  ...
  #:use-module (system machines base))

(define-public jfred-server-base-system
  (operating-system
   ;; Set these in hardware-configuration.scm
   (bootloader #f)
   (host-name #f)
   (file-systems #f)
   (sudoers-file
     (plain-file &amp;quot;sudoers&amp;quot;
                 (string-append (plain-file-content %sudoers-specification)
                                (format #f &amp;quot;~a ALL = NOPASSWD: ALL~%&amp;quot;
                                        &amp;quot;jfred&amp;quot;))))

   ;; Base configs for my servers
   (locale &amp;quot;en_US.utf8&amp;quot;)
   (keyboard-layout (keyboard-layout &amp;quot;us&amp;quot;))
   (timezone &amp;quot;America/New_York&amp;quot;)
   (users (cons* (user-account
                  (name &amp;quot;jfred&amp;quot;)
                  (comment &amp;quot;Jonathan Frederickson&amp;quot;)
                  (group &amp;quot;users&amp;quot;)
                  (home-directory &amp;quot;/home/jfred&amp;quot;)
                  (supplementary-groups '(&amp;quot;wheel&amp;quot; &amp;quot;netdev&amp;quot; &amp;quot;audio&amp;quot; &amp;quot;video&amp;quot;)))
                 %base-user-accounts))
   (packages %base-packages)

   (services
   (append (list
            (service openssh-service-type
                     (openssh-configuration
                      (use-pam? #f)))
            (service elogind-service-type)
            (service dhcpcd-service-type)
            (service dbus-root-service-type)
            (service docker-service-type)
            (service containerd-service-type)
            (service ntp-service-type))
           (jfred-append-base-services %base-services)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is where I keep configuration that should apply to &lt;em&gt;all&lt;/em&gt; of my servers, rather than just one. I always want to have a user for myself in sudoers on each of them, for it to be in my local timezone, and for it to have the &lt;code&gt;us&lt;/code&gt; keyboard layout. And there's a base set of services that I'll almost certainly want on any server I'm running.&lt;/p&gt;&lt;p&gt;This is the part of my config that feels the messiest to me. You might notice the fields set to &lt;code&gt;#f&lt;/code&gt; at the top there; that's because it's an error to have an &lt;code&gt;operating-system&lt;/code&gt; record that does not define all the fields. I'll always need to set the bootloader, filesystems, and hostname for any new machine anyway, so in practice it's not an issue - it just feels a bit weird.&lt;/p&gt;&lt;p&gt;And yes, there's yet another layer of composition with &lt;code&gt;jfred-append-base-services&lt;/code&gt; at the end there. But I think this is where I'm going to stop. :)&lt;/p&gt;&lt;p&gt;I hope this post is helpful to someone in the future! And if you have any other ideas, I'd love to hear about them.&lt;/p&gt;</content></entry><entry><title>Brainstorming - managing a fleet of Guix machines with Goblins</title><id>https://www.terracrypt.net/posts/guix-goblins-fleet.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2024-12-19T17:04:00Z</updated><link href="https://www.terracrypt.net/posts/guix-goblins-fleet.html" rel="alternate" /><content type="html">&lt;p&gt;I've been noodling on the possibility of managing a bunch of Guix machines with Goblins for a little while now. Spent a little time at a local coffee shop today thinking about how this might work...&lt;/p&gt;&lt;p&gt;With both Guix and Goblins being written in Guile, it's at least pretty straightforward to start mashing them up:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(use-modules
 (goblins)
 (goblins actor-lib methods)
 (guix describe))

(define (^guix-machine-mgr bcom)
  (methods
   [(get-channels)
    (current-channels)]))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, functions like &lt;code&gt;current-channels&lt;/code&gt; return Guix records...&lt;/p&gt;&lt;pre&gt;&lt;code&gt;goblins/0@(guile-user) [1]&amp;gt; ($ mgr 'get-channels)
$6 = (#&amp;lt;&amp;lt;channel&amp;gt; name: guix url: &amp;quot;https://git.savannah.gnu.org/git/guix.git&amp;quot; branch: &amp;quot;master&amp;quot; commit: &amp;quot;5ab3c4c1e43ebb637551223791db0ea3519986e1&amp;quot; introduction: #&amp;lt;&amp;lt;channel-introduction&amp;gt; first-signed-commit: &amp;quot;9edb3f66fd807b096b48283debdcddccfea34bad&amp;quot; first-commit-signer: #vu8(187 176 45 223 44 234 246 168 13 29 230 67 162 160 109 242 163 58 84 250)&amp;gt; location: ((filename . &amp;quot;guix/channels.scm&amp;quot;) (line . 1069) (column . 5))&amp;gt;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;...and I don't know yet whether these can be sent over a captp connection as-is or if I'll need to wrap them somehow. Gotta play around I guess!&lt;/p&gt;&lt;p&gt;One of the other things I haven't decided on yet is which parts of a Guix system exactly this should manage, since Guix lets multiple users have multiple profiles, and since the currently configured channels for a given user don't necessarily reflect the currently installed packages in the user's profile. It might make sense for such a Goblins daemon to take a specific profile as a parameter, and to essentially take ownership of that profile.&lt;/p&gt;&lt;p&gt;I'd also like it to be able to remotely manage the operating-system config and by extension the packages/services installed through it, though I'll need to figure out how exactly to do that. &lt;code&gt;switch-to-system&lt;/code&gt; in &lt;code&gt;(guix scripts system reconfigure)&lt;/code&gt; seems like it might be the right starting point.&lt;/p&gt;&lt;p&gt;My current (very rough) thought on what the management flow would look like is:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;On a centralized management machine, have an object per client machine that represents the desired state of that machine, with a reference to the following daemon&lt;/li&gt;&lt;li&gt;On each client machine, have a daemon running that's managing the operating-system config on that machine, with a reference to the above object&lt;/li&gt;&lt;li&gt;When an admin updates the list of packages/services on the machine object, it sends a message to the client daemon prompting it to run a system rebuild&lt;/li&gt;&lt;li&gt;Periodically, the client daemon reaches out to the machine object to determine if it is up to date (e.g. if it's missed one of the above messages), and to fetch the current desired config if not&lt;/li&gt;&lt;/ul&gt;</content></entry><entry><title>Visual structural editing for Guix (and Schemes in general)</title><id>https://www.terracrypt.net/posts/visual-structural-editing-for-guix-and-schemes-in-general.html</id><author><name>Jonathan Frederickson</name><email>jonathan@terracrypt.net</email></author><updated>2024-09-21T10:38:00Z</updated><link href="https://www.terracrypt.net/posts/visual-structural-editing-for-guix-and-schemes-in-general.html" rel="alternate" /><content type="html">&lt;p&gt;I've been noodling on structural editing for a while now. I'm fully bought into Lisps myself, but most of my friends and coworkers are skeptical, and I think a lot of their skepticism has to do (as usual) with all the parens. One of the points I make frequently is that with Lisp code being written as a nested data structure, the textual representation is just one of many possible representations. But it can be hard to get across what that means without concrete examples.&lt;/p&gt;&lt;p&gt;A few years back, I ran across &lt;a href=&quot;https://github.com/disconcision/fructure&quot;&gt;Fructure&lt;/a&gt; for Racket. To this day, it's still the structural editor with the most appealing visual display to me. But Fructure itself has a few drawbacks for my purposes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It's specifically targeting Racket. Racket is a wonderful Scheme, but I'm a Guix and Goblins user as well, and I would ideally like whichever editor I use to work with any Scheme, not just one.&lt;/li&gt;&lt;li&gt;It was a prototype, and its creator has mostly moved onto other projects.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to these, I've been wanting a way to make Guix configuration as easy and painless as possible for new users. Having a sort of &amp;quot;command palette&amp;quot; available seems like it might be a good way to accomplish this.&lt;/p&gt;&lt;p&gt;So recently, I did a quick initial sketch of what such a system might look like:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;../images/structural-scheme.png&quot; alt=&quot;Pencil mockup of a structural s-expression editor for Schemes, showing a Guix operating-system record. There is an expression palette that can be used to search for expressions and drag them into the structural editor.&quot; /&gt;&lt;/p&gt;&lt;p&gt;I have a few initial use cases in mind:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Guix configuration, as particularly mentioned. Guix data structures (like &lt;code&gt;operating-system&lt;/code&gt;
or &lt;code&gt;file-system&lt;/code&gt;) are written as Guix-specific record types, so there may be some metadata about expected values in each embedded in them that you can tap into somehow.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://dustycloud.org/tmp/interfaces.html&quot;&gt;Content-addressed interfaces&lt;/a&gt; from the Spritely folks. This can make it more clear which methods are available to use on a remote Goblins object, and tying that into a visual command palette seems like it could be very nice.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Obviously given the fact that there are two styles of very different interfaces here, this has to involve some sort of runtime checking. And we probably can't entirely infer which to use based solely on the source code, so there's probably some per-project editor configuration needed for this to work. But... I think this might be doable.&lt;/p&gt;&lt;p&gt;I need to look into this some more, but a good starting point might be the &lt;a href=&quot;https://nrepl.org/nrepl/usage/misc.html&quot;&gt;nREPL protocol&lt;/a&gt;. It seems pretty extensible, and already has support for symbol lookups and such. But need to look into this all some more!&lt;/p&gt;</content></entry></feed>