Each host heading produces a nixosSystem declaration that is shoved in to Arroyo System Flake Generator via ARROYO_OUTPUT metadata. The shared host-modules Lua block resolves role-filtered NixOS modules from the Arroyo DB.
Deploying My Laptops and Desktop
My laptops are installed through my NixOS Automatic Partitioning Installer and carry My NixOS configuration for laptops, the "endpoint configuration".
Virtuous Cassette
Linked from
Virtuous Cassette is my Framework 12 Laptop. It was a Framework 13 for quite some years, but that chassis is my computer for my job now.
nixosConfigurations.virtuous-cassette = mkHost {
name = "virtuous-cassette";
roleModules = [
<<host-modules("endpoint")>>
];
};{ config, pkgs, lib, ... }:
{
imports = [
../../nixos/framework-laptop-12.nix
];
system.stateVersion = "23.11";
sops.age.keyFile = "/home/rrix/.config/sops/age/keys.txt";
networking.hostName = "virtuous-cassette";
boot.loader.grub.efiSupport = true;
boot.loader.grub.device = "nodev";
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub.enable = true;
boot.loader.systemd-boot.enable = false;
boot.initrd.luks.devices = {
"swap" = {
name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true;
};
"root" = {
name = "root"; device = "/dev/nvme0n1p3"; preLVM = true;
};
};
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
powerManagement.cpuFreqGovernor = "powersave";
hardware.enableRedistributableFirmware = true;
services.udev.extraRules = ''
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="18d1|096e", ATTRS{idProduct}=="5026|0858|085b", TAG+="uaccess", GROUP="plugdev"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407", TAG+="uaccess", GROUP="plugdev", MODE="0660"
'';
services.udev.packages = with pkgs; [ platformio-core.udev ];
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
pkgs.udev
pkgs.SDL2
pkgs.libpng
pkgs.libz
];
hardware.sensor.iio.enable = true;
environment.systemPackages = [
pkgs.maliit-framework
pkgs.maliit-keyboard
pkgs.wl-clipboard
];
sops.secrets.tailscale_virtuous_cassette.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_virtuous_cassette.path;
networking.hostId = "291fe33d"; # required for zfs use
fileSystems."/" =
{ device = "host/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "host/home";
fsType = "zfs";
};
fileSystems."/media" =
{ device = "host/landfill";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "host/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/CD54-B840";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/ddfce221-2d29-4882-9c66-1669ea60bc49"; }
];
}Rose Quine
Rose Quine is my GPD Pocket 3. Right now I use it to contain my microvm for langlemangling.
nixosConfigurations.rose-quine = mkHost {
name = "rose-quine";
roleModules = [
<<host-modules("endpoint")>>
];
};{ config, pkgs, lib, ... }:
{
imports = [ ../../nixos/gpd-pocket-3.nix ];
networking.hostName = "rose-quine";
system.stateVersion = "23.05";
services.xserver.dpi = 280;
sops.secrets.tailscale_rose_quine.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_rose_quine.path;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub.efiSupport = true;
boot.loader.grub.device = "nodev";
boot.loader.grub.enable = true;
boot.loader.grub.gfxmodeBios = "1200x1920x32";
boot.loader.systemd-boot.enable = lib.mkForce false;
networking.hostId = "3f5dbbf9"; # required for zfs use
boot.zfs.devNodes = "/dev/mapper"; # (ref:devNodes)
boot.initrd.luks.devices = {
"swap" = {
name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true;
};
"root" = {
name = "root"; device = "/dev/nvme0n1p3"; preLVM = true;
};
};
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "tank/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "tank/home";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "tank/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/9FDC-2C40";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/455bbc40-e01c-4137-b593-a05b6220ce6b"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
}NEXT derivation for umpc-display-rotate.c
NEXT split and document all this out in to an import on GPD Pocket 3 Support page
Window Smoke
: :ARROYO_SYSTEM_ROLE: endpoint : :ARROYO_AGE_RECIPIENT: age1<PLACEHOLDER_WINDOW_SMOKE> : #+ARROYO_OUTPUT: snippets/window-smoke.nix
Window Smoke is my desktop. It runs my Endpoint Configuration and some of My NixOS Tower Customizations. These days I just boot it into steam big picture mode and rdp in over Tailscale.
nixosConfigurations.window-smoke = mkHost {
name = "window-smoke";
roleModules = [
<<host-modules("endpoint")>>
];
};{ lib, config, ... }:
{
imports = [ ./hardware-configuration.nix ../../roles/desktop ];
boot.enableVFIO = false;
networking.hostName = "window-smoke";
system.stateVersion = "22.11";
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.enable = true;
services.xserver.dpi = 110;
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" "wl" ];
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
sops.secrets.tailscale_window_smoke.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_window_smoke.path;
networking.hostId = "141e1b4f"; # required for zfs use
boot.zfs.devNodes = lib.mkForce "/dev/disk/by-id/";
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/nvme0n1p3"; preLVM = true; };
};
fileSystems."/" =
{ device = "window-smoke/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "window-smoke/home";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "window-smoke/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/12CA-451F";
fsType = "vfat";
};
fileSystems."/media" =
{ device = "tank/media";
fsType = "zfs";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/26776a6d-4e53-4e39-b0e5-5a540ce78406"; }
];
}Meadow Crush
: :ARROYO_SYSTEM_ROLE: endpoint : :ARROYO_AGE_RECIPIENT: age1<PLACEHOLDER_MEADOW_CRUSH> : #+ARROYO_OUTPUT: snippets/meadow-crush.nix
Meadow Crush is my GPD Pocket 2; I don't use this right now but it's still running a viable NixOS if I need it in a Situation.
nixosConfigurations.meadow-crush = mkHost {
name = "meadow-crush";
roleModules = [
<<host-modules("endpoint")>>
];
};{ config, ... }:
{
imports = [ ./hardware-configuration.nix ../../nixos/gpd-pocket.nix ];
networking.hostName = "meadow-crush";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
sops.secrets.tailscale_meadow_crush.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_meadow_crush.path;
networking.hostId = "c9ec7cad"; # required for zfs use
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/mmcblk0p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/mmcblk0p3"; preLVM = true; };
};
fileSystems."/mnt/music" =
{ device = "/dev/disk/by-label/muzak";
fsType = "ext4";
noCheck = true;
};
}NEXT implement nixos encrypted secrets and make these safe!
Deploying My NixOS Set Top Box
Tres Ebow
Linked from
: :ARROYO_SYSTEM_ROLE: settop : :ARROYO_AGE_RECIPIENT: age1<PLACEHOLDER_TRES_EBOW> : #+ARROYO_OUTPUT: snippets/tres-ebow.nix
Tres Ebow is my Thinkpad Yoga gen 3 -- a decent 2-in-1 with very un-Lenovo serviceability, and due to ordering error and soldered RAM, only 4 GiB of RAM. awkward. it'll be a fine kodi box.
nixosConfigurations.tres-ebow = mkHost {
name = "tres-ebow";
roleModules = [
<<host-modules("settop")>>
];
};{ config, lib, ... }:
{
networking.hostName = "tres-ebow";
boot.loader.grub.efiSupport = true;
boot.loader.grub.device = "nodev";
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub.enable = true;
boot.loader.systemd-boot.enable = false;
services.xserver.dpi = 207;
networking.hostId = "389acda5"; # required for zfs use
boot.zfs.devNodes = lib.mkForce "/dev/disk/by-uuid"; # (ref:devNodes)
sops.secrets.tailscale_tres_ebow.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_tres_ebow.path;
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "host/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "host/home";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "host/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/CB62-8263";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/4f1751ef-0ddd-4005-b69c-daafc518e9df"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
powerManagement.cpuFreqGovernor = lib.mkDefault "balanced";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.enableRedistributableFirmware = true;
}Deploying The Wobserver
Last Bank
Linked from
Last Bank is my New Homelab Build, a living-room server that will be proxied through Wobscale Technologies in Seattle, WA. It's going to replace terra-firma.
nixosConfigurations.last-bank = mkHost {
name = "last-bank";
homeManager = false;
roleModules = [
<<host-modules("server")>>
];
extraModules = [
./nixos/home-manager-server.nix
];
};{ lib, config, ... }:
let
in {
# imports = [ ../../roles/desktop ];
# boot.enableVFIO = true;
networking.hostName = "last-bank";
system.stateVersion = "23.05";
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_S75BNL0WA24883N";
sops.secrets.tailscale_last_bank.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_last_bank.path;
networking.hostId = "56c334f2"; # required for zfs use
boot.zfs.devNodes = "/dev/disk/by-id"; # (ref:devNodes)
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "isci" "usbhid" "usb_storage" "sd_mod" "igb" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "host/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "host/nix";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "tank/home";
fsType = "zfs";
};
fileSystems."/media" =
{ device = "tank/media";
fsType = "zfs";
};
fileSystems."/srv" =
{ device = "tank/srv";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/19C9-747A";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_S75BNL0WA24883N-part2"; }
];
boot.initrd.network = {
enable = true;
ssh = {
enable = true;
port = 2222;
hostKeys = [ /home/rrix/arroyo-nix/files/last-bank-initrd-host-key ];
authorizedKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt7MT45sX7yML+aUqWUC2RZdxhVpoGz2XLEDes/h0HnvwkV8ZURSBAlkwSAH5Sd2c6nyego0GsvkOUppeqoKtacMz6JK5iut3hMWiR6NcSZfG7r8NR5/WrPpWwGtU7cRkkxVKM1PwtYk0crQTCVg5G9+9quKtGkEQ33ile5XSr2VVO44hWafZlSLPFPXTLvxgm7MN9E28k7hVeDBIYppM6VnWz5xsbhboKJMSHU8SFPQKw2GqaugDqokeS0SbyCj7poj1uyijQx3hw0RTpzy1XrmCFu4HmT7qgpESi+1aMObItezKyHy6zBh58DF3Hu/T3tqFglR6XbyfsR3IHyTVz rrix" ];
};
# postCommands = ''
# zpool import -a
# echo "zfs load-key -a; killall zfs" >> /root/.profile
# '';
};
# greetz https://elis.nu/blog/2026/04/nixos-zfs-remote-unlock-over-ssh/
boot.initrd.systemd.services.zfs-setup-root-profile = {
description = "Prepare root .profile for ZFS unlocking via SSH";
wantedBy = [ "initrd.target" ];
before = [ "initrd-root-fs.target" ];
unitConfig.DefaultDependencies = false;
script = ''
mkdir -p /var/empty
echo "systemd-tty-ask-password-agent --watch" > /var/empty/.profile
'';
serviceConfig.Type = "oneshot";
};
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}Deploying the Edge Server
King Mountain
The Wobserver's Edge Server in seattle
King Mountain is The Wobserver's Edge Server, a small VM hosted by Wobscale Technologies in Seattle, WA so that my Wobserver doesn't need a public IP.
nixosConfigurations.king-mountain = mkHost {
name = "king-mountain";
roleModules = [
<<host-modules("edge")>>
];
};{ lib, config, modulesPath, ... }:
{
imports = [
"${toString modulesPath}/profiles/qemu-guest.nix"
];
networking.hostName = "king-mountain";
system.stateVersion = "24.11";
sops.secrets.tailscale_king_mountain.owner = "root";
services.tailscale.authKeyFile = config.sops.secrets.tailscale_king_mountain.path;
networking.hostId = "66c334a2"; # required for zfs use
boot.zfs.devNodes = "/dev/disk/by-uuid"; # (ref:devNodes)
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
autoResize = true;
fsType = "ext4";
};
boot.growPartition = true;
boot.kernelParams = ["console=ttyS0"];
boot.loader.grub.device = "/dev/sda";
boot.loader.timeout = 3;
boot.initrd.availableKernelModules = [ "ehci_pci" "ahci" "isci" "usbhid" "usb_storage" "sd_mod" ] ++ [
"virtio_net"
"virtio_pci"
"virtio_mmio"
"virtio_blk"
"virtio_scsi"
"9p"
"9pnet_virtio"
];
boot.initrd.kernelModules = [
"virtio_balloon"
"virtio_console"
"virtio_rng"
"virtio_gpu"
];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}Shared Generator
host-modules(role) queries the DB for ARROYO_NIXOS_MODULE entries filtered by role and returns ./modulePath lines.
local modules = arroyo.nixos_role_modules(role)
local lines = {}
for _, m in ipairs(modules) do
table.insert(lines, "./" .. m.module_path)
end
return table.concat(lines, "\n ")