From 2e6bef9ad2a7c2a60a8ceb25c3a60bdf7bd52c31 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 01:46:09 +1000 Subject: [PATCH 01/37] add importOverlays --- cerulean/nexus/nexus.nix | 74 +++++++++++++++------------------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 8b65fdd..12ad933 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -54,8 +54,11 @@ Ensure `nexus.${path}` exists under your call to `cerulean.mkNexus`. ''); in { - groups = Terminal {}; overlays = []; + extraModules = []; + specialArgs = Terminal {}; + + groups = Terminal {}; nodes = Terminal {}; }; @@ -121,10 +124,19 @@ in final; + importOverlays = root: let + path = findImport (root + "/overlay"); + in + if pathExists path + then import path + else []; + # XXX: TODO: create a function in NixTypes that handles this instead findImport = path: if pathExists path then path + else if pathExists (path + "default.nix") + then path + "/default.nix" else path + ".nix"; in { mkNexus = root: outputsBuilder: let @@ -143,29 +155,6 @@ in { system = node.system; modules = let host = findImport (root + "/hosts/${nodeName}"); - # XXX: TODO: don't use a naive type for this (ie _name property) - # XXX: TODO: i really need NixTypes to be stable and use that instead - # groups = - # node.groups - # |> map (group: - # assert group ? _name - # || throw (let - # got = - # if ! isAttrs group - # then toString group - # else - # group - # |> attrNames - # |> map (name: "${name} = <${typeOf (getAttr name group)}>;") - # |> concatStringsSep " " - # |> (x: "{ ${x} }"); - # in '' - # Cerulean Nexus node "${nodeName}" is a member of a nonexistent group. - # Got "${got}" of primitive type "${typeOf group}". - # NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP` - # ''); - # findImport (root + "/groups/${group._name}")) - # |> nt.prim.unique; # filter by uniqueness groups = assert isList node.groups || throw '' Cerulean Nexus node "${nodeName}" does not declare group membership as a list, got "${typeOf node.groups}" instead! @@ -194,26 +183,10 @@ in { '') # add all inherited groups via _parent |> map (let - delegate = g: let - got = - if ! isAttrs g - then toString g - else - g - |> attrNames - |> map (name: "${name} = <${typeOf (getAttr name g)}>;") - |> concatStringsSep " " - |> (x: "{ ${x} }"); - in - assert g ? _parent - || throw '' - Cerulean Nexus node "${nodeName}" is a member of an incorrectly structured group. - Got "${got}" of primitive type "${typeOf g}". - NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP` - ''; - if g._parent == null - then [g] - else [g] ++ delegate (g._parent); + delegate = g: + if g._parent == null + then [g] + else [g] ++ delegate (g._parent); in delegate) # flatten recursion result @@ -225,7 +198,9 @@ in { # ignore missing groups |> filter pathExists; in - [../nixos-module host] ++ groups ++ node.extraModules; + [../nixos-module host] + ++ groups + ++ node.extraModules; # nix passes these to every single module specialArgs = let @@ -234,8 +209,13 @@ in { inherit (node) system; # XXX: WARNING: TODO: i've stopped caring # XXX: WARNING: TODO: just figure out a better solution to pkgConfig - config.allowUnfree = true; - overlays = self.overlays ++ nexus.overlays ++ node.overlays; + config.allowUnfree = false; + config.allowBroken = false; + overlays = + self.overlays + ++ nexus.overlays + ++ node.overlays + ++ importOverlays root; } // node.extraPkgConfig; in From 22d02d49f06cf99f66e5e981c396dc740603c809 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 01:46:16 +1000 Subject: [PATCH 02/37] remove old lib --- lib/cdesktop.nix | 149 --------------------- lib/csystem.nix | 330 ----------------------------------------------- lib/cuser.nix | 102 --------------- 3 files changed, 581 deletions(-) delete mode 100644 lib/cdesktop.nix delete mode 100644 lib/csystem.nix delete mode 100644 lib/cuser.nix diff --git a/lib/cdesktop.nix b/lib/cdesktop.nix deleted file mode 100644 index ef2b205..0000000 --- a/lib/cdesktop.nix +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2025 Emile Clark-Boman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{ - lib, - config, - pkgs, - pkgs-unstable, - ... -} @ args: let - getModule = name: "../modules/homemanager/${name}.nix"; - getModules = map (x: getModule x); -in { - imports = getModules [ - "term/foot" - "editor/vscode" - - "wm/hyprland" - "wm/hyprland/hyprlock" - - "dm/sddm" - "dm/sddm/themes/corners" - - "apps/firefox" - "apps/thunderbird" - "apps/obsidian" - "apps/rider" - "apps/winbox" - "apps/gitkraken" - "apps/thunar" - - "wm/kanshi" - "wm/mako" - ]; - - home = { - pointerCursor = { - gtk.enable = true; - # x11.enable = true # dont enable since im on hyprland - package = pkgs.bibata-cursors; - name = "Bibata-Modern-Ice"; - size = 16; - }; - - packages = with pkgs; [ - # for services.gnome-keyring - ( - if config.cerulean.isGraphical - then seahorse # gui - else null - ) - - fuzzel - ]; - }; - - gtk = { - enable = true; - font.name = "Victor Mono SemiBold 12"; - theme = { - name = "Dracula"; - package = pkgs.dracula-theme; - }; - iconTheme = { - name = "kora"; - package = pkgs.kora-icon-theme; - }; - # TODO: use a variable to mirror this cursor size - # with the `home.pointerCurser.size` - cursorTheme = { - package = pkgs.bibata-cursors; - name = "Bibata-Modern-Ice"; - size = 16; - }; - }; - - qt = { - enable = true; - platformTheme.name = "gtk2"; - style.name = "gtk2"; - }; - - services = { - # Set display manager (login screen) - displayManager = { - # sddm relies on pkgs.libsForQt5.qt5.qtgraphicaleffects - sddm = { - enable = true; - wayland.enable = true; # experimental - theme = "corners"; - }; - defaultSession = - "hyprland" - + ( - if config.programs.hyprland.withUWSM - then "-uwsm" - else null - ); - }; - - # Multimedia Framework - # With backwards compatability for alsa/pulseaudio/jack - pipewire = { - enable = true; - wireplumber.enable = true; - - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - jack.enable = true; - }; - }; - - # ---- ENVIRONMENT ---- - environment = { - sessionVariables = { - # Hint Electron apps to use support Wayland - NIXOS_OZONE_WL = "1"; - }; - }; - - # ---- SYSTEM PACKAGES ---- - environment.systemPackages = with pkgs; [ - # User Environment - swww - helvum - easyeffects - pavucontrol - hyprpicker # colour picking utility - hyprshot # screenshot utility - qbittorrent - signal-desktop # MAKE THIS ONLY FOR THE DESKTOP FOR END USERS, NOT SERVERS - kdePackages.gwenview # image viewer - libreoffice - wl-clipboard # clipboard for wayland - ]; - - security.rtkit.enable = true; # I *think* this is for pipewire -} diff --git a/lib/csystem.nix b/lib/csystem.nix deleted file mode 100644 index 64e3aa3..0000000 --- a/lib/csystem.nix +++ /dev/null @@ -1,330 +0,0 @@ -# Copyright 2025 Emile Clark-Boman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{ - inputs, - lib, - config, - pkgs, - pkgs-unstable, - homemanager, - cerulean, - ... -} @ args: let - getModule = name: "../modules/nixos/${name}.nix"; - getModules = map (x: getModule x); - - getHostModule = name: "TODO"; -in { - imports = getModules [ - (getHostModule "hardware-configuration") - (import "${homemanager}/nixos") - - "shell/bash" - "shell/bash/bashistrans.nix" - "shell/zsh" - "shell/fish" - - "cli/git" - "cli/bat" - "cli/btop" - "cli/tmux" - "cli/nvim" - - "lang/asm" - "lang/bash" # TODO: (YES THIS IS DIFFERENT TO shell/bash, this provides language support ie pkgs.shellcheck) - "lang/c-family" - "lang/dotnet" - # "lang/go" - # "lang/haskell" - # "lang/java" - # "lang/nim" - "lang/python" - # "lang/rust" - # "lang/sage" - - "editor/helix" - ]; - - nix.settings = { - # REF: https://nix.dev/manual/nix/2.24/development/experimental-features - experimental-features = [ - # Significant - "flakes" - "nix-command" - "pipe-operators" - - # Minor - "no-url-literals" - "parse-toml-timestamps" - "recursive-nix" - ]; - - download-buffer-size = 524288000; # 500 MiB - - # making wheel group members "trusted users" allows - # them to import packages not signed by a trusted key - # (aka super duper easier to remote deploy) - trusted-users = ["root" "@wheel"]; - }; - - nixpkgs = { - overlays = cerulean.lib.importOverlaysNixOS; - - config = if config.cerulean.allowUnfreeWhitelist != [] - then { - allowUnfreePredicate = - pkg: builtins.elem - (lib.getName pkg) - config.cerulean.allowUnfreeWhitelist; - } - else { - allowUnfree = config.cerulean.allowUnfree; - }; - }; - - # colmena deployment configuration - deployment = { - targetHost = config.cerulean.domain ?? config.cerulean.ip; - targetUser = "cerulean"; - targetPort = "22"; - sshOptions = [ - "-A" # forward ssh-agent - ]; - buildOnTarget = false; # build locally then deploy - }; - - - time.timeZone = config.cerulean.timeZone; - i18n.defaultLocale = "en_US.UTF-8"; - - # Enable initrd hook for virtual console customisation - # aka cool colours when booting yay!! - console = { - enable = true; - earlySetup = true; # initrd pre hook - keyMap = "us"; - font = "Lat2-Terminus16"; - # ANSI 24-bit color definitions (theme: dracula) - colors = [ - "21222c" - "ff5555" - "50fa7b" - "f1fa8c" - "bd93f9" - "ff79c6" - "8be9fd" - "f8f8f2" - "6272a4" - "ff6e6e" - "69ff94" - "ffffa5" - "d6acff" - "ff92df" - "a4ffff" - "ffffff" - ]; - }; - - # super duper minimum grub2 config - boot.loader = { - efi = { - canTouchEfiVariables = true; - efiSysMountPoint = "/boot/efi"; - }; - - grub = { - enable = true; - device = "nodev"; - }; - - # GitHub: vinceliuice/grub2-themes - grub2-theme = { - enable = true; - theme = "whitesur"; # stylish, vimix, or whitesur - footer = true; - # TODO: switch my cables to switch default grub display - customResolution = "3840x2160"; - }; - }; - - networking = { - hostName = config.cerulean.hostname; - networkmanager.enable = true; - - firewall = { - enable = true; - allowedTCPPorts = [ - 22 # sshd - 80 # nginx (http) - 443 # nginx (https) - # 5678 # MikroTik WinBox - ]; - }; - }; - - # ------- USERS ------- - security.sudo.wheelNeedsPassword = true; - users = { - defaultUserShell = pkgs.bash; - - users = cerulean.lib.importUsersNixOS; - }; - - home-manager = { - users = cerulean.lib.importUsersHomeManager; - - extraSpecialArgs = { inherit inputs pkgs pkgs-unstable; }; - sharedModules = []; - }; - - # ---- ENVIRONMENT ---- - environment = { - # always install "dev"/"man" derivation outputs - extraOutputsToInstall = ["dev" "man"]; - - systemPackages = with pkgs; [ - # User Environment - bluetui - - # Shell - bash - fish - shellcheck - grc # colorise command outputs - moreutils - - # Systems Programming & Compilation - qemu # Fellice Bellard's Quick Emulator - # GNU Utils - gnumake - # Binaries - binutils - strace - ltrace - perf-tools # ftrace + perf - radare2 - gdb - # ASM - nasm - (callPackage ../packages/x86-manpages {}) - # C Family - gcc - clang - clang-tools - - # Rust - cargo - rustc - # Go - go - # Nim - nim - nimble - # Haskell - ghc - ghcid - haskell-language-server - ormolu - - # Python - python312 # I use 3.12 since it's in a pretty stable state now - python314 # also 3.14 for latest features - poetry - - openvpn - inetutils - - # security tools - nmap - - httpie - curlie - zoxide - doggo - tldr - btop - eza - yazi - lazygit - ripgrep - viddy # modern `watch` command - thefuck - - # TODO: once upgraded past Nix-24.07 this line won't be necessary (I think) - # helix will support nixd by default - # SOURCE: https://github.com/nix-community/nixd/blob/main/nixd/docs/editor-setup.md#Helix - # nixd # lsp for nix # DEBUG - - # Pretty necessary - nix-prefetch-git - brightnessctl - acpi - powertop - imagemagick - - # "Standard" Unix Commands - vim - file - wget - tree - pstree - unzip - unrar-free - lz4 - man-pages - man-pages-posix - - # Cryptography - gnupg - openssl - libargon2 - ]; - }; - - programs = { - nix-ld.enable = true; - }; - - documentation = { - enable = true; - doc.enable = true; # install /share/doc packages - man.enable = true; # install manpages - info.enable = true; # install GNU info - dev.enable = true; # install docs intended for developers - nixos = { - enable = true; # install NixOS documentation (ie man -k nix, & nixos-help) - options.splitBuild = true; - # includeAllModules = true; - }; - }; - - virtualisation.docker.enable = true; - - - hardware = { - graphics = { - enable = true; - enable32Bit = true; - }; - - bluetooth = let - btSupported = config.cerulean.bluetoothSupported; - in { - enable = btSupported; - powerOnBoot = btSupported; - }; - }; - - system.stateVersion = config.cerulean.stateVersion; # DO NOT MODIFY -} diff --git a/lib/cuser.nix b/lib/cuser.nix deleted file mode 100644 index f602e03..0000000 --- a/lib/cuser.nix +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2025 Emile Clark-Boman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{ - lib, - config, - pkgs, - pkgs-unstable, - ... -} @ args: let - getModule = name: "../modules/homemanager/${name}.nix"; - getModules = map (x: getModule x); -in { - imports = getModules [ - "shell/fish" - - "cli/git" - "cli/bat" - "cli/btop" - "cli/tmux" - - "editor/helix" - ]; - - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.GetName pkg) [ - "vscode-extension-ms-dotnettools-csharp" - ]; - - home = { - stateVersion = config.cerulean.stateVersion; # DO NOT MODIFY - - username = config.cerulean.username; - homeDirectory = "/home/${config.cerulean.username}"; - - shellAliases = { - rg = "batgrep"; # bat + ripgrep - man = "batman"; # bat + man - }; - - sessionVariables = { - NIX_SHELL_PRESERVE_PROMPT = 1; - }; - - packages = with pkgs; [ - # for services.gnome-keyring - gcr # provides org.gnome.keyring.SystemPrompter - speedtest-cli - ]; - }; - - programs = { - home-manager.enable = true; - - zsh = { - enable = true; - enableCompletion = true; - autosuggestion.enable = true; - syntaxHighlighting.enable = true; - - history = { - size = 10000; - ignoreAllDups = true; - path = "$HOME/.zsh_history"; - ignorePatterns = [ - "rm *" - ]; - }; - }; - - # set ssh profiles - # NOTE: (IMPORTANT) this DOES NOT start the ssh-agent - # for that you need to use `services.ssh-agent.enable` - ssh = { - enable = true; - forwardAgent = false; - addKeysToAgent = "no"; - }; - }; - - services = { - # enable OpenSSH private key agent - ssh-agent.enable = true; - - gnome-keyring.enable = true; - }; - - # the ssh-agent won't set this for itself... - systemd.user.sessionVariables.SSH_AUTH_SOCK = "$XDG_RUNTIME_DIR/ssh-agent"; - # Nicely reload system units when changing configs - systemd.user.startServices = "sd-switch"; -} From c07ac05a0d50f05eb57221b4f8173a16404e33ae Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 01:46:25 +1000 Subject: [PATCH 03/37] progress flake.lock --- flake.lock | 146 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 23 deletions(-) diff --git a/flake.lock b/flake.lock index e9a0074..e0b0735 100644 --- a/flake.lock +++ b/flake.lock @@ -36,43 +36,71 @@ "type": "github" } }, - "mix": { + "flake-parts": { "inputs": { - "nib": [ - "nib" + "nixpkgs-lib": [ + "nt", + "nix-unit", + "nixpkgs" ] }, "locked": { - "lastModified": 1768525804, - "narHash": "sha256-jlpNb7Utqfdq2HESAB1mtddWHOsxKlTjPiLFRLd35r8=", - "owner": "emilelcb", - "repo": "mix", - "rev": "617d8915a6518a3d4e375b87c50ae34d9daee6c6", + "lastModified": 1762440070, + "narHash": "sha256-xxdepIcb39UJ94+YydGP221rjnpkDZUlykKuF54PsqI=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "26d05891e14c88eb4a5d5bee659c0db5afb609d8", "type": "github" }, "original": { - "owner": "emilelcb", - "repo": "mix", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "nib": { + "nix-github-actions": { "inputs": { - "systems": [ - "systems" + "nixpkgs": [ + "nt", + "nix-unit", + "nixpkgs" ] }, "locked": { - "lastModified": 1768472076, - "narHash": "sha256-bdVRCDy6oJx/CZiyxkke783FgtBW//wDuOAITUsQcNc=", - "owner": "emilelcb", - "repo": "nib", - "rev": "42ac66dfc180a13af1cc8850397db66ec5556991", + "lastModified": 1737420293, + "narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9", "type": "github" }, "original": { - "owner": "emilelcb", - "repo": "nib", + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-unit": { + "inputs": { + "flake-parts": "flake-parts", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "nt", + "nixpkgs" + ], + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1762774186, + "narHash": "sha256-hRADkHjNt41+JUHw2EiSkMaL4owL83g5ZppjYUdF/Dc=", + "owner": "nix-community", + "repo": "nix-unit", + "rev": "1c9ab50554eed0b768f9e5b6f646d63c9673f0f7", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-unit", "type": "github" } }, @@ -124,14 +152,49 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1767313136, + "narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ac62194c3917d5f474c1a844b6fd6da2db95077d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nt": { + "inputs": { + "nix-unit": "nix-unit", + "nixpkgs": "nixpkgs_3", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1770911021, + "narHash": "sha256-8FcXBu0CjeeZeq3uW2h/c5AV+hqELuyPiHsUogOSmZM=", + "owner": "emilelcb", + "repo": "nt", + "rev": "471e1617e8cc0bc749712a7a6af2b2e9f988ffbf", + "type": "github" + }, + "original": { + "owner": "emilelcb", + "repo": "nt", + "type": "github" + } + }, "root": { "inputs": { "deploy-rs": "deploy-rs", - "mix": "mix", - "nib": "nib", "nixpkgs": "nixpkgs_2", "nixpkgs-unstable": "nixpkgs-unstable", - "systems": "systems_2" + "nt": "nt", + "systems": "systems_3" } }, "systems": { @@ -164,6 +227,43 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nt", + "nix-unit", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762410071, + "narHash": "sha256-aF5fvoZeoXNPxT0bejFUBXeUjXfHLSL7g+mjR/p5TEg=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "97a30861b13c3731a84e09405414398fbf3e109f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "utils": { "inputs": { "systems": "systems" From b151f45dfbdb0849d3c24940af946f11652dd8bf Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 02:35:35 +1000 Subject: [PATCH 04/37] duplicate node opts to nexus --- cerulean/nexus/nexus.nix | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 12ad933..116b8ce 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -57,6 +57,8 @@ overlays = []; extraModules = []; specialArgs = Terminal {}; + # XXX: WARNING: extraPkgConfig is a terrible solution (but im lazy for now) + extraPkgConfig = Terminal {}; groups = Terminal {}; nodes = Terminal {}; @@ -200,7 +202,8 @@ in { in [../nixos-module host] ++ groups - ++ node.extraModules; + ++ node.extraModules + ++ nexus.extraModules; # nix passes these to every single module specialArgs = let @@ -217,9 +220,11 @@ in { ++ node.overlays ++ importOverlays root; } - // node.extraPkgConfig; + // nexus.extraPkgConfig # TODO: import + // node.extraPkgConfig; # TODO: import in - node.specialArgs + nexus.specialArgs + // node.specialArgs // { inherit root; pkgs = import nixpkgs pkgConfig; From 66c10fdb59fcc0778a9d2e35c2ec0698b51c245b Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 02:53:03 +1000 Subject: [PATCH 05/37] should i rewrite nixpkgs.lib.nixosSystem? --- cerulean/nexus/nexus.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 116b8ce..edc9361 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -207,6 +207,8 @@ in { # nix passes these to every single module specialArgs = let + # XXX: NOTE: REF: https://github.com/NixOS/nixpkgs/blob/master/flake.nix#L57 + # XXX: NOTE: lib.nixosSystem is defined here ^^^^ pkgConfig = { inherit (node) system; From 54512e63996e6d73b716094952fede5b36a835c6 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 03:27:21 +1000 Subject: [PATCH 06/37] add TODO.md --- cerulean/TODO.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 cerulean/TODO.md diff --git a/cerulean/TODO.md b/cerulean/TODO.md new file mode 100644 index 0000000..2a08659 --- /dev/null +++ b/cerulean/TODO.md @@ -0,0 +1,2 @@ +- [ ] extend the options.nixpkgs to allow any number of package repositories!! +- [ ] auto-propagate the same specialArgs for hosts to home-manager From 71ffa820a9035c5996503912412797b66aedf2dd Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 03:28:03 +1000 Subject: [PATCH 07/37] install deploy-rs also begin adding support for multiple pkgs repos --- cerulean/nixos-module/config.nix | 14 --------- cerulean/nixos-module/default.nix | 10 +++++-- cerulean/nixos-module/nixpkgs.nix | 48 +++++++++++++++++++++++++++++++ cerulean/nixos-module/options.nix | 20 ------------- 4 files changed, 55 insertions(+), 37 deletions(-) delete mode 100644 cerulean/nixos-module/config.nix create mode 100644 cerulean/nixos-module/nixpkgs.nix delete mode 100644 cerulean/nixos-module/options.nix diff --git a/cerulean/nixos-module/config.nix b/cerulean/nixos-module/config.nix deleted file mode 100644 index 26d459c..0000000 --- a/cerulean/nixos-module/config.nix +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2026 Emile Clark-Boman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{...}: {} diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index cc92212..e7561ee 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -11,8 +11,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -{...} @ inputs: { - options = import ./options.nix inputs; +{deploy-rs, ...}: { + imports = [ + # ./nixpkgs.nix + ]; - config = import ./config.nix inputs; + environment.systemPackages = [ + deploy-rs.packages.default + ]; } diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix new file mode 100644 index 0000000..f4bb2ae --- /dev/null +++ b/cerulean/nixos-module/nixpkgs.nix @@ -0,0 +1,48 @@ +# Copyright 2026 Emile Clark-Boman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +{ + lib, + config, + ... +}: let + cfg = config.pkgrepo; +in { + options.pkgrepo = lib.mkOption { + type = lib.types.attrsOf lib.types.attrs; + default = {}; + description = "Declare and import custom package repositories."; + example = { + "pkgs" = { + source = "inputs.nixpkgs"; + system = "x86-64-linux"; + config = { + allowUnfree = true; + allowBroken = false; + }; + }; + }; + }; + + config.nixpkgs = + lib.mkIf (cfg ? pkgs) + (let + pkgs = cfg.pkgs; + in + lib.mkForce ( + (builtins.removeAttrs pkgs ["source"]) + // { + flake.source = pkgs.source; + } + )); +} diff --git a/cerulean/nixos-module/options.nix b/cerulean/nixos-module/options.nix deleted file mode 100644 index 8fb6a46..0000000 --- a/cerulean/nixos-module/options.nix +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2026 Emile Clark-Boman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{lib, ...}: { - cerulean.nexus.node = { - group = lib.mkOption { - type = lib.types.enum; - }; - }; -} From 4bce8ee7b2c724b746417610f772a9cfe1eab4fb Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 03:55:47 +1000 Subject: [PATCH 08/37] auto-propagate home-manager options --- cerulean/nixos-module/default.nix | 3 ++- cerulean/nixos-module/home-manager.nix | 29 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 cerulean/nixos-module/home-manager.nix diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index e7561ee..3bf3a9c 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -13,7 +13,8 @@ # limitations under the License. {deploy-rs, ...}: { imports = [ - # ./nixpkgs.nix + ./nixpkgs.nix + ./home-manager.nix ]; environment.systemPackages = [ diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos-module/home-manager.nix new file mode 100644 index 0000000..6833e1d --- /dev/null +++ b/cerulean/nixos-module/home-manager.nix @@ -0,0 +1,29 @@ +# Copyright 2026 Emile Clark-Boman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +{ + root, + config, + lib, + ... +} @ args: { + home-manager = { + users = + config.users.users + |> builtins.attrNames + |> builtins.filter (x: builtins.pathExists (root + "/homes/${x}")) + |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); + + extraSpecialArgs = args; + }; +} From 135f2fb996aea4bb1bb287383e58c438fedfe23d Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 12:08:02 +1000 Subject: [PATCH 09/37] update TODO + upstream --- TODO.md | 3 +++ cerulean/TODO.md | 2 -- flake.nix | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 cerulean/TODO.md diff --git a/TODO.md b/TODO.md index c43e8c6..25f6f1b 100755 --- a/TODO.md +++ b/TODO.md @@ -3,3 +3,6 @@ also rename `Cerulean` to `cerulean` in Nix to maintain the naming convention. Using `flake-parts` ensures Cerulean is usable without restricting yourself only to the Cerulean ecosystem. + +- [ ] extend the options.nixpkgs to allow any number of package repositories!! +- [x] auto-propagate the same specialArgs for hosts to home-manager diff --git a/cerulean/TODO.md b/cerulean/TODO.md deleted file mode 100644 index 2a08659..0000000 --- a/cerulean/TODO.md +++ /dev/null @@ -1,2 +0,0 @@ -- [ ] extend the options.nixpkgs to allow any number of package repositories!! -- [ ] auto-propagate the same specialArgs for hosts to home-manager diff --git a/flake.nix b/flake.nix index 94f4b33..ff430bc 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,7 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; - nt.url = "github:emilelcb/nt"; + nt.url = "github:cry128/nt"; deploy-rs.url = "github:serokell/deploy-rs"; }; From 7591af6e3a56fbc650f4dd7db10f8a747cbb022f Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 12:38:53 +1000 Subject: [PATCH 10/37] add support for multiple pkg channels --- cerulean/nexus/nexus.nix | 161 ++++++++++++------------------ cerulean/nexus/nodes.nix | 2 - cerulean/nixos-module/default.nix | 2 +- cerulean/nixos-module/nixpkgs.nix | 61 ++++++++--- 4 files changed, 111 insertions(+), 115 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index edc9361..4c757ba 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -12,10 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. { - self, this, - nixpkgs, - nixpkgs-unstable, nt, lib, deploy-rs, @@ -42,6 +39,11 @@ mapNodes ; + inherit + (nt) + findImport + ; + templateNexus = let inherit (nt.naive.terminal) @@ -54,11 +56,8 @@ Ensure `nexus.${path}` exists under your call to `cerulean.mkNexus`. ''); in { - overlays = []; extraModules = []; specialArgs = Terminal {}; - # XXX: WARNING: extraPkgConfig is a terrible solution (but im lazy for now) - extraPkgConfig = Terminal {}; groups = Terminal {}; nodes = Terminal {}; @@ -71,7 +70,8 @@ isAttrs g || throw '' Cerulean Nexus groups must be provided as attribute sets, got "${typeOf g}" instead! - Ensure all the `groups` definitions are attribute sets under your call to `cerulean.mkNexus`. + Ensure all the group definitions are attribute sets under your call to `cerulean.mkNexus`. + NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP` ''; delegate = parent: gName: g: let result = @@ -126,20 +126,49 @@ in final; - importOverlays = root: let - path = findImport (root + "/overlay"); - in - if pathExists path - then import path - else []; - - # XXX: TODO: create a function in NixTypes that handles this instead - findImport = path: - if pathExists path - then path - else if pathExists (path + "default.nix") - then path + "/default.nix" - else path + ".nix"; + getGroupModules = root: nodeName: node: + assert isList node.groups + || throw '' + Cerulean Nexus node "${nodeName}" does not declare group membership as a list, got "${typeOf node.groups}" instead! + Ensure `nexus.nodes.${nodeName}.groups` is a list under your call to `cerulean.mkNexus`. + ''; + node.groups + # ensure all members are actually groups + |> map (group: let + got = + if ! isAttrs group + then toString group + else + group + |> attrNames + |> map (name: "${name} = <${typeOf (getAttr name group)}>;") + |> concatStringsSep " " + |> (x: "{ ${x} }"); + in + if group ? _name + then group + else + throw '' + Cerulean Nexus node "${nodeName}" is a member of an incorrectly structured group. + Got "${got}" of primitive type "${typeOf group}". + NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP` + '') + # add all inherited groups via _parent + |> map (let + delegate = g: + if g._parent == null + then [g] + else [g] ++ delegate (g._parent); + in + delegate) + # flatten recursion result + |> concatLists + # find import location + |> map (group: findImport (root + "/groups/${group._name}")) + # filter by uniqueness + |> nt.prim.unique + # ignore missing groups + |> filter pathExists; in { mkNexus = root: outputsBuilder: let decl = parseDecl outputsBuilder; @@ -152,87 +181,21 @@ in { outputs = rec { nixosConfigurations = mapNodes nexus.nodes ( - nodeName: node: - lib.nixosSystem { + nodeName: node: let + nixosDecl = lib.nixosSystem { system = node.system; - modules = let - host = findImport (root + "/hosts/${nodeName}"); - groups = assert isList node.groups - || throw '' - Cerulean Nexus node "${nodeName}" does not declare group membership as a list, got "${typeOf node.groups}" instead! - Ensure `nexus.nodes.${nodeName}.groups` is a list under your call to `cerulean.mkNexus`. - ''; - node.groups - # ensure all members are actually groups - |> map (group: let - got = - if ! isAttrs group - then toString group - else - group - |> attrNames - |> map (name: "${name} = <${typeOf (getAttr name group)}>;") - |> concatStringsSep " " - |> (x: "{ ${x} }"); - in - if group ? _name - then group - else - throw '' - Cerulean Nexus node "${nodeName}" is a member of an incorrectly structured group. - Got "${got}" of primitive type "${typeOf group}". - NOTE: Groups can be accessed via `self.groups.PATH.TO.YOUR.GROUP` - '') - # add all inherited groups via _parent - |> map (let - delegate = g: - if g._parent == null - then [g] - else [g] ++ delegate (g._parent); - in - delegate) - # flatten recursion result - |> concatLists - # find import location - |> map (group: findImport (root + "/groups/${group._name}")) - # filter by uniqueness - |> nt.prim.unique - # ignore missing groups - |> filter pathExists; - in - [../nixos-module host] - ++ groups - ++ node.extraModules - ++ nexus.extraModules; - - # nix passes these to every single module - specialArgs = let - # XXX: NOTE: REF: https://github.com/NixOS/nixpkgs/blob/master/flake.nix#L57 - # XXX: NOTE: lib.nixosSystem is defined here ^^^^ - pkgConfig = - { - inherit (node) system; - # XXX: WARNING: TODO: i've stopped caring - # XXX: WARNING: TODO: just figure out a better solution to pkgConfig - config.allowUnfree = false; - config.allowBroken = false; - overlays = - self.overlays - ++ nexus.overlays - ++ node.overlays - ++ importOverlays root; - } - // nexus.extraPkgConfig # TODO: import - // node.extraPkgConfig; # TODO: import - in + specialArgs = nexus.specialArgs // node.specialArgs - // { - inherit root; - pkgs = import nixpkgs pkgConfig; - upkgs = import nixpkgs-unstable pkgConfig; - }; - } + // {inherit root;}; + modules = + [../nixos-module (findImport (root + "/hosts/${nodeName}"))] + ++ getGroupModules root nodeName node + ++ node.extraModules + ++ nexus.extraModules; + }; + in + nixosDecl ); deploy.nodes = mapNodes nexus.nodes (nodeName: node: let diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index 25a1d02..3d49434 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -31,8 +31,6 @@ in rec { extraModules = []; specialArgs = Terminal {}; overlays = []; - # XXX: WARNING: extraPkgConfig is a terrible solution (but im lazy for now) - extraPkgConfig = Terminal {}; deploy = { user = "root"; diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index 3bf3a9c..30e1967 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -{deploy-rs, ...}: { +{deploy-rs}: { imports = [ ./nixpkgs.nix ./home-manager.nix diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix index f4bb2ae..ee4ef55 100644 --- a/cerulean/nixos-module/nixpkgs.nix +++ b/cerulean/nixos-module/nixpkgs.nix @@ -12,13 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. { + nt, lib, config, ... }: let - cfg = config.pkgrepo; + inherit + (builtins) + mapAttrs + ; + + inherit + (nt) + flip + ; + + cfg = config.pkgsrc; in { - options.pkgrepo = lib.mkOption { + options.pkgsrc = lib.mkOption { type = lib.types.attrsOf lib.types.attrs; default = {}; description = "Declare and import custom package repositories."; @@ -34,15 +45,39 @@ in { }; }; - config.nixpkgs = - lib.mkIf (cfg ? pkgs) - (let - pkgs = cfg.pkgs; - in - lib.mkForce ( - (builtins.removeAttrs pkgs ["source"]) - // { - flake.source = pkgs.source; - } - )); + config = let + # TODO: use lib.types.submodule to restrict what options + # TODO: can be given to pkgsrc + repos = + cfg + |> mapAttrs ( + name: args: + assert args ? source + || abort '' + ${./.} + `pkgsrc.${name} missing required attribute "source"` + ''; + args + |> flip removeAttrs ["source"] + |> import args.source + ); + in { + # NOTE: _module.args is a special option that allows us to + # NOTE: set extend specialArgs from inside the modules. + # "pkgs" is unique since the nix module system already handles it + _module.args = + removeAttrs repos ["pkgs"]; + + # nixpkgs = + # lib.mkIf (cfg ? pkgs) + # (let + # pkgs = cfg.pkgs; + # in + # lib.mkForce ( + # (removeAttrs pkgs ["source"]) + # // { + # flake.source = pkgs.source; + # } + # )); + }; } From 5397bf5efcb1a047612a6e919bc2aad87ba9bb40 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 12:41:18 +1000 Subject: [PATCH 11/37] progress flake.lock to new upstream --- flake.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index e0b0735..40c2662 100644 --- a/flake.lock +++ b/flake.lock @@ -175,15 +175,15 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1770911021, - "narHash": "sha256-8FcXBu0CjeeZeq3uW2h/c5AV+hqELuyPiHsUogOSmZM=", - "owner": "emilelcb", + "lastModified": 1770950436, + "narHash": "sha256-+h5jrsIJBea5P+rAk4OqUpScqnHYQTvCRUhgGv/MX34=", + "owner": "cry128", "repo": "nt", - "rev": "471e1617e8cc0bc749712a7a6af2b2e9f988ffbf", + "rev": "8725f5079f8f27b3faafeff90e5fc075d55e7d0a", "type": "github" }, "original": { - "owner": "emilelcb", + "owner": "cry128", "repo": "nt", "type": "github" } From d363c47e7fcf5e0be180f89c4d045f3d4291f092 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 13:26:01 +1000 Subject: [PATCH 12/37] fix missing ... --- cerulean/nixos-module/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index 30e1967..3bf3a9c 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -{deploy-rs}: { +{deploy-rs, ...}: { imports = [ ./nixpkgs.nix ./home-manager.nix From 933423514279ee28e4cd9f31c2370971ed257196 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 13:54:37 +1000 Subject: [PATCH 13/37] ensure system is inherited --- cerulean/nexus/nexus.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 4c757ba..1171f3e 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -187,10 +187,13 @@ in { specialArgs = nexus.specialArgs // node.specialArgs - // {inherit root;}; + // { + inherit root; + inherit (node) system; + }; modules = [../nixos-module (findImport (root + "/hosts/${nodeName}"))] - ++ getGroupModules root nodeName node + ++ (getGroupModules root nodeName node) ++ node.extraModules ++ nexus.extraModules; }; From 369041869a4dac25558477473d739ffd0a9bf1be Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 15:58:04 +1000 Subject: [PATCH 14/37] add flake.nix#version field --- cerulean/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cerulean/default.nix b/cerulean/default.nix index 68846bf..06492f8 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -21,6 +21,8 @@ mix.newMixture inputs (mixture: { ./nexus ]; + version = "0.1.0"; + overlays = [ # build deploy-rs as a package not from the flake input, # hence we can rely on a nixpkg binary cache. From 30e8e1f6c32f157add047bcd90932b870c129d35 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Fri, 13 Feb 2026 19:32:22 +1000 Subject: [PATCH 15/37] fix nixpkgs.channels system --- cerulean/default.nix | 9 ++- cerulean/nexus/default.nix | 4 +- cerulean/nexus/nexus.nix | 20 ++++--- cerulean/nixos-module/default.nix | 12 +++- cerulean/nixos-module/home-manager.nix | 20 +++++-- cerulean/nixos-module/nixpkgs.nix | 77 ++++++++++++++------------ flake.lock | 6 +- 7 files changed, 92 insertions(+), 56 deletions(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index 06492f8..a824f8e 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -15,14 +15,19 @@ mix, deploy-rs, ... -} @ inputs: -mix.newMixture inputs (mixture: { +} @ args: +mix.newMixture args (mixture: { includes.public = [ ./nexus ]; version = "0.1.0"; + nixosModules = rec { + default = cerulean; + cerulean = ./nixos-module; + }; + overlays = [ # build deploy-rs as a package not from the flake input, # hence we can rely on a nixpkg binary cache. diff --git a/cerulean/nexus/default.nix b/cerulean/nexus/default.nix index d8e0f7c..65495bf 100644 --- a/cerulean/nexus/default.nix +++ b/cerulean/nexus/default.nix @@ -11,8 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -{mix, ...} @ inputs: -mix.newMixture inputs (mixture: { +{mix, ...} @ args: +mix.newMixture args (mixture: { includes.public = [ ./nodes.nix ./nexus.nix diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 1171f3e..ae8fe38 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. { + self, this, nt, lib, @@ -184,15 +185,18 @@ in { nodeName: node: let nixosDecl = lib.nixosSystem { system = node.system; - specialArgs = - nexus.specialArgs - // node.specialArgs - // { - inherit root; - inherit (node) system; - }; + specialArgs = let + specialArgs = + nexus.specialArgs + // node.specialArgs + // { + inherit root specialArgs; + inherit (node) system; + }; + in + specialArgs; modules = - [../nixos-module (findImport (root + "/hosts/${nodeName}"))] + [self.nixosModules.default (findImport (root + "/hosts/${nodeName}"))] ++ (getGroupModules root nodeName node) ++ node.extraModules ++ nexus.extraModules; diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index 3bf3a9c..d657021 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -11,9 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -{deploy-rs, ...}: { +{ + root, + deploy-rs, + ... +} @ args: { imports = [ - ./nixpkgs.nix + # user configuration + (import (root + "/nixpkgs.nix")) + # options declarations + (import ./nixpkgs.nix (args // {contextName = "hosts";})) + ./home-manager.nix ]; diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos-module/home-manager.nix index 6833e1d..4c41280 100644 --- a/cerulean/nixos-module/home-manager.nix +++ b/cerulean/nixos-module/home-manager.nix @@ -15,15 +15,27 @@ root, config, lib, + specialArgs, ... -} @ args: { +} @ args: let + inherit + (builtins) + attrNames + filter + pathExists + ; +in { home-manager = { users = config.users.users - |> builtins.attrNames - |> builtins.filter (x: builtins.pathExists (root + "/homes/${x}")) + |> attrNames + |> filter (x: pathExists (root + "/homes/${x}")) |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); - extraSpecialArgs = args; + extraSpecialArgs = specialArgs; + sharedModules = [ + (import (root + "/nixpkgs.nix")) + (import ./nixpkgs.nix (args // {contextName = "homes";})) + ]; }; } diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix index ee4ef55..9db5d3d 100644 --- a/cerulean/nixos-module/nixpkgs.nix +++ b/cerulean/nixos-module/nixpkgs.nix @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. { - nt, lib, + system, config, + contextName, ... }: let inherit @@ -22,62 +23,68 @@ mapAttrs ; - inherit - (nt) - flip - ; - - cfg = config.pkgsrc; + cfg = config.nixpkgs.channels; in { - options.pkgsrc = lib.mkOption { - type = lib.types.attrsOf lib.types.attrs; + options.nixpkgs.channels = lib.mkOption { + type = lib.types.attrsOf (lib.types.attrs); default = {}; - description = "Declare and import custom package repositories."; + description = "Declare package repositories per module context (nixos, home-manager, etc)"; example = { - "pkgs" = { - source = "inputs.nixpkgs"; - system = "x86-64-linux"; - config = { - allowUnfree = true; - allowBroken = false; + "homes" = { + "pkgs" = { + source = "inputs.nixpkgs"; + system = "x86-64-linux"; + config = { + allowUnfree = true; + allowBroken = false; + }; + }; + "upkgs" = { + source = "inputs.nixpkgs-unstable"; + system = "x86-64-linux"; + config = { + allowUnfree = true; + allowBroken = false; + }; }; }; }; }; + # or abort '' + # `nixpkgs.channels.${contextName}` does not exist, but neither does `nixpkgs.channels.default`! + # A channel configuration must be declared for module context "${contextName}". + # '' + config = let # TODO: use lib.types.submodule to restrict what options - # TODO: can be given to pkgsrc + # TODO: can be given to `nixpkgs.channels.${moduleName}.${name}` + decl = + cfg.${contextName} or cfg.default; + repos = - cfg + decl |> mapAttrs ( name: args: assert args ? source || abort '' - ${./.} - `pkgsrc.${name} missing required attribute "source"` + ${toString ./.} + `nixpkgs.channels.${contextName}.${name} missing required attribute "source"` ''; - args - |> flip removeAttrs ["source"] + ((removeAttrs args ["source"]) + // {inherit system;}) |> import args.source + |> lib.mkOverride 200 ); in { # NOTE: _module.args is a special option that allows us to # NOTE: set extend specialArgs from inside the modules. # "pkgs" is unique since the nix module system already handles it - _module.args = - removeAttrs repos ["pkgs"]; + _module.args = removeAttrs repos ["pkgs"]; - # nixpkgs = - # lib.mkIf (cfg ? pkgs) - # (let - # pkgs = cfg.pkgs; - # in - # lib.mkForce ( - # (removeAttrs pkgs ["source"]) - # // { - # flake.source = pkgs.source; - # } - # )); + nixpkgs = + if contextName == "hosts" + then {flake.source = lib.mkIf (decl ? pkgs) (lib.mkOverride 200 decl.pkgs.source);} + else {}; }; } diff --git a/flake.lock b/flake.lock index 40c2662..0dd06b1 100644 --- a/flake.lock +++ b/flake.lock @@ -175,11 +175,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1770950436, - "narHash": "sha256-+h5jrsIJBea5P+rAk4OqUpScqnHYQTvCRUhgGv/MX34=", + "lastModified": 1770975056, + "narHash": "sha256-ZXTz/P3zUbbM6lNXzt91u8EwfNqhXpYMu8+wvFZqQHE=", "owner": "cry128", "repo": "nt", - "rev": "8725f5079f8f27b3faafeff90e5fc075d55e7d0a", + "rev": "f42dcdd49a7921a7f433512e83d5f93696632412", "type": "github" }, "original": { From 23378831aaf2544b83dbd67f25518ad0a22899b5 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Fri, 13 Feb 2026 22:13:35 +1000 Subject: [PATCH 16/37] IM FUCKING SISYPHUS --- cerulean/nexus/nexus.nix | 1 + cerulean/nixos-module/default.nix | 5 +-- cerulean/nixos-module/home-manager.nix | 10 +++++- cerulean/nixos-module/nixpkgs.nix | 44 ++++++++++++++++++++------ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index ae8fe38..7466bb8 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -192,6 +192,7 @@ in { // { inherit root specialArgs; inherit (node) system; + _deploy-rs = deploy-rs; }; in specialArgs; diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos-module/default.nix index d657021..f15b236 100644 --- a/cerulean/nixos-module/default.nix +++ b/cerulean/nixos-module/default.nix @@ -13,7 +13,8 @@ # limitations under the License. { root, - deploy-rs, + system, + _deploy-rs, ... } @ args: { imports = [ @@ -26,6 +27,6 @@ ]; environment.systemPackages = [ - deploy-rs.packages.default + _deploy-rs.packages.${system}.default ]; } diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos-module/home-manager.nix index 4c41280..e693ac9 100644 --- a/cerulean/nixos-module/home-manager.nix +++ b/cerulean/nixos-module/home-manager.nix @@ -32,10 +32,18 @@ in { |> filter (x: pathExists (root + "/homes/${x}")) |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); - extraSpecialArgs = specialArgs; + # extraSpecialArgs = specialArgs; sharedModules = [ + # user configuration + # (import (root + "/nixpkgs.nix")) (import (root + "/nixpkgs.nix")) + # options declarations + # (import ./nixpkgs.nix (args // {contextName = "homes";})) (import ./nixpkgs.nix (args // {contextName = "homes";})) ]; + + # disable home-manager trying anything fancy + # we control the pkgs now!! + # useGlobalPkgs = true; }; } diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix index 9db5d3d..c5a97f7 100644 --- a/cerulean/nixos-module/nixpkgs.nix +++ b/cerulean/nixos-module/nixpkgs.nix @@ -66,25 +66,49 @@ in { decl |> mapAttrs ( name: args: - assert args ? source - || abort '' - ${toString ./.} - `nixpkgs.channels.${contextName}.${name} missing required attribute "source"` - ''; - ((removeAttrs args ["source"]) - // {inherit system;}) - |> import args.source - |> lib.mkOverride 200 + lib.mkForce ( + # builtins.trace "SAVE ME GOT NAME: ${name}" ( + assert args ? source + || abort '' + ${toString ./.} + `nixpkgs.channels.${contextName}.${name}` missing required attribute "source" + ''; + ((removeAttrs args ["source"]) + // {inherit system;}) + |> import args.source + # DEBUG: |> lib.mkOverride 200 + ) + # ) ); in { # NOTE: _module.args is a special option that allows us to # NOTE: set extend specialArgs from inside the modules. # "pkgs" is unique since the nix module system already handles it - _module.args = removeAttrs repos ["pkgs"]; + # DEBUG: _module.args = lib.mkOverride 200 ( + # _module.args = ( + # if contextName == "hosts" + # then repos + # else + # assert ( + # repos + # |> builtins.attrNames + # |> map (x: "\"${x}\"") + # |> builtins.concatStringsSep " " + # |> (x: "FUCK YOU SO BAD: { ${x} }") + # |> abort + # ); + # removeAttrs repos ["pkgs"] + # ); + _module.args = repos; nixpkgs = if contextName == "hosts" then {flake.source = lib.mkIf (decl ? pkgs) (lib.mkOverride 200 decl.pkgs.source);} + else if contextName == "homes" + then { + config = decl.pkgs.config or {}; + overlays = decl.pkgs.overlays or {}; + } else {}; }; } From 3ba385ee25cc02c91fe4c245a734d59c54a1b1df Mon Sep 17 00:00:00 2001 From: _cry64 Date: Fri, 13 Feb 2026 22:15:34 +1000 Subject: [PATCH 17/37] 0.2.0 --- cerulean/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index a824f8e..d7797c4 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -21,7 +21,7 @@ mix.newMixture args (mixture: { ./nexus ]; - version = "0.1.0"; + version = "0.2.0"; nixosModules = rec { default = cerulean; From f995411682535d63665ac9d441b0d885797b2336 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 14:06:29 +1000 Subject: [PATCH 18/37] add extraSpecialArgs --- cerulean/nixos-module/home-manager.nix | 39 ++++++++++++++------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos-module/home-manager.nix index e693ac9..97e4530 100644 --- a/cerulean/nixos-module/home-manager.nix +++ b/cerulean/nixos-module/home-manager.nix @@ -13,6 +13,7 @@ # limitations under the License. { root, + system, config, lib, specialArgs, @@ -25,25 +26,27 @@ pathExists ; in { - home-manager = { - users = - config.users.users - |> attrNames - |> filter (x: pathExists (root + "/homes/${x}")) - |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); + config = { + home-manager = { + users = + config.users.users + |> attrNames + |> filter (x: pathExists (root + "/homes/${x}")) + |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); - # extraSpecialArgs = specialArgs; - sharedModules = [ - # user configuration - # (import (root + "/nixpkgs.nix")) - (import (root + "/nixpkgs.nix")) - # options declarations - # (import ./nixpkgs.nix (args // {contextName = "homes";})) - (import ./nixpkgs.nix (args // {contextName = "homes";})) - ]; + extraSpecialArgs = {inherit root system;} // (specialArgs.inputs or {}); + sharedModules = [ + # user configuration + # (import (root + "/nixpkgs.nix")) + (import (root + "/nixpkgs.nix")) + # options declarations + # (import ./nixpkgs.nix (args // {contextName = "homes";})) + (import ./nixpkgs.nix (args // {contextName = "homes";})) + ]; - # disable home-manager trying anything fancy - # we control the pkgs now!! - # useGlobalPkgs = true; + # disable home-manager trying anything fancy + # we control the pkgs now!! + # useGlobalPkgs = true; + }; }; } From af89d579082b5deaa40400cb2f7b7eff35be4eae Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 14:42:02 +1000 Subject: [PATCH 19/37] fix overlays bad type --- cerulean/nixos-module/nixpkgs.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix index c5a97f7..5bf925f 100644 --- a/cerulean/nixos-module/nixpkgs.nix +++ b/cerulean/nixos-module/nixpkgs.nix @@ -21,6 +21,7 @@ inherit (builtins) mapAttrs + typeOf ; cfg = config.nixpkgs.channels; @@ -107,7 +108,8 @@ in { else if contextName == "homes" then { config = decl.pkgs.config or {}; - overlays = decl.pkgs.overlays or {}; + # XXX: WARNING: TODO: modify options so overlays must always be given as the correct type + overlays = decl.pkgs.overlays or []; } else {}; }; From f329d48223d8addd340f14c9c653960544b3ce2c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 16:00:34 +1000 Subject: [PATCH 20/37] support nixpkgs.channels.*.default --- cerulean/nixos-module/home-manager.nix | 2 -- cerulean/nixos-module/nixpkgs.nix | 43 +++++++++----------------- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos-module/home-manager.nix index 97e4530..21ee78c 100644 --- a/cerulean/nixos-module/home-manager.nix +++ b/cerulean/nixos-module/home-manager.nix @@ -37,10 +37,8 @@ in { extraSpecialArgs = {inherit root system;} // (specialArgs.inputs or {}); sharedModules = [ # user configuration - # (import (root + "/nixpkgs.nix")) (import (root + "/nixpkgs.nix")) # options declarations - # (import ./nixpkgs.nix (args // {contextName = "homes";})) (import ./nixpkgs.nix (args // {contextName = "homes";})) ]; diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos-module/nixpkgs.nix index 5bf925f..65db5a5 100644 --- a/cerulean/nixos-module/nixpkgs.nix +++ b/cerulean/nixos-module/nixpkgs.nix @@ -21,7 +21,6 @@ inherit (builtins) mapAttrs - typeOf ; cfg = config.nixpkgs.channels; @@ -52,11 +51,6 @@ in { }; }; - # or abort '' - # `nixpkgs.channels.${contextName}` does not exist, but neither does `nixpkgs.channels.default`! - # A channel configuration must be declared for module context "${contextName}". - # '' - config = let # TODO: use lib.types.submodule to restrict what options # TODO: can be given to `nixpkgs.channels.${moduleName}.${name}` @@ -68,7 +62,6 @@ in { |> mapAttrs ( name: args: lib.mkForce ( - # builtins.trace "SAVE ME GOT NAME: ${name}" ( assert args ? source || abort '' ${toString ./.} @@ -77,39 +70,31 @@ in { ((removeAttrs args ["source"]) // {inherit system;}) |> import args.source - # DEBUG: |> lib.mkOverride 200 ) - # ) ); in { # NOTE: _module.args is a special option that allows us to # NOTE: set extend specialArgs from inside the modules. - # "pkgs" is unique since the nix module system already handles it - # DEBUG: _module.args = lib.mkOverride 200 ( - # _module.args = ( - # if contextName == "hosts" - # then repos - # else - # assert ( - # repos - # |> builtins.attrNames - # |> map (x: "\"${x}\"") - # |> builtins.concatStringsSep " " - # |> (x: "FUCK YOU SO BAD: { ${x} }") - # |> abort - # ); - # removeAttrs repos ["pkgs"] - # ); _module.args = repos; - nixpkgs = + nixpkgs = let + defaultPkgs = + decl.default or (throw '' + Your `nixpkgs.nix` file does not declare a default package source. + Ensure you set `nixpkgs.channels.*.default = ...;` + ''); + in if contextName == "hosts" - then {flake.source = lib.mkIf (decl ? pkgs) (lib.mkOverride 200 decl.pkgs.source);} + then { + flake.source = lib.mkOverride 200 defaultPkgs.source; + config = lib.mkOverride 200 defaultPkgs.config; + } else if contextName == "homes" then { - config = decl.pkgs.config or {}; + # XXX: XXX: XXX: OH OH OH OMG, its because aurora never defines pkgs + config = lib.mkOverride 200 (defaultPkgs.config or {}); # XXX: WARNING: TODO: modify options so overlays must always be given as the correct type - overlays = decl.pkgs.overlays or []; + overlays = lib.mkOverride 200 (defaultPkgs.overlays or []); } else {}; }; From 8ef3ce18cd0e4f149cfd1211f26878d6d940d8c9 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:43:19 +1000 Subject: [PATCH 21/37] only inherit inputs --- cerulean/default.nix | 10 ++-------- cerulean/nexus/nexus.nix | 8 ++++---- flake.nix | 15 +++++++++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index d7797c4..6ec21cc 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -13,7 +13,7 @@ # limitations under the License. { mix, - deploy-rs, + inputs, ... } @ args: mix.newMixture args (mixture: { @@ -31,12 +31,6 @@ mix.newMixture args (mixture: { overlays = [ # build deploy-rs as a package not from the flake input, # hence we can rely on a nixpkg binary cache. - deploy-rs.overlays.default - # (self: super: { - # deploy-rs = { - # inherit (super) deploy-rs; - # lib = super.deploy-rs.lib; - # }; - # }) + inputs.deploy-rs.overlays.default ]; }) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 7466bb8..29d7387 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -16,7 +16,7 @@ this, nt, lib, - deploy-rs, + inputs, ... }: let inherit @@ -192,7 +192,7 @@ in { // { inherit root specialArgs; inherit (node) system; - _deploy-rs = deploy-rs; + _deploy-rs = inputs.deploy-rs; }; in specialArgs; @@ -220,7 +220,7 @@ in { user ; - nixosFor = system: deploy-rs.lib.${system}.activate.nixos; + nixosFor = system: inputs.deploy-rs.lib.${system}.activate.nixos; in { hostname = ssh.host; @@ -256,7 +256,7 @@ in { }; }); - checks = mapAttrs (system: deployLib: deployLib.deployChecks deploy) deploy-rs.lib; + checks = mapAttrs (system: deployLib: deployLib.deployChecks deploy) inputs.deploy-rs.lib; }; in outputs // customOutputs; diff --git a/flake.nix b/flake.nix index ff430bc..1a3f46e 100644 --- a/flake.nix +++ b/flake.nix @@ -22,7 +22,10 @@ nt.url = "github:cry128/nt"; - deploy-rs.url = "github:serokell/deploy-rs"; + deploy-rs = { + url = "github:serokell/deploy-rs"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { @@ -31,9 +34,9 @@ ... } @ inputs: import ./cerulean - (inputs - // { - inherit (nixpkgs) lib; - inherit (nt) mix; - }); + { + inherit inputs; + inherit (nixpkgs) lib; + inherit (nt) mix; + }; } From 75c87fb6d1d7cf132eb4ac7e8a6a0ef3f0bf5a7c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:43:37 +1000 Subject: [PATCH 22/37] remove nixpkgs-unstable --- flake.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/flake.nix b/flake.nix index 1a3f46e..24c43ac 100644 --- a/flake.nix +++ b/flake.nix @@ -16,10 +16,7 @@ inputs = { systems.url = "github:nix-systems/default"; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; - nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; - nt.url = "github:cry128/nt"; deploy-rs = { From 86a0c9fc3d9b5a786e8c7119390bb2f476dca7b9 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:45:39 +1000 Subject: [PATCH 23/37] auto-import home-manager and microvm nixosModules --- cerulean/nexus/nexus.nix | 8 +++++++- flake.nix | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 29d7387..88f2863 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -197,7 +197,13 @@ in { in specialArgs; modules = - [self.nixosModules.default (findImport (root + "/hosts/${nodeName}"))] + [ + self.nixosModules.default + (findImport (root + "/hosts/${nodeName}")) + + inputs.home-manager.nixosModules.default + inputs.microvm.nixosModules.microvm + ] ++ (getGroupModules root nodeName node) ++ node.extraModules ++ nexus.extraModules; diff --git a/flake.nix b/flake.nix index 24c43ac..6d911c5 100644 --- a/flake.nix +++ b/flake.nix @@ -19,10 +19,20 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nt.url = "github:cry128/nt"; + home-manager = { + url = "github:nix-community/home-manager/release-25.11"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + deploy-rs = { url = "github:serokell/deploy-rs"; inputs.nixpkgs.follows = "nixpkgs"; }; + + microvm = { + url = "github:microvm-nix/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { From 23615355b7ca97786f575e415958b4819d5341cc Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:12 +1000 Subject: [PATCH 24/37] remove overlays overlays is no longer configured this way --- cerulean/nexus/nodes.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index 3d49434..ed1c8ad 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -30,7 +30,6 @@ in rec { groups = []; extraModules = []; specialArgs = Terminal {}; - overlays = []; deploy = { user = "root"; From 49fcdee32068e1273fccdcb1c68a4e014a004c8b Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:29 +1000 Subject: [PATCH 25/37] add new TODO.md --- TODO.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/TODO.md b/TODO.md index 25f6f1b..f5e657d 100755 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,14 @@ -Allow `Cerulean.mkNexus` to be an alias for `flake-parts.lib.mkFlake` -also rename `Cerulean` to `cerulean` in Nix to maintain the naming convention. +- [ ] use the Nix module system instead of projectOnto for `cerulean.mkNexus` +- [ ] find an alternative to `nix.settings.trusted-users` probably +- [ ] add support for github:microvm-nix/microvm.nix +- [ ] add support for sops-nix -Using `flake-parts` ensures Cerulean is usable without restricting -yourself only to the Cerulean ecosystem. +- [ ] create an alternative to nixos-install called cerulean-install that + allows people to easily bootstrap new machines -- [ ] extend the options.nixpkgs to allow any number of package repositories!! -- [x] auto-propagate the same specialArgs for hosts to home-manager + +- [ ] rename nixos-modules/ to nixos/ + + +- [ ] add the ceru-build user +- [ ] ensure all machines are in groups.all by default From b94b42abec83d7b379da2dd9ed0fe8f207dc9a89 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:35 +1000 Subject: [PATCH 26/37] 0.2.1 --- cerulean/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index 6ec21cc..449028b 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -21,7 +21,7 @@ mix.newMixture args (mixture: { ./nexus ]; - version = "0.2.0"; + version = "0.2.1"; nixosModules = rec { default = cerulean; From 33d217c899348ce09e62b45f0f7c6a606c0e09cb Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:35:18 +1000 Subject: [PATCH 27/37] always use root group --- cerulean/nexus/nexus.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 88f2863..41ef28b 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -133,7 +133,12 @@ Cerulean Nexus node "${nodeName}" does not declare group membership as a list, got "${typeOf node.groups}" instead! Ensure `nexus.nodes.${nodeName}.groups` is a list under your call to `cerulean.mkNexus`. ''; - node.groups + # ensure root group is always added + (node.groups + ++ { + _parent = null; + _name = ROOT_GROUP_NAME; + }) # ensure all members are actually groups |> map (group: let got = From 149f873d976c80b2b8385a967446201fce9004da Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:46:37 +1000 Subject: [PATCH 28/37] move nixos-modules/ -> nixos/ --- cerulean/default.nix | 2 +- cerulean/{nixos-module => nixos}/default.nix | 0 cerulean/{nixos-module => nixos}/home-manager.nix | 0 cerulean/{nixos-module => nixos}/nixpkgs.nix | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename cerulean/{nixos-module => nixos}/default.nix (100%) rename cerulean/{nixos-module => nixos}/home-manager.nix (100%) rename cerulean/{nixos-module => nixos}/nixpkgs.nix (100%) diff --git a/cerulean/default.nix b/cerulean/default.nix index 449028b..f24bb5a 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -25,7 +25,7 @@ mix.newMixture args (mixture: { nixosModules = rec { default = cerulean; - cerulean = ./nixos-module; + cerulean = ./nixos; }; overlays = [ diff --git a/cerulean/nixos-module/default.nix b/cerulean/nixos/default.nix similarity index 100% rename from cerulean/nixos-module/default.nix rename to cerulean/nixos/default.nix diff --git a/cerulean/nixos-module/home-manager.nix b/cerulean/nixos/home-manager.nix similarity index 100% rename from cerulean/nixos-module/home-manager.nix rename to cerulean/nixos/home-manager.nix diff --git a/cerulean/nixos-module/nixpkgs.nix b/cerulean/nixos/nixpkgs.nix similarity index 100% rename from cerulean/nixos-module/nixpkgs.nix rename to cerulean/nixos/nixpkgs.nix From f23830e29a1910e91a66b5a3847027859bf2b59c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 23:29:41 +1000 Subject: [PATCH 29/37] more TODO.md --- TODO.md | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/TODO.md b/TODO.md index f5e657d..995ed69 100755 --- a/TODO.md +++ b/TODO.md @@ -1,14 +1,39 @@ - [ ] use the Nix module system instead of projectOnto for `cerulean.mkNexus` +- [ ] create an alternative to nixos-install called cerulean-install that + allows people to easily bootstrap new machines (and host it on dobutterfliescry.net) + - [ ] find an alternative to `nix.settings.trusted-users` probably +- [ ] add the ceru-build user, - [ ] add support for github:microvm-nix/microvm.nix - [ ] add support for sops-nix -- [ ] create an alternative to nixos-install called cerulean-install that - allows people to easily bootstrap new machines +- [ ] it would be cool to enable/disable groups and hosts +- [ ] find a standard for how nixpkgs.nix can have a different base per group + +- [X] rename nixos-modules/ to nixos/ +- [X] ensure all machines are in groups.all by default + +## Low Priority +- [ ] rename extraModules to modules? +- [ ] rename specialArgs to args? + +- [ ] make an extension to the nix module system (different to mix) + that allows transformations (ie a stop post config, ie outputs, which + it then returns instead of config) -- [ ] rename nixos-modules/ to nixos/ - - -- [ ] add the ceru-build user -- [ ] ensure all machines are in groups.all by default +``` +vms = { + home-assistant = { + autostart = true; + # matches in vms/* + image = "home-assistant"; + options = { + mem = 2048; + }; + }; + equinox = { + image = "home-assistant"; + }; +}; +``` From 619c74fad40e344772d6f14aadca82d9550e75d8 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:17:33 +1000 Subject: [PATCH 30/37] fix nt not propagated --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 6d911c5..220e732 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,7 @@ } @ inputs: import ./cerulean { - inherit inputs; + inherit inputs nt; inherit (nixpkgs) lib; inherit (nt) mix; }; From fbe9c6e6cef4034ba11d52d647c12df177145586 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:19:07 +1000 Subject: [PATCH 31/37] fix self not propagated --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 220e732..8fcd0e0 100644 --- a/flake.nix +++ b/flake.nix @@ -36,13 +36,14 @@ }; outputs = { + self, nixpkgs, nt, ... } @ inputs: import ./cerulean { - inherit inputs nt; + inherit inputs self nt; inherit (nixpkgs) lib; inherit (nt) mix; }; From 9ddb124ec26592157eb590964aaa3567f873ca2c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:20:24 +1000 Subject: [PATCH 32/37] fix [] ++ {} (im oopid) --- cerulean/nexus/nexus.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 41ef28b..d17cfdb 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -96,7 +96,7 @@ assert isAttrs nexus || abort '' Cerulean Nexus config must be provided as an attribute set, got "${typeOf nexus}" instead! - Ensure all the `nexus` declaration is an attribute set under your call to `cerulean.mkNexus`. + Ensure the `nexus` declaration is an attribute set under your call to `cerulean.mkNexus`. ''; let base = nt.projectOnto templateNexus nexus; in @@ -135,10 +135,12 @@ ''; # ensure root group is always added (node.groups - ++ { - _parent = null; - _name = ROOT_GROUP_NAME; - }) + ++ [ + { + _parent = null; + _name = ROOT_GROUP_NAME; + } + ]) # ensure all members are actually groups |> map (group: let got = From d527937829dec0f410f126a2f85e374cb99a2fbb Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:21:50 +1000 Subject: [PATCH 33/37] fix dont use microvm.nixosModules.microvm by default --- TODO.md | 6 ++ cerulean/nexus/nexus.nix | 2 +- cerulean/nexus/nodes.nix | 1 + cerulean/nexus/snow.nix | 108 ++++++++++++++++++++++++++++++ cerulean/nixos/microvm-child.nix | 13 ++++ cerulean/nixos/microvm-parent.nix | 13 ++++ 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 cerulean/nexus/snow.nix create mode 100644 cerulean/nixos/microvm-child.nix create mode 100644 cerulean/nixos/microvm-parent.nix diff --git a/TODO.md b/TODO.md index 995ed69..b80f03c 100755 --- a/TODO.md +++ b/TODO.md @@ -22,6 +22,12 @@ it then returns instead of config) +- [ ] what if we automated the process of replacing windows with Nix?? + then push this to nixos-anywhere or nix-infect lmaooo + +- [ ] patch microvm so that acpi=off https://github.com/microvm-nix/microvm.nix/commit/b59a26962bb324cc0a134756a323f3e164409b72 + cause otherwise 2GB causes a failure + ``` vms = { home-assistant = { diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index d17cfdb..f03d1ce 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -209,7 +209,7 @@ in { (findImport (root + "/hosts/${nodeName}")) inputs.home-manager.nixosModules.default - inputs.microvm.nixosModules.microvm + # inputs.microvm.nixosModules.microvm ] ++ (getGroupModules root nodeName node) ++ node.extraModules diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index ed1c8ad..1687e46 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -26,6 +26,7 @@ in rec { Terminal ; in { + enabled = true; system = "x86_64-linux"; # sane default (i hope...) groups = []; extraModules = []; diff --git a/cerulean/nexus/snow.nix b/cerulean/nexus/snow.nix new file mode 100644 index 0000000..1316ee3 --- /dev/null +++ b/cerulean/nexus/snow.nix @@ -0,0 +1,108 @@ +# Copyright 2026 Emile Clark-Boman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +{ + inputs, + lib, + ... +}: { + # nexus + options = let + inherit + (lib) + mkOption + types + ; + in { + extraModules = mkOption { + type = types.listOf types.path; + }; + specialArgs = mkOption { + type = types.attrs; + }; + + groups = mkOption { + type = types.attrs; + }; + + nodes = mkOption { + type = types.attrsOf (types.submoduleWith ({...}: { + options = { + enabled = mkOption { + type = types.bool; + default = true; + }; + system = mkOption { + type = types.enum inputs.systems; + }; + groups = mkOption { + type = types.list; + }; + modules = mkOption { + type = types.list; + }; + args = mkOption { + type = types.attrs; + }; + + deploy = { + user = mkOption { + type = types.str; + }; + sudoCmd = mkOption { + type = types.str; + }; + interactiveSudo = mkOption { + type = types.bool; + }; + + remoteBuild = mkOption { + type = types.bool; + }; + autoRollback = mkOption { + type = types.bool; + }; + magicRollback = mkOption { + type = types.bool; + }; + + activationTimeout = mkOption { + type = types.int; + }; + confirmTimeout = mkOption { + type = types.int; + }; + + ssh = { + host = mkOption { + type = types.str; + }; + user = mkOption { + type = types.str; + }; + port = mkOption { + type = types.int; + }; + opts = mkOption { + type = types.listOf types.str; + }; + }; + }; + }; + })); + }; + }; + + config = { + }; +} diff --git a/cerulean/nixos/microvm-child.nix b/cerulean/nixos/microvm-child.nix new file mode 100644 index 0000000..2b6a12e --- /dev/null +++ b/cerulean/nixos/microvm-child.nix @@ -0,0 +1,13 @@ +# Copyright 2026 Emile Clark-Boman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/cerulean/nixos/microvm-parent.nix b/cerulean/nixos/microvm-parent.nix new file mode 100644 index 0000000..2b6a12e --- /dev/null +++ b/cerulean/nixos/microvm-parent.nix @@ -0,0 +1,13 @@ +# Copyright 2026 Emile Clark-Boman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. From f15e28b76c0e40b2cf5e54dc5753f18cdaa20cc1 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 18:56:34 +1000 Subject: [PATCH 34/37] remove nixpkgs dependency YIPPIE YIPPIE YIPPIE --- TODO.md | 3 +++ cerulean/nexus/nexus.nix | 23 +++++++++++++---------- cerulean/nexus/nodes.nix | 32 +++++++++++++++++++++++++++++--- flake.nix | 4 +--- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/TODO.md b/TODO.md index b80f03c..e86d610 100755 --- a/TODO.md +++ b/TODO.md @@ -13,6 +13,9 @@ - [X] rename nixos-modules/ to nixos/ - [X] ensure all machines are in groups.all by default +- [X] fix nixpkgs.nix not working (default not respected) +- [X] remove dependence on nixpkgs + ## Low Priority - [ ] rename extraModules to modules? - [ ] rename specialArgs to args? diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index f03d1ce..24a0b75 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -15,7 +15,6 @@ self, this, nt, - lib, inputs, ... }: let @@ -50,13 +49,8 @@ (nt.naive.terminal) Terminal ; - - missing = msg: path: - Terminal (abort '' - Each Cerulean Nexus node is required to specify ${msg}! - Ensure `nexus.${path}` exists under your call to `cerulean.mkNexus`. - ''); in { + base = null; extraModules = []; specialArgs = Terminal {}; @@ -188,8 +182,13 @@ in { customOutputs = removeAttrs decl ["nexus"]; outputs = rec { - nixosConfigurations = mapNodes nexus.nodes ( - nodeName: node: let + nixosConfigurations = mapNodes nexus ( + { + lib, + nodeName, + node, + ... + }: let nixosDecl = lib.nixosSystem { system = node.system; specialArgs = let @@ -219,7 +218,11 @@ in { nixosDecl ); - deploy.nodes = mapNodes nexus.nodes (nodeName: node: let + deploy.nodes = mapNodes nexus ({ + nodeName, + node, + ... + }: let inherit (node.deploy) activationTimeout diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index 1687e46..fa0bc0b 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -25,6 +25,12 @@ in rec { (nt.naive.terminal) Terminal ; + + missing = msg: path: + Terminal (abort '' + Each Cerulean Nexus node is required to specify ${msg}! + Ensure `nexus.${path}` exists under your call to `cerulean.mkNexus`. + ''); in { enabled = true; system = "x86_64-linux"; # sane default (i hope...) @@ -32,6 +38,8 @@ in rec { extraModules = []; specialArgs = Terminal {}; + base = null; + deploy = { user = "root"; sudo = "sudo -u"; @@ -67,7 +75,25 @@ in rec { in nt.projectOnto templateAttrs nodeAttrs; - mapNodes = nodes: f: - nodes - |> mapAttrs (nodeName: nodeAttrs: f nodeName (parseNode nodeName nodeAttrs)); + mapNodes = nexus: f: + nexus.nodes + |> mapAttrs (nodeName: nodeAttrs: let + node = parseNode nodeName nodeAttrs; + + # use per-node base or default to nexus base + base = + if node.base != null + then node.base + else if nexus.base != null + then nexus.base + else + abort '' + Cerulean cannot construct nexus node "${nodeName}" without a base package source. + Ensure `nexus.nodes.*.base` or `nexus.base` is a flake reference to the github:NixOS/nixpkgs repository. + ''; + in + f { + inherit nodeName node; + lib = base.lib; + }); } diff --git a/flake.nix b/flake.nix index 8fcd0e0..6682de0 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,7 @@ inputs = { systems.url = "github:nix-systems/default"; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + # nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nt.url = "github:cry128/nt"; home-manager = { @@ -37,14 +37,12 @@ outputs = { self, - nixpkgs, nt, ... } @ inputs: import ./cerulean { inherit inputs self nt; - inherit (nixpkgs) lib; inherit (nt) mix; }; } From aab6c3bdd32e03c570ce95f5c18162f03516d7ce Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 18:56:51 +1000 Subject: [PATCH 35/37] update TODO --- TODO.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index e86d610..a12b8c3 100755 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,5 @@ +- [ ] deploy port should default to the first port given to `services.openssh` + - [ ] use the Nix module system instead of projectOnto for `cerulean.mkNexus` - [ ] create an alternative to nixos-install called cerulean-install that allows people to easily bootstrap new machines (and host it on dobutterfliescry.net) @@ -10,12 +12,16 @@ - [ ] it would be cool to enable/disable groups and hosts - [ ] find a standard for how nixpkgs.nix can have a different base per group +- [ ] go through all flake inputs (recursively) and ENSURE we remove all duplicates by using follows!! + - [X] rename nixos-modules/ to nixos/ - [X] ensure all machines are in groups.all by default - [X] fix nixpkgs.nix not working (default not respected) - [X] remove dependence on nixpkgs +- [ ] allow multiple privesc methods, the standard is pam_ssh_agent_auth + ## Low Priority - [ ] rename extraModules to modules? - [ ] rename specialArgs to args? @@ -31,7 +37,11 @@ - [ ] patch microvm so that acpi=off https://github.com/microvm-nix/microvm.nix/commit/b59a26962bb324cc0a134756a323f3e164409b72 cause otherwise 2GB causes a failure -``` +- [ ] rewrite the ceru cli in rust +- [ ] make `ceru` do local and remote deployments + +```nix +# REF: foxora vms = { home-assistant = { autostart = true; From da4cfefe7b2d5a204ce7d693bd11ed35e804c308 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 19:25:23 +1000 Subject: [PATCH 36/37] force system to be specified --- cerulean/nexus/nodes.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index fa0bc0b..ccb5c20 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -33,7 +33,7 @@ in rec { ''); in { enabled = true; - system = "x86_64-linux"; # sane default (i hope...) + system = missing "its system architecture" "system"; groups = []; extraModules = []; specialArgs = Terminal {}; From e813b0f443895dbeaa3fa5a5b2f080203d10895c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 19:37:21 +1000 Subject: [PATCH 37/37] ok maybe leave nixpkgs... we won't depend on it (i force that) but it's good to allow following --- flake.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 6682de0..89ce6b4 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,11 @@ inputs = { systems.url = "github:nix-systems/default"; - # nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + + # WARNING: nixpkgs is ONLY included so flakes using Cerulean can + # WARNING: force Cerulean's inputs to follow a specific revision. + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + nt.url = "github:cry128/nt"; home-manager = {