diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1c7a9a3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +## v0.2.0-alpha +Initial "stable" release. Cerulean is currently usable and supports: +1. local & remote deployment configuration +2. nixos/homemanager module-level support for any number of nixpkg branches +3. use of the [nix-systems standard](https://github.com/nix-systems/nix-systems), the introduction of the `snow/flake` standard, and the introduction of the `nixpkgs.nix` standard module. +4. hierarchical groups for NixOS hosts via `snow.nix` + +This is still a alpha-build of Cerulean. Everything will break in the future as I change the internals a bunch. I'll aim to write documentation in future cause currently there's no guide. + +## v0.2.1-alpha +Minor patches +- cerulean no longer has a `inputs.nixpkgs-unstable` (the `nixpkgs.nix` is the new alternative) +- `home-manager.nixosModules.default` and `microvm.nixosModules.microvm` are added as default modules +- fixed `groups.all` not being added to nodes with `groups = []` + +## v0.2.2-alpha +Minor patches +- fixed `nexus.groups.all` not added to empty `nexus.nodes.*.groups` declarations +- fixed bad propagation of inputs +- forced system architecture to be specified per node +- cerulean no longer depends on `nixpkgs`, `base` package set should be set instead +- rename `extraModules` -> `modules` +- rename `specialArgs` -> `args` diff --git a/TODO.md b/TODO.md index a12b8c3..1dde662 100755 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,7 @@ +- [ ] base should automatically be set as the default (dont do anything with the default) +- [ ] try to remove common foot guns, ie abort if the user provides the home-manager or microvm nixosModules + since cerulean ALREADY provides these + - [ ] deploy port should default to the first port given to `services.openssh` - [ ] use the Nix module system instead of projectOnto for `cerulean.mkNexus` @@ -23,8 +27,8 @@ - [ ] allow multiple privesc methods, the standard is pam_ssh_agent_auth ## Low Priority -- [ ] rename extraModules to modules? -- [ ] rename specialArgs to args? +- [X] rename extraModules to modules? +- [X] 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 @@ -40,6 +44,8 @@ - [ ] rewrite the ceru cli in rust - [ ] make `ceru` do local and remote deployments +- [ ] support `legacyImports` + ```nix # REF: foxora vms = { diff --git a/cerulean/nexus/nexus.nix b/cerulean/nexus/nexus.nix index 22424ba..5d0ca02 100644 --- a/cerulean/nexus/nexus.nix +++ b/cerulean/nexus/nexus.nix @@ -20,6 +20,7 @@ }: let inherit (builtins) + all attrNames concatLists concatStringsSep @@ -53,6 +54,7 @@ base = null; modules = []; args = Terminal {}; + homeManager = null; groups = Terminal {}; nodes = Terminal {}; @@ -92,13 +94,13 @@ Cerulean Nexus config must be provided as an attribute set, got "${typeOf nexus}" instead! Ensure the `nexus` declaration is an attribute set under your call to `cerulean.mkNexus`. ''; let - base = nt.projectOnto templateNexus nexus; + decl = nt.projectOnto templateNexus nexus; in # XXX: TODO: create a different version of nt.projectOnto that can actually # XXX: TODO: handle applying a transformation to the result of each datapoint - base + decl // { - groups = parseGroupDecl base.groups; + groups = parseGroupDecl decl.groups; }; parseDecl = outputsBuilder: let @@ -184,33 +186,52 @@ in { outputs = rec { nixosConfigurations = mapNodes nexus ( { + base, lib, nodeName, node, ... }: let - nixosDecl = lib.nixosSystem rec { - system = node.system; - specialArgs = - nexus.args - // node.args - // { - inherit root specialArgs; - inherit (node) system; - _deploy-rs = inputs.deploy-rs; - }; - modules = - [ - self.nixosModules.default - (findImport (root + "/hosts/${nodeName}")) + nixosDecl = let + homeManager = + if node.homeManager != null + then node.homeManager + else nexus.homeManager; - inputs.home-manager.nixosModules.default - # inputs.microvm.nixosModules.microvm - ] - ++ (getGroupModules root nodeName node) - ++ node.modules - ++ nexus.modules; - }; + userArgs = nexus.args // node.args; + ceruleanArgs = { + inherit root base; + inherit (node) system; + _cerulean = { + inherit inputs userArgs ceruleanArgs homeManager; + specialArgs = userArgs // ceruleanArgs; + }; + }; + specialArgs = assert (userArgs + |> attrNames + |> all (argName: + ! ceruleanArgs ? argName + || abort '' + `specialArgs` are like super important to Cerulean my love... attrNames - |> filter (x: pathExists (root + "/homes/${x}")) - |> (x: lib.genAttrs x (y: import (root + "/homes/${y}"))); + home-manager = { + users = + config.users.users + |> attrNames + |> filter (x: pathExists (root + "/homes/${x}")) + |> (x: + lib.genAttrs x (y: + import (root + "/homes/${y}"))); - extraSpecialArgs = {inherit root system;} // (specialArgs.inputs or {}); - sharedModules = [ - # user configuration - (import (root + "/nixpkgs.nix")) - # options declarations - (import ./nixpkgs.nix (args // {contextName = "homes";})) - ]; - - # disable home-manager trying anything fancy - # we control the pkgs now!! - # useGlobalPkgs = true; - }; + extraSpecialArgs = _cerulean.specialArgs; + sharedModules = [ + # user configuration + (import (root + "/nixpkgs.nix")) + # options declarations + (import ./nixpkgs.nix (args // {contextName = "homes";})) + ]; }; } diff --git a/cerulean/nixos/nixpkgs.nix b/cerulean/nixos/nixpkgs.nix index 65db5a5..0376f47 100644 --- a/cerulean/nixos/nixpkgs.nix +++ b/cerulean/nixos/nixpkgs.nix @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. { + base, lib, system, config, @@ -26,74 +27,66 @@ cfg = config.nixpkgs.channels; in { options.nixpkgs.channels = lib.mkOption { - type = lib.types.attrsOf (lib.types.attrs); + type = lib.types.attrs; default = {}; - description = "Declare package repositories per module context (nixos, home-manager, etc)"; + description = "Declare package repositories"; example = { - "homes" = { - "pkgs" = { - source = "inputs.nixpkgs"; - system = "x86-64-linux"; - config = { - allowUnfree = true; - allowBroken = false; - }; + "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; - }; + }; + "upkgs" = { + source = "inputs.nixpkgs-unstable"; + system = "x86-64-linux"; + config = { + allowUnfree = false; + allowBroken = true; }; }; }; }; config = let - # TODO: use lib.types.submodule to restrict what options - # TODO: can be given to `nixpkgs.channels.${moduleName}.${name}` - decl = - cfg.${contextName} or cfg.default; - repos = - decl + cfg + |> (xs: removeAttrs xs ["default"]) |> mapAttrs ( name: args: lib.mkForce ( assert args ? source || abort '' - ${toString ./.} - `nixpkgs.channels.${contextName}.${name}` missing required attribute "source" + `nixpkgs.channels.${name}` missing required attribute "source" ''; - ((removeAttrs args ["source"]) - // {inherit system;}) - |> import args.source + import args.source ({inherit system;} // (removeAttrs args ["source"])) ) ); + + # XXX: TODO: would it work to use `base` instead of having default? + defaultPkgs = + cfg.default or (throw '' + Your `nixpkgs.nix` file does not declare a default package source. + Ensure you set `nixpkgs.channels.*.default = ...;` + ''); in { # NOTE: _module.args is a special option that allows us to # NOTE: set extend specialArgs from inside the modules. - _module.args = repos; + # WARNING: pkgs is a reserved specialArg + _module.args = removeAttrs repos ["pkgs"]; - 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 + nixpkgs = if contextName == "hosts" then { - flake.source = lib.mkOverride 200 defaultPkgs.source; - config = lib.mkOverride 200 defaultPkgs.config; + flake.source = lib.mkOverride 200 base; # DEBUG: temp while getting base to work + overlays = lib.mkOverride 200 (defaultPkgs.overlays or {}); + config = lib.mkOverride 200 (defaultPkgs.config or {}); } else if contextName == "homes" then { - # 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 = lib.mkOverride 200 (defaultPkgs.overlays or []); } else {}; diff --git a/flake.lock b/flake.lock index 0dd06b1..fc8e402 100644 --- a/flake.lock +++ b/flake.lock @@ -3,7 +3,9 @@ "deploy-rs": { "inputs": { "flake-compat": "flake-compat", - "nixpkgs": "nixpkgs", + "nixpkgs": [ + "nixpkgs" + ], "utils": "utils" }, "locked": { @@ -58,6 +60,27 @@ "type": "github" } }, + "microvm": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, + "locked": { + "lastModified": 1771365290, + "narHash": "sha256-1XJOslVyF7yzf6yd/yl1VjGLywsbtwmQh3X1LuJcLI4=", + "owner": "microvm-nix", + "repo": "microvm.nix", + "rev": "789c90b164b55b4379e7a94af8b9c01489024c18", + "type": "github" + }, + "original": { + "owner": "microvm-nix", + "repo": "microvm.nix", + "type": "github" + } + }, "nix-github-actions": { "inputs": { "nixpkgs": [ @@ -105,38 +128,6 @@ } }, "nixpkgs": { - "locked": { - "lastModified": 1743014863, - "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-unstable": { - "locked": { - "lastModified": 1768305791, - "narHash": "sha256-AIdl6WAn9aymeaH/NvBj0H9qM+XuAuYbGMZaP0zcXAQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1412caf7bf9e660f2f962917c14b1ea1c3bc695e", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { "locked": { "lastModified": 1768323494, "narHash": "sha256-yBXJLE6WCtrGo7LKiB6NOt6nisBEEkguC/lq/rP3zRQ=", @@ -152,7 +143,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_2": { "locked": { "lastModified": 1767313136, "narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=", @@ -171,7 +162,7 @@ "nt": { "inputs": { "nix-unit": "nix-unit", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_2", "systems": "systems_2" }, "locked": { @@ -191,12 +182,28 @@ "root": { "inputs": { "deploy-rs": "deploy-rs", - "nixpkgs": "nixpkgs_2", - "nixpkgs-unstable": "nixpkgs-unstable", + "microvm": "microvm", + "nixpkgs": "nixpkgs", "nt": "nt", "systems": "systems_3" } }, + "spectrum": { + "flake": false, + "locked": { + "lastModified": 1759482047, + "narHash": "sha256-H1wiXRQHxxPyMMlP39ce3ROKCwI5/tUn36P8x6dFiiQ=", + "ref": "refs/heads/main", + "rev": "c5d5786d3dc938af0b279c542d1e43bce381b4b9", + "revCount": 996, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + }, + "original": { + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 89ce6b4..c1a5498 100644 --- a/flake.nix +++ b/flake.nix @@ -23,11 +23,6 @@ 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";