The Complete Computing Environment

Arroyo NixOS Generator


Arroyo can manage any number of NixOS hosts, though right now it seeks to only manage systems which are "endpoints" – a place the user may want to deploy their Arroyo configuration to.

Server and cluster management will be explored at some point in the future, but for now this is designed to build laptops and desktops which can be given a bare-bones NixOS install through my NixOS Automatic Partitioning Installer and attached to the same network as a machine running Arroyo or capable of running Morph on a set of Arroyo tangled files.

NixOS configuration.nix Generator

This thing is pretty functionally similar to the Arroyo Home Manager generator and is conceptually quite similar. It constructs a NixOS configuration.nix-like which is suitable for being deployed with Morph. That file documents My Laptops and provides an example of the system "in-flight."

(defcustom arroyo-nixos-network-path (expand-file-name "~/arroyo-nix/networks/laptops.nix" org-roam-directory)
  "Location of Nix network definition suitable for Morphing"
  :group 'arroyo
  :type 'string)

(dolist (mod '("ARROYO_NIXOS_MODULE"
  (add-to-list 'arroyo-db-keywords mod nil #'equal))

(add-to-list 'arroyo-db--schemata
               [(file        :not-null)
                (nix-module :not-null)
(defun arroyo-nixos-update-db (&optional keywords-too)
  (interactive "P")
  (when keywords-too
  (if (org-roam-file-p)
      (arroyo-db-query [:delete :from nixos :where (= file $s1)]
    (arroyo-db-query [:delete :from nixos]))
  (when-let* ((args
               (if (org-roam-file-p)
                   (list [:select [file value] :from keywords
                          :where (= keyword $s1) :and (= file $s2)]
                 (list [:select [file value] :from keywords
                        :where (= keyword $s1)]
              (results (apply #'arroyo-db-query args))
              (results (-map (pcase-lambda (`(,file ,value))
                               (list file value (arroyo-db-get "ARROYO_NIXOS_ROLE" file)))
    (arroyo-db-query [:insert :into nixos :values $v1]
                     (-map (lambda (result) (apply #'vector result))

(add-to-list 'arroyo-db-update-functions #'arroyo-nixos-update-db)

arroyo-home-manager-imports returns a list of strings suitable for import'ing in home-manager's literate helpers.

(defun arroyo-nixos-imports (&optional role)
  (if-let* ((imports (arroyo-nixos-imports1))
            (no-role? (not role)))
      (-map #'car imports)
      (let* ((all-files (-map #'cadr imports))
             (role-only-files (arroyo-db-by-keyword "ARROYO_NIXOS_ROLE" role))
             (exclude-these-files (arroyo-db-by-keyword "ARROYO_NIXOS_EXCLUDE" role))
             ;; also need to exclude things whose ARROYO_NIXOS_ROLE is not `role'!
              (-map #'car
                    (arroyo-db-query [:select file :from nixos
                                      :where (!= role $s1)]
                                     (list role))))
             ;; combine all those lists in to a single authoritative list.
              (-union role-only-files
                      (->> all-files
                           (--remove (-contains? exclude-these-files it))
                           (--remove (-contains? not-my-role-files it)))))
             ;; make them relative to org-roam-directory for the module orderer
             (rel-files (--map (file-relative-name it org-roam-directory) amalgamated-files))
             ;; map the org path back to the tangled module
             (tangled-files (-map (lambda (org-file)
                                    (car (arroyo-db-get "ARROYO_NIXOS_MODULE"
                                                    (expand-file-name org-file org-roam-directory))))
                                  (arroyo-utils-order-modules rel-files))))
        (-filter #'identity tangled-files)))))

(defun arroyo-nixos-imports1 ()
  (->> [:select [nix-module file] :from nixos]

NEXT I should make this function which crates the tangled-files list a function in Arroyo System Cache

It's a very useful thing to say "just go figure out the DAG stuff for the files that are set up by -these- metadata keywords" – i already have a copy of this in Arroyo Home Manager that could be combined in to a better pattern, surely.

I need to generally be thinking about an "API" for arroyo, something that other folks could extend, rather than just accreting features forever.

Arroyo NixOS manages systems with Morph:

It goes in to Arroyo Home Manager but can be installed from GitHub to bootstrap the system.

{ pkgs, ... }:
  home.packages = [ pkgs.morph ];

Flooding the Arroyo tangles and deploys all sub-systems

an interactive command which stitches together the arroyo system and runs the morph command which deploys the system:

Click here to flood the Arroyo.

(defun arroyo-nixos-full-spread (&optional local-only dep-file switch-action)
  "Flood the arroyo. Tangle all related files and run morph deploy.
DEP-FILE is a string pointing to a Morph network definition.
SWITCH-ACTION is one of the actions which morph deploy expects. Read its docs."
  (interactive "P")
  (let ((switch-action (or switch-action "switch"))
        (dep-file (or dep-file arroyo-nixos-network-path)))
    ;; expand this to include CCE_NIXOS keywords eventually
    (org-babel-tangle-file (expand-file-name "cce/" org-roam-directory))
    (org-babel-tangle-file (expand-file-name "arroyo/" org-roam-directory))
    ;(arroyo-feeds-flood local-only)
    (async-shell-command (if local-only
                             (format "morph deploy --passwd %s %s --on=\"%s\"" dep-file switch-action (system-name))
                           (format "morph deploy --passwd %s %s" dep-file switch-action))

(defalias 'arroyo-flood 'arroyo-nixos-full-spread)
(provide 'arroyo-nixos)