diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | accounts/.keep | 0 | ||||
-rw-r--r-- | flake.lock | 49 | ||||
-rw-r--r-- | flake.nix | 94 | ||||
-rw-r--r-- | hosts/.keep | 0 | ||||
-rw-r--r-- | modules/.keep | 0 | ||||
-rw-r--r-- | overlays/.keep | 0 | ||||
-rw-r--r-- | pkgs/default.nix | 3 | ||||
-rw-r--r-- | shell.nix | 16 | ||||
-rw-r--r-- | system-profiles/.keep | 0 | ||||
-rw-r--r-- | system-profiles/core.nix | 47 | ||||
-rw-r--r-- | user-profiles/.keep | 0 | ||||
-rw-r--r-- | users/.keep | 0 | ||||
-rw-r--r-- | utils/default.nix | 57 |
14 files changed, 268 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f295f429 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | result | ||
2 | result-* \ No newline at end of file | ||
diff --git a/accounts/.keep b/accounts/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/accounts/.keep | |||
diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..89225a55 --- /dev/null +++ b/flake.lock | |||
@@ -0,0 +1,49 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "home-manager": { | ||
4 | "inputs": { | ||
5 | "nixpkgs": [ | ||
6 | "nixpkgs" | ||
7 | ] | ||
8 | }, | ||
9 | "locked": { | ||
10 | "lastModified": 1609269962, | ||
11 | "narHash": "sha256-YvkJhcBBls39JFZzh/S3oRKyDFAgy2KoW5AzJ+MvNgQ=", | ||
12 | "owner": "nix-community", | ||
13 | "repo": "home-manager", | ||
14 | "rev": "8e0c1c55fbb7f16f9fd313275ddf63c97b34394c", | ||
15 | "type": "github" | ||
16 | }, | ||
17 | "original": { | ||
18 | "owner": "nix-community", | ||
19 | "ref": "master", | ||
20 | "repo": "home-manager", | ||
21 | "type": "github" | ||
22 | } | ||
23 | }, | ||
24 | "nixpkgs": { | ||
25 | "locked": { | ||
26 | "lastModified": 1609337906, | ||
27 | "narHash": "sha256-xj027twGqdK/xRzxlnM8icyUUF4GANlBevHqLYhqb7w=", | ||
28 | "owner": "NixOS", | ||
29 | "repo": "nixpkgs", | ||
30 | "rev": "58f3c19b78594e1839abf702fa73ddf9d7a96437", | ||
31 | "type": "github" | ||
32 | }, | ||
33 | "original": { | ||
34 | "owner": "NixOS", | ||
35 | "ref": "master", | ||
36 | "repo": "nixpkgs", | ||
37 | "type": "github" | ||
38 | } | ||
39 | }, | ||
40 | "root": { | ||
41 | "inputs": { | ||
42 | "home-manager": "home-manager", | ||
43 | "nixpkgs": "nixpkgs" | ||
44 | } | ||
45 | } | ||
46 | }, | ||
47 | "root": "root", | ||
48 | "version": 7 | ||
49 | } | ||
diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..fa1e81d6 --- /dev/null +++ b/flake.nix | |||
@@ -0,0 +1,94 @@ | |||
1 | { | ||
2 | description = "gkleen's machines"; | ||
3 | |||
4 | inputs = { | ||
5 | nixpkgs = { | ||
6 | type = "github"; | ||
7 | owner = "NixOS"; | ||
8 | repo = "nixpkgs"; | ||
9 | ref = "master"; | ||
10 | }; | ||
11 | home-manager = { | ||
12 | type = "github"; | ||
13 | owner = "nix-community"; | ||
14 | repo = "home-manager"; | ||
15 | ref = "master"; | ||
16 | inputs.nixpkgs.follows = "nixpkgs"; | ||
17 | }; | ||
18 | }; | ||
19 | |||
20 | outputs = { self, nixpkgs, home-manager }@inputs: | ||
21 | let | ||
22 | inherit (builtins) attrNames attrValues elemAt; | ||
23 | inherit (nixpkgs) lib; | ||
24 | utils = import ./utils { inherit lib; }; | ||
25 | inherit (utils) recImport overrideModule; | ||
26 | inherit (lib) nixosSystem mkIf splitString filterAttrs listToAttrs mapAttrsToList nameValuePair concatMap composeManyExtensions mapAttrs mapAttrs' recursiveUpdate; | ||
27 | |||
28 | mkNixosConfiguration = dir: path: hostName: nixosSystem rec { | ||
29 | specialArgs = { | ||
30 | flake = self; | ||
31 | flakeInputs = inputs; | ||
32 | path = toString ./.; | ||
33 | }; | ||
34 | modules = | ||
35 | let | ||
36 | defaultProfiles = with self.nixosModules.systemProfiles; [core]; | ||
37 | local = "${toString dir}/${path}"; | ||
38 | global._module.args = { | ||
39 | customUtils = utils; | ||
40 | inherit hostName; | ||
41 | }; | ||
42 | accountModules = attrValues (filterAttrs accountMatchesHost self.nixosModules.accounts); | ||
43 | accountMatchesHost = n: _v: | ||
44 | let | ||
45 | accountName' = splitString "@" n; | ||
46 | hostName' = elemAt accountName' 1; | ||
47 | in hostName' == hostName; | ||
48 | in [ home-manager.nixosModules.home-manager global ] ++ defaultProfiles ++ [ local ] ++ accountModules; | ||
49 | }; | ||
50 | |||
51 | mkSystemProfile = dir: path: profileName: { | ||
52 | imports = [ "${toString dir}/${path}" ]; | ||
53 | config = { | ||
54 | system.profiles = [profileName]; | ||
55 | }; | ||
56 | }; | ||
57 | |||
58 | mkUserModule = dir: path: userName: overrideModule (import "${toString dir}/${path}") (inputs: inputs // { inherit userName; }) (outputs: { _file = "${toString dir}/${path}"; } // outputs); | ||
59 | |||
60 | mkAccountModule = dir: path: accountName: | ||
61 | let | ||
62 | accountName' = splitString "@" accountName; | ||
63 | userName = elemAt accountName' 0; | ||
64 | in overrideModule (import "${toString dir}/${path}") (inputs: inputs // { inherit userName; }) (outputs: { _file = "${toString dir}/${path}"; } // outputs // { imports = [self.nixosModules.users.${userName}] ++ (outputs.imports or []); }); | ||
65 | |||
66 | forAllSystems = f: mapAttrs f nixpkgs.legacyPackages; | ||
67 | |||
68 | activateHomeManagerConfigurations = forAllSystems (system: _pkgs: mapAttrs' (configName: hmConfig: nameValuePair "${configName}-activate" { type = "app"; program = "${hmConfig.activationPackage}/bin/activate"; }) self.homeManagerConfigurations); | ||
69 | activateNixosConfigurations = forAllSystems (system: _pkgs: mapAttrs' (hostName: nixosConfig: nameValuePair "${hostName}-activate" { type = "app"; program = "${nixosConfig.config.system.build.toplevel}/bin/switch-to-configuration"; }) self.nixosConfigurations); | ||
70 | in | ||
71 | { | ||
72 | nixosModules = | ||
73 | let modulesAttrs = recImport { dir = ./modules; }; | ||
74 | systemProfiles = recImport rec { dir = ./system-profiles; _import = mkSystemProfile dir; }; | ||
75 | userProfiles = recImport rec { dir = ./user-profiles; }; | ||
76 | users = recImport rec { dir = ./users; _import = mkUserModule dir; }; | ||
77 | accounts = recImport rec { dir = ./accounts; _import = mkAccountModule dir; }; | ||
78 | in modulesAttrs // { inherit systemProfiles userProfiles users accounts; }; | ||
79 | nixosConfigurations = recImport rec { dir = ./hosts; _import = mkNixosConfiguration dir; }; | ||
80 | |||
81 | homeManagerConfigurations = listToAttrs (concatMap ({hostName, users}: mapAttrsToList (userName: homeConfig: nameValuePair "${userName}@${hostName}" homeConfig) users) (mapAttrsToList (hostName: nixosConfig: { inherit hostName; users = nixosConfig.config.home-manager.users; }) (self.nixosConfigurations))); | ||
82 | |||
83 | overlay = import ./pkgs; | ||
84 | overlays = recImport { dir = ./overlays; } // { pkgs = self.overlay; }; | ||
85 | |||
86 | packages = forAllSystems (system: systemPkgs: composeManyExtensions (attrValues self.overlays) (self.legacyPackages.${system}) systemPkgs); | ||
87 | |||
88 | legacyPackages = forAllSystems (system: systemPkgs: recursiveUpdate systemPkgs self.packages.${system}); | ||
89 | |||
90 | apps = recursiveUpdate activateNixosConfigurations activateHomeManagerConfigurations; | ||
91 | |||
92 | devShell = forAllSystems (system: systemPkgs: import ./shell.nix { pkgs = self.legacyPackages.${system}; }); | ||
93 | }; | ||
94 | } | ||
diff --git a/hosts/.keep b/hosts/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/hosts/.keep | |||
diff --git a/modules/.keep b/modules/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/modules/.keep | |||
diff --git a/overlays/.keep b/overlays/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/overlays/.keep | |||
diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 00000000..b5d83487 --- /dev/null +++ b/pkgs/default.nix | |||
@@ -0,0 +1,3 @@ | |||
1 | self: super: | ||
2 | { | ||
3 | } | ||
diff --git a/shell.nix b/shell.nix new file mode 100644 index 00000000..2820eb1a --- /dev/null +++ b/shell.nix | |||
@@ -0,0 +1,16 @@ | |||
1 | { pkgs ? import <nixpkgs> {} }: | ||
2 | let | ||
3 | nixWithFlakes = pkgs.symlinkJoin { | ||
4 | name = "nix-with-flakes"; | ||
5 | paths = [ pkgs.nixFlakes ]; | ||
6 | buildInputs = [ pkgs.makeWrapper ]; | ||
7 | postBuild = '' | ||
8 | wrapProgram $out/bin/nix --add-flags '--option experimental-features "nix-command flakes ca-references"' | ||
9 | ''; | ||
10 | }; | ||
11 | in pkgs.mkShell { | ||
12 | name = "nixos"; | ||
13 | nativeBuildInputs = with pkgs; [ | ||
14 | nixWithFlakes | ||
15 | ]; | ||
16 | } | ||
diff --git a/system-profiles/.keep b/system-profiles/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/system-profiles/.keep | |||
diff --git a/system-profiles/core.nix b/system-profiles/core.nix new file mode 100644 index 00000000..2af82703 --- /dev/null +++ b/system-profiles/core.nix | |||
@@ -0,0 +1,47 @@ | |||
1 | { flake, flakeInputs, path, hostName, config, lib, pkgs, customUtils, ... }: | ||
2 | let | ||
3 | profileSet = customUtils.types.attrNameSet flake.nixosModules.systemProfiles; | ||
4 | in { | ||
5 | options = { | ||
6 | # See mkSystemProfile in ../flake.nix | ||
7 | system.profiles = lib.mkOption { | ||
8 | type = profileSet; | ||
9 | default = []; | ||
10 | description = '' | ||
11 | Set (list without duplicates) of ‘systemProfiles’ enabled for this host | ||
12 | ''; | ||
13 | }; | ||
14 | }; | ||
15 | |||
16 | config = { | ||
17 | networking.hostName = hostName; | ||
18 | system.configurationRevision = lib.mkIf (flake ? rev) flake.rev; | ||
19 | |||
20 | nixpkgs.pkgs = flakeInputs.nixpkgs.legacyPackages.${config.nixpkgs.system}; | ||
21 | nixpkgs.overlays = lib.attrValues flake.overlays; | ||
22 | |||
23 | nix = { | ||
24 | package = pkgs.nixUnstable; | ||
25 | useSandbox = true; | ||
26 | allowedUsers = [ "@wheel" ]; | ||
27 | trustedUsers = [ "root" "@wheel" ]; | ||
28 | extraOptions = '' | ||
29 | experimental-features = nix-command flakes ca-references | ||
30 | ''; | ||
31 | nixPath = [ | ||
32 | "nixpkgs=${path}" | ||
33 | ]; | ||
34 | registry = { | ||
35 | nixpkgs.flake = flakeInputs.nixpkgs; | ||
36 | home-manager.flake = flakeInputs.home-manager; | ||
37 | machines.flake = flake; | ||
38 | }; | ||
39 | }; | ||
40 | |||
41 | users.mutableUsers = false; | ||
42 | |||
43 | # documentation.nixos.includeAllModules = true; # incompatible with home-manager (build fails) | ||
44 | |||
45 | home-manager.useGlobalPkgs = true; # Otherwise home-manager would only work impurely | ||
46 | }; | ||
47 | } | ||
diff --git a/user-profiles/.keep b/user-profiles/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/user-profiles/.keep | |||
diff --git a/users/.keep b/users/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/users/.keep | |||
diff --git a/utils/default.nix b/utils/default.nix new file mode 100644 index 00000000..d00357af --- /dev/null +++ b/utils/default.nix | |||
@@ -0,0 +1,57 @@ | |||
1 | { lib }: | ||
2 | rec { | ||
3 | inherit (builtins) readDir; | ||
4 | inherit (lib) filterAttrs hasSuffix removeSuffix mapAttrs' nameValuePair isFunction functionArgs setFunctionArgs id; | ||
5 | mapFilterAttrs = seive: f: attrs: filterAttrs seive (mapAttrs' f attrs); | ||
6 | recImport = { dir, _import ? name: _base: import "${toString dir}/${name}" }: | ||
7 | mapFilterAttrs | ||
8 | (_: v: v != null) | ||
9 | (n: v: | ||
10 | if n != "default.nix" && hasSuffix ".nix" n && v == "regular" | ||
11 | then | ||
12 | let name = removeSuffix ".nix" n; in nameValuePair (name) (_import n name) | ||
13 | else | ||
14 | if v == "directory" | ||
15 | then | ||
16 | nameValuePair n (_import n n) | ||
17 | else | ||
18 | nameValuePair ("") (null)) | ||
19 | (readDir dir); | ||
20 | |||
21 | types.attrNameSet = attr: | ||
22 | let | ||
23 | elemType = lib.types.enum (builtins.attrNames attr); | ||
24 | in lib.types.mkOptionType rec { | ||
25 | name = "attrNameSet"; | ||
26 | description = "set of names taken from an attribute set"; | ||
27 | check = lib.isList; | ||
28 | emptyValue = { value = {}; }; | ||
29 | getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); | ||
30 | getSubModules = elemType.getSubModules; | ||
31 | substSubModules = m: lib.types.listOf (elemType.substSubModules m); | ||
32 | functor = (lib.types.defaultFunctor name) // { wrapped = elemType; }; | ||
33 | merge = loc: defs: map (x: x.value) (lib.lists.filter (x: x ? value) (lib.lists.unique (lib.lists.concatLists (lib.lists.imap1 (n: def: | ||
34 | lib.lists.imap1 (m: def': | ||
35 | (lib.modules.mergeDefinitions | ||
36 | (loc ++ ["[definition ${toString n}-entry ${toString m}]"]) | ||
37 | elemType | ||
38 | [{ inherit (def) file; value = def'; }] | ||
39 | ).optionalValue | ||
40 | ) def.value | ||
41 | ) defs)))); | ||
42 | }; | ||
43 | |||
44 | overrideModuleArgs = | ||
45 | let | ||
46 | overrideModuleArgs = module: appOverride: if isFunction module then overrideModuleArgs' module appOverride else module; | ||
47 | overrideModuleArgs' = module: appOverride: setFunctionArgs (inputs: overrideModuleArgs (module (appOverride inputs)) id) (functionArgs module); | ||
48 | in overrideModuleArgs; | ||
49 | |||
50 | overrideModuleOutput = | ||
51 | let | ||
52 | overrideModuleOutput = module: appOverride: if isFunction module then overrideModuleOutput' module appOverride else appOverride module; | ||
53 | overrideModuleOutput' = module: appOverride: setFunctionArgs (inputs: overrideModuleOutput (module inputs) appOverride) (functionArgs module); | ||
54 | in overrideModuleOutput; | ||
55 | |||
56 | overrideModule = module: appInput: appOutput: overrideModuleOutput (overrideModuleArgs module appInput) appOutput; | ||
57 | } | ||