From 3ba385ee25cc02c91fe4c245a734d59c54a1b1df Mon Sep 17 00:00:00 2001 From: _cry64 Date: Fri, 13 Feb 2026 22:15:34 +1000 Subject: [PATCH 01/49] 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 02/49] 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 03/49] 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 04/49] 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 05/49] 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 06/49] 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 07/49] 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 08/49] 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 09/49] 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 10/49] 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 11/49] 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 12/49] 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 13/49] 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 14/49] 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 15/49] 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 16/49] 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 17/49] 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 18/49] 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 19/49] 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 20/49] 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 21/49] 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 = { From 2def17862f69883393a6c009e23242e4eff699cf Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:12:21 +1000 Subject: [PATCH 22/49] update README --- README.md | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b62396e..474239b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +![enbyware](https://pride-badges.pony.workers.dev/static/v1?label=enbyware&labelColor=%23555&stripeWidth=8&stripeColors=FCF434%2CFFFFFF%2C9C59D1%2C2C2C2C) +![repo size](https://img.shields.io/github/repo-size/cry128/cerulean) + >[!WARNING] > ✨ **Under Construction** ✨ > Cerulean has lived rent free in my head for the last 12 months. @@ -5,15 +8,41 @@ > for use at my workplace. **Be not afraid!** It's only a matter > of time until Cerulean is ready for use! +# 🌌 🚀 Cerulean Nexus +The culmination of 2 years designing better Nix flakes. Cerulean removes the boilerplate of managing +NixOS infrastructure by declaring each machine as a **node** and their relationships as *"Nexus Networks"*, +virtual networks of servers that Cerulean can manage. Each Nexus is **very powerful**. Allowing for simple +distributed computing, automatic construction of VPNs, DNS for local hostnames, and that's just scratching the surface... + +- Is your node a VPS? Set `deploy.ssh.host = "example.com"` and Cerulean will configure custom build users, + ssh deployment via custom PAM modules, etc etc +- Is your node a VM? Set `vms = [ nodes.VM_NODE ]` on your host node, and Cerulean will configure + all the bridging, NAT, and other networking you so desire! + +## 🩷💜 Motivation +Nix is intended as a non-restrictive & unopinionated system, which is amazing, but it also means +every user develops their own standards to simplify their config. Cerulean however is very much +opinionated and contains all the standards I personally believe should be sane defaults for every NixOS machine. + +> Flakes are not designed for NixOS, they're designed for Nix, and that's an important distinction. + +Flakes and NixOS don't offer anything to simplify managing interconnected nodes of machines. +But this ends with *extremely messy configs* with **a lot of footguns**. You shouldn't have to spend +days reading about networking and learning to work with other peoples' modules. + +Finally, the Nix module system assumes you only use one channel of `github:NixOS/nixpkgs` but this +just isn't realistic. Most people have both `inputs.nixpkgs` and `inputs.nixpkgs-unstable` defined. +So cerulean declares the `nixpkgs.channels.*` option so you don't have to import your channels +manually! + ## 💙 Same Colour, More Control -Cerulean is what you wish Azure could be. An expansive collection of microservices, pre-configured systems, +>[!NOTE] +> This section is *mostly* for the business minded people. + +Cerulean is what you wish Azure could be. Providing an expansive collection of microservices, pre-configured systems, and entirely self-hosted! Cerulean is built using NixOS as a foundation so you know it's never going to break randomly. NixOS backing makes Cerulean **extremely scalable**! Just rent a new VPS and Cerulean will build an ISO of your configuration. No stress, no hassle! Say goodbye to Azure! And say goodbye to Kubernetes! You're taking life into your own hands 💙 -### 🌌 🚀 Nexus -Cerulean allows you to declare *"Nexus Networks"*, virtual networks of servers that Cerulean can manage. -Each Nexus is **very powerful**. Allowing for simple distributed computing, automatic construction of a wireguard -VPN, distributed DNS for local hostnames, and that's just scratching the surface... From 47db6a2b350afc9baed035bf7d1cfd53b5ea65dd Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:18:11 +1000 Subject: [PATCH 23/49] update construction README --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 474239b..b1362ae 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,13 @@ >[!WARNING] > ✨ **Under Construction** ✨ -> Cerulean has lived rent free in my head for the last 12 months. -> I'm developing this project for personal use and especially -> for use at my workplace. **Be not afraid!** It's only a matter -> of time until Cerulean is ready for use! +> +> Cerulean is in an **experimental alpha release stage**.
+> **Be not afraid!** It's only a matter of time until Cerulean is ready for use! +> +> If you're curious about or want to use Cerulean then
+> *please please please* contact me on Bluesky [@dobutterfliescry.net](https://bsky.app/profile/dobutterfliescry.net).
+> (i would actually *melt* and fall in love with you...) # 🌌 🚀 Cerulean Nexus The culmination of 2 years designing better Nix flakes. Cerulean removes the boilerplate of managing From 0bb3c21aae76533220dddda64c8b4e664934bc41 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Fri, 13 Feb 2026 22:15:34 +1000 Subject: [PATCH 24/49] v0.2.0-alpha --- 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 91ebd09398f7a50e82d6a7a42efc6cdde77d3212 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 14:06:29 +1000 Subject: [PATCH 25/49] 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 162086b065df5ddfa26a99206c2b86a5ca391ca9 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 14:42:02 +1000 Subject: [PATCH 26/49] 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 84b2fa8a76bad78540f28af04fb538db8890a050 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sat, 14 Feb 2026 16:00:34 +1000 Subject: [PATCH 27/49] 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 88cd8c4b3bdc98654f0a32fa0e4de8fdfeedf430 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:43:19 +1000 Subject: [PATCH 28/49] 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 d9dc30cc98afe85a39bdbf6378b2a5e69b1491c2 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:43:37 +1000 Subject: [PATCH 29/49] 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 26903695b884375c8fd384d523e6349d7900bc4e Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 13:45:39 +1000 Subject: [PATCH 30/49] 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 368fa8978b3b2250a0bed5cbbc9c52016a66d79c Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:12 +1000 Subject: [PATCH 31/49] 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 fd32dac1bf83d3ae0bc125bc59f7066581b9effd Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:29 +1000 Subject: [PATCH 32/49] 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 53992e50a93cee9f7e71f69f16d257af97d43494 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:34:35 +1000 Subject: [PATCH 33/49] v0.2.1-alpha --- 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 a853b217c0699959a9aa1fba49e632d1293b3304 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:35:18 +1000 Subject: [PATCH 34/49] 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 0d8751780ee1ea06c2e0109ee1c4a2922d398cb1 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 17:46:37 +1000 Subject: [PATCH 35/49] 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 ee81f45bcfa56aac4ce8b65d516c720ffcb0b7aa Mon Sep 17 00:00:00 2001 From: _cry64 Date: Sun, 15 Feb 2026 23:29:41 +1000 Subject: [PATCH 36/49] 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 8d09a2b035621d6f8a982dc19ff9b9142c438a25 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:17:33 +1000 Subject: [PATCH 37/49] 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 dd77742f5fe5f0bc73ce02595945b43c3e1e7b46 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:19:07 +1000 Subject: [PATCH 38/49] 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 d241f6c1924f69912d070001c3b6c4e2226f1e2e Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:20:24 +1000 Subject: [PATCH 39/49] 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 12ffb132ac596b638226eaa9ba2ed67383d743b6 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 08:21:50 +1000 Subject: [PATCH 40/49] 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 108fefcd9ba3e399a5c85b8fbde11787fe96ff93 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 18:56:34 +1000 Subject: [PATCH 41/49] 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 7e122bbe144f3b4bfb8de55f6205236fe0f97993 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 18:56:51 +1000 Subject: [PATCH 42/49] 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 e6cda64e775d89f5ccd1c36ea26691ab8f812ddf Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 19:25:23 +1000 Subject: [PATCH 43/49] 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 0a768b960622c398770125305f70b490f744937d Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 16 Feb 2026 19:37:21 +1000 Subject: [PATCH 44/49] 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 = { From 84b7af58636744555498f7a94b7e58186b759a49 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:12:21 +1000 Subject: [PATCH 45/49] update README --- README.md | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b62396e..474239b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +![enbyware](https://pride-badges.pony.workers.dev/static/v1?label=enbyware&labelColor=%23555&stripeWidth=8&stripeColors=FCF434%2CFFFFFF%2C9C59D1%2C2C2C2C) +![repo size](https://img.shields.io/github/repo-size/cry128/cerulean) + >[!WARNING] > ✨ **Under Construction** ✨ > Cerulean has lived rent free in my head for the last 12 months. @@ -5,15 +8,41 @@ > for use at my workplace. **Be not afraid!** It's only a matter > of time until Cerulean is ready for use! +# 🌌 🚀 Cerulean Nexus +The culmination of 2 years designing better Nix flakes. Cerulean removes the boilerplate of managing +NixOS infrastructure by declaring each machine as a **node** and their relationships as *"Nexus Networks"*, +virtual networks of servers that Cerulean can manage. Each Nexus is **very powerful**. Allowing for simple +distributed computing, automatic construction of VPNs, DNS for local hostnames, and that's just scratching the surface... + +- Is your node a VPS? Set `deploy.ssh.host = "example.com"` and Cerulean will configure custom build users, + ssh deployment via custom PAM modules, etc etc +- Is your node a VM? Set `vms = [ nodes.VM_NODE ]` on your host node, and Cerulean will configure + all the bridging, NAT, and other networking you so desire! + +## 🩷💜 Motivation +Nix is intended as a non-restrictive & unopinionated system, which is amazing, but it also means +every user develops their own standards to simplify their config. Cerulean however is very much +opinionated and contains all the standards I personally believe should be sane defaults for every NixOS machine. + +> Flakes are not designed for NixOS, they're designed for Nix, and that's an important distinction. + +Flakes and NixOS don't offer anything to simplify managing interconnected nodes of machines. +But this ends with *extremely messy configs* with **a lot of footguns**. You shouldn't have to spend +days reading about networking and learning to work with other peoples' modules. + +Finally, the Nix module system assumes you only use one channel of `github:NixOS/nixpkgs` but this +just isn't realistic. Most people have both `inputs.nixpkgs` and `inputs.nixpkgs-unstable` defined. +So cerulean declares the `nixpkgs.channels.*` option so you don't have to import your channels +manually! + ## 💙 Same Colour, More Control -Cerulean is what you wish Azure could be. An expansive collection of microservices, pre-configured systems, +>[!NOTE] +> This section is *mostly* for the business minded people. + +Cerulean is what you wish Azure could be. Providing an expansive collection of microservices, pre-configured systems, and entirely self-hosted! Cerulean is built using NixOS as a foundation so you know it's never going to break randomly. NixOS backing makes Cerulean **extremely scalable**! Just rent a new VPS and Cerulean will build an ISO of your configuration. No stress, no hassle! Say goodbye to Azure! And say goodbye to Kubernetes! You're taking life into your own hands 💙 -### 🌌 🚀 Nexus -Cerulean allows you to declare *"Nexus Networks"*, virtual networks of servers that Cerulean can manage. -Each Nexus is **very powerful**. Allowing for simple distributed computing, automatic construction of a wireguard -VPN, distributed DNS for local hostnames, and that's just scratching the surface... From 57a4ec8d82ee553f3107daec51d5b231bb52ec51 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:18:11 +1000 Subject: [PATCH 46/49] update construction README --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 474239b..b1362ae 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,13 @@ >[!WARNING] > ✨ **Under Construction** ✨ -> Cerulean has lived rent free in my head for the last 12 months. -> I'm developing this project for personal use and especially -> for use at my workplace. **Be not afraid!** It's only a matter -> of time until Cerulean is ready for use! +> +> Cerulean is in an **experimental alpha release stage**.
+> **Be not afraid!** It's only a matter of time until Cerulean is ready for use! +> +> If you're curious about or want to use Cerulean then
+> *please please please* contact me on Bluesky [@dobutterfliescry.net](https://bsky.app/profile/dobutterfliescry.net).
+> (i would actually *melt* and fall in love with you...) # 🌌 🚀 Cerulean Nexus The culmination of 2 years designing better Nix flakes. Cerulean removes the boilerplate of managing From 880c4ebfbee72760775cce5d015e1fa85ff9ecf4 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:42:59 +1000 Subject: [PATCH 47/49] rename specialArgs -> args --- cerulean/nexus/nexus.nix | 23 ++++++++++------------- cerulean/nexus/nodes.nix | 2 +- cerulean/nexus/snow.nix | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 24a0b75..2424cd2 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -52,7 +52,7 @@ in { base = null; extraModules = []; - specialArgs = Terminal {}; + args = Terminal {}; groups = Terminal {}; nodes = Terminal {}; @@ -189,19 +189,16 @@ in { node, ... }: let - nixosDecl = lib.nixosSystem { + nixosDecl = lib.nixosSystem rec { system = node.system; - specialArgs = let - specialArgs = - nexus.specialArgs - // node.specialArgs - // { - inherit root specialArgs; - inherit (node) system; - _deploy-rs = inputs.deploy-rs; - }; - in - specialArgs; + specialArgs = + nexus.args + // node.args + // { + inherit root specialArgs; + inherit (node) system; + _deploy-rs = inputs.deploy-rs; + }; modules = [ self.nixosModules.default diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index ccb5c20..46b9add 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -36,7 +36,7 @@ in rec { system = missing "its system architecture" "system"; groups = []; extraModules = []; - specialArgs = Terminal {}; + args = Terminal {}; base = null; diff --git a/cerulean/nexus/snow.nix b/cerulean/nexus/snow.nix index 1316ee3..6704710 100644 --- a/cerulean/nexus/snow.nix +++ b/cerulean/nexus/snow.nix @@ -27,7 +27,7 @@ extraModules = mkOption { type = types.listOf types.path; }; - specialArgs = mkOption { + args = mkOption { type = types.attrs; }; From f8ed7e278762477443635b5222ddb82ba71b3b03 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:46:59 +1000 Subject: [PATCH 48/49] rename extraModules -> modules --- cerulean/nexus/nexus.nix | 6 +++--- cerulean/nexus/nodes.nix | 2 +- cerulean/nexus/snow.nix | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 2424cd2..22424ba 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -51,7 +51,7 @@ ; in { base = null; - extraModules = []; + modules = []; args = Terminal {}; groups = Terminal {}; @@ -208,8 +208,8 @@ in { # inputs.microvm.nixosModules.microvm ] ++ (getGroupModules root nodeName node) - ++ node.extraModules - ++ nexus.extraModules; + ++ node.modules + ++ nexus.modules; }; in nixosDecl diff --git a/cerulean/nexus/nodes.nix b/cerulean/nexus/nodes.nix index 46b9add..a1b6117 100644 --- a/cerulean/nexus/nodes.nix +++ b/cerulean/nexus/nodes.nix @@ -35,7 +35,7 @@ in rec { enabled = true; system = missing "its system architecture" "system"; groups = []; - extraModules = []; + modules = []; args = Terminal {}; base = null; diff --git a/cerulean/nexus/snow.nix b/cerulean/nexus/snow.nix index 6704710..28496ca 100644 --- a/cerulean/nexus/snow.nix +++ b/cerulean/nexus/snow.nix @@ -24,7 +24,7 @@ types ; in { - extraModules = mkOption { + modules = mkOption { type = types.listOf types.path; }; args = mkOption { From e5d6c1830b4b31d2c0d7709c2dbe4c64b03b44b7 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 17 Feb 2026 11:47:49 +1000 Subject: [PATCH 49/49] v0.2.2-alpha --- cerulean/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cerulean/default.nix b/cerulean/default.nix index f24bb5a..202fdf9 100644 --- a/cerulean/default.nix +++ b/cerulean/default.nix @@ -21,7 +21,7 @@ mix.newMixture args (mixture: { ./nexus ]; - version = "0.2.1"; + version = "0.2.2"; nixosModules = rec { default = cerulean;