From a30c45c01d8beb3db50a2b694546a2653444128f Mon Sep 17 00:00:00 2001 From: Jack O'Sullivan Date: Sun, 13 Feb 2022 23:06:31 +0000 Subject: [PATCH] Implement home-manager support --- boxes/colony.nix | 26 +++++++++++++--------- flake.lock | 11 +++++----- flake.nix | 46 ++++++++++++++++++++++++++++----------- home-modules/common.nix | 48 +++++++++++++++++++++++++++++++++++++++++ homes.nix | 32 +++++++++++++++++++++++++++ homes/castle.nix | 6 ++++++ modules/common.nix | 21 +++++++++++++----- systems.nix | 4 ++-- util.nix | 20 +++++++++++++++-- 9 files changed, 176 insertions(+), 38 deletions(-) create mode 100644 home-modules/common.nix create mode 100644 homes.nix create mode 100644 homes/castle.nix diff --git a/boxes/colony.nix b/boxes/colony.nix index 8477369..4a809c1 100644 --- a/boxes/colony.nix +++ b/boxes/colony.nix @@ -1,15 +1,5 @@ { lib, pkgs, ... }: { - fileSystems = { - "/persist" = { - device = "/dev/disk/by-label/persist"; - fsType = "ext4"; - neededForBoot = true; - }; - }; - - networking = { }; - my = { firewall = { trustedInterfaces = [ "blah" ]; @@ -25,5 +15,21 @@ }; }; server.enable = true; + + homeConfig = { + programs = { + fish.enable = true; + }; + }; }; + + fileSystems = { + "/persist" = { + device = "/dev/disk/by-label/persist"; + fsType = "ext4"; + neededForBoot = true; + }; + }; + + networking = { }; } diff --git a/flake.lock b/flake.lock index 4c40cdb..7c683ad 100644 --- a/flake.lock +++ b/flake.lock @@ -80,17 +80,16 @@ ] }, "locked": { - "lastModified": 1644534280, - "narHash": "sha256-Gzf/Jq/F1vvTp6XkzPU+pBCj3OSAFLiR7f0ptwRseiI=", + "lastModified": 1644706973, + "narHash": "sha256-xOyxrhc5V79u0ZNmnPmJbY3ngtp43dNISEmrb8Ie6wQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "6d9d9294d09b5e88df65f8c6651efb8a4d7d2476", + "rev": "7c2ae0bdd20ddcaafe41ef669226a1df67f8aa06", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "home-manager", - "type": "github" + "id": "home-manager", + "type": "indirect" } }, "impermanence": { diff --git a/flake.nix b/flake.nix index d2557e6..fa49fa5 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,7 @@ agenix.inputs.nixpkgs.follows = "nixpkgs-unstable"; deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable"; - home-manager.url = "github:nix-community/home-manager"; + home-manager.url = "home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs-unstable"; # Stuff used by systems @@ -35,7 +35,7 @@ let inherit (builtins) mapAttrs attrValues; inherit (lib.flake) eachDefaultSystem; - inherit (lib.my) mkApp mkShellApp; + inherit (lib.my) mkApp mkShellApp inlineModules mkDefaultSystemsPkgs flakePackageOverlay; extendLib = lib: lib.extend (final: prev: { my = import ./util.nix { lib = final; }; @@ -51,14 +51,24 @@ lib = pkgsFlakes.unstable.lib; pkgs' = mapAttrs - (_: path: lib.my.mkDefaultSystemsPkgs path { + (_: path: mkDefaultSystemsPkgs path (system: { overlays = [ libOverlay inputs.agenix.overlay inputs.deploy-rs.overlay inputs.nix.overlay + (flakePackageOverlay inputs.home-manager system) ]; - }) + })) + pkgsFlakes; + + # Easiest to build the basic pkgs here (with our lib overlay too) + homePkgs' = mapAttrs + (_: path: mkDefaultSystemsPkgs path (_: { + overlays = [ + libOverlay + ]; + })) pkgsFlakes; modules = mapAttrs (_: f: ./. + "/modules/${f}") { @@ -69,23 +79,32 @@ firewall = "firewall.nix"; server = "server.nix"; }; + homeModules = mapAttrs (_: f: ./. + "/home-modules/${f}") { + common = "common.nix"; + }; in # Platform independent stuff { lib = lib.my; nixpkgs = pkgs'; - nixosModules = mapAttrs - (_: path: - { - _file = path; - imports = [ (import path) ]; - }) - modules; + nixosModules = inlineModules modules; + homeModules = inlineModules homeModules; - nixosConfigurations = import ./systems.nix { inherit lib pkgsFlakes inputs; modules = attrValues modules; }; + nixosConfigurations = import ./systems.nix { + inherit lib pkgsFlakes inputs; + modules = attrValues modules; + homeModules = attrValues homeModules; + }; systems = mapAttrs (_: system: system.config.system.build.toplevel) self.nixosConfigurations; vms = mapAttrs (_: system: system.config.my.build.devVM) self.nixosConfigurations; + + homeConfigurations = import ./homes.nix { + inherit lib inputs; + pkgs' = homePkgs'; + modules = attrValues homeModules; + }; + homes = mapAttrs(_: home: home.activationPackage) self.homeConfigurations; } // (eachDefaultSystem (system: let @@ -99,7 +118,7 @@ }; devShell = pkgs.mkShell { - NIX_CONFIG = pkgs.writeText "nix.conf" + NIX_USER_CONF_FILES = pkgs.writeText "nix.conf" '' experimental-features = nix-command flakes ca-derivations ''; @@ -109,6 +128,7 @@ agenix deploy-rs.deploy-rs nixpkgs-fmt + home-manager ]; }; })); diff --git a/home-modules/common.nix b/home-modules/common.nix new file mode 100644 index 0000000..7fafa23 --- /dev/null +++ b/home-modules/common.nix @@ -0,0 +1,48 @@ +{ lib, pkgs, inputs, isStandalone, config, ... }: +let + inherit (lib) mkMerge mkIf mkDefault mkForce; +in +mkMerge [ + { + programs = { + home-manager = { + # Even when enabled this will only be actually installed in standalone mode + enable = true; + }; + + htop = { + enable = true; + settings = {}; + }; + }; + + home = { + language.base = mkDefault "en_IE.UTF-8"; + + packages = with pkgs; [ + tree + iperf3 + ]; + + # The flake passes a default setting, but we don't care about that + stateVersion = mkForce "22.05"; + }; + } + (mkIf isStandalone { + # Note: this only applies outside NixOS where home-manager imports nixpkgs internally + nixpkgs = { + overlays = [ + inputs.nix.overlay + ]; + config = { + allowUnfree = true; + }; + }; + + home = { + packages = with pkgs; [ + nix + ]; + }; + }) +] diff --git a/homes.nix b/homes.nix new file mode 100644 index 0000000..7dda0f0 --- /dev/null +++ b/homes.nix @@ -0,0 +1,32 @@ +{ lib, inputs, pkgs', modules }: +let + inherit (builtins) removeAttrs mapAttrs; + inherit (lib) recursiveUpdate; + + mkHome = name: { + system, + nixpkgs ? "unstable", + config, + ... + }@args: + let + rest = removeAttrs args [ "nixpkgs" "config" ]; + in + inputs.home-manager.lib.homeManagerConfiguration (recursiveUpdate rest { + configuration = config; + pkgs = pkgs'.${nixpkgs}.${system}; + extraModules = modules ++ [{ + _module.args = { inherit inputs; isStandalone = true; }; + }]; + }); +in +mapAttrs mkHome { + "dev@castle" = { + system = "x86_64-linux"; + nixpkgs = "unstable"; + config = homes/castle.nix; + + homeDirectory = "/home/dev"; + username = "dev"; + }; +} diff --git a/homes/castle.nix b/homes/castle.nix new file mode 100644 index 0000000..a4d6bdd --- /dev/null +++ b/homes/castle.nix @@ -0,0 +1,6 @@ +{ pkgs, ... }: +{ + programs = { + kakoune.enable = true; + }; +} diff --git a/modules/common.nix b/modules/common.nix index 66861a9..5eeb1a3 100644 --- a/modules/common.nix +++ b/modules/common.nix @@ -1,5 +1,6 @@ -{ lib, pkgs, inputs, system, config, options, ... }: +{ lib, pkgs, inputs, homeModules, config, options, ... }: let + inherit (builtins) attrValues; inherit (lib) mkIf mkDefault mkAliasDefinitions; inherit (lib.my) mkOpt'; in @@ -7,6 +8,7 @@ in options.my = with lib.types; { # Pretty hacky but too lazy to figure out if there's a better way to alias the options user = mkOpt' (attrsOf anything) { } "User definition (as `users.users.*`)."; + homeConfig = mkOpt' anything {} "Home configuration (as `home-manager.users.*`)"; }; config = @@ -25,13 +27,23 @@ in }; }; - time.timeZone = mkDefault "Europe/Dublin"; + home-manager = { + useGlobalPkgs = mkDefault true; + useUserPackages = mkDefault true; + sharedModules = homeModules ++ [{ + _module.args = { inherit inputs; isStandalone = false; }; + }]; + }; users = { mutableUsers = false; users.${uname} = mkAliasDefinitions options.my.user; }; + # NOTE: As the "outermost" module is still being evaluated in NixOS land, special params (e.g. pkgs) won't be + # passed to it + home-manager.users.${uname} = config.my.homeConfig; + security = { sudo.enable = mkDefault false; doas = { @@ -55,6 +67,8 @@ in }; }; + time.timeZone = mkDefault "Europe/Dublin"; + boot = { # Use latest LTS release by default kernelPackages = mkDefault pkgs.linuxKernel.packages.linux_5_15; @@ -80,10 +94,7 @@ in environment.systemPackages = with pkgs; [ bash-completion - tree vim - htop - iperf3 ]; services.openssh = { diff --git a/systems.nix b/systems.nix index 15c1660..4dfc303 100644 --- a/systems.nix +++ b/systems.nix @@ -1,4 +1,4 @@ -{ lib, pkgsFlakes, inputs, modules }: +{ lib, pkgsFlakes, inputs, modules, homeModules }: let inherit (builtins) attrValues mapAttrs; inherit (lib) optionals mkDefault; @@ -35,7 +35,7 @@ let ] ++ (optionals docCustom modules); modules = (optionals (!docCustom) modules) ++ [ { - _module.args = { inherit system inputs; }; + _module.args = { inherit system inputs homeModules; }; system.name = name; networking.hostName = mkDefault name; } diff --git a/util.nix b/util.nix index 5ae2dd0..d4b6087 100644 --- a/util.nix +++ b/util.nix @@ -1,6 +1,6 @@ { lib }: let - inherit (builtins) replaceStrings elemAt; + inherit (builtins) replaceStrings elemAt mapAttrs; inherit (lib) genAttrs mapAttrs' types mkOption mkOverride; inherit (lib.flake) defaultSystems; in @@ -21,9 +21,25 @@ rec { ports = checked (replaceStrings ["-"] [":"] (elemAt m 1)); }; - mkDefaultSystemsPkgs = path: args: genAttrs defaultSystems (system: import path (args // { inherit system; })); + mkDefaultSystemsPkgs = path: args': genAttrs defaultSystems (system: import path ((args' system) // { inherit system; })); mkApp = program: { type = "app"; inherit program; }; mkShellApp = pkgs: name: text: mkApp (pkgs.writeShellScript name text).outPath; + inlineModules = modules: mapAttrs + (_: path: + { + _file = path; + imports = [ (import path) ]; + }) + modules; + flakePackageOverlay' = flake: pkg: system: (final: prev: + let + pkg' = if pkg != null then flake.packages.${system}.${pkg} else flake.defaultPackage.${system}; + name = if pkg != null then pkg else pkg'.name; + in + { + ${name} = pkg'; + }); + flakePackageOverlay = flake: flakePackageOverlay' flake null; mkOpt = type: default: mkOption { inherit type default; }; mkOpt' = type: default: description: mkOption { inherit type default description; };