├── LICENSE ├── README.md ├── default.nix ├── eval-modules.nix ├── flake.nix ├── nix-patches ├── 2.16.2 │ └── evaluable-flake.patch ├── 2.19.2 │ └── evaluable-flake.patch └── evaluable-flake.patch └── templates ├── bare └── flake.nix └── example ├── configuration.nix ├── flake.nix └── hardware-configuration.nix /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Flafy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Combined Manager 2 | Combined Manager provides a new structure for personal NixOS configurations. 3 | ###### Note: Requires patching `nix` to solve [this issue](https://github.com/NixOS/nix/issues/3966). See more in the [Nix Patches section](#nix-patches). 4 | 5 | - [Introduction](#introduction-no-separation) 6 | - [Module options](#module-options) 7 | - [Examples](#examples) 8 | - [Full configurations](#full-configurations) 9 | - [Modules](#modules) 10 | - [Current limitations](#examples) 11 | - [Stability](#stability) 12 | - [Setup](#setup) 13 | - [Nix Patches](#nix-patches) 14 | - [evaluable-flake.patch](#required-evaluable-flakepatch-2-line-diff) 15 | - [FAQ](#faq) 16 | - [I want to get started, but don’t know how to patch Nix.](#i-want-to-get-started-but-dont-know-how-to-patch-nix) 17 | - [Why does Combined Manager need to evaluate inputs?](#why-does-combined-manager-need-to-evaluate-inputs) 18 | 19 | ## Introduction: No separation 20 | Combined Manager's main feature is to break separation. If you want, you should be able to keep everything in a single module. 21 | Most NixOS configuration structures are designed to separate related things into multiple files. 22 | 23 | Most prominent separations: 24 | - Dividing modules into system and home categories. These categories are then further maintained in separate files. 25 | - All flake inputs must be in the same file in flake.nix. 26 | 27 | Combined Manager breaks this pattern by allowing modules to add inputs, overlays and Home Manager and Nixpkgs options as if they are simple options. 28 | 29 | ## Module Options 30 | ```nix 31 | { 32 | lib, 33 | pkgs, 34 | config, 35 | osConfig, 36 | hmConfig, 37 | inputs, 38 | combinedManager, # Path to the root of combinedManager 39 | configs, # The results of all NixOS/CombinedManager configurations 40 | ... 41 | }: { 42 | imports = [ ]; 43 | 44 | options = { }; 45 | 46 | config = { 47 | # Adding inputs. 48 | inputs = { name.url = "..."; }; 49 | 50 | # Importing system modules. 51 | osModules = [ ]; 52 | 53 | # Importing Home Manager modules. 54 | hmModules = [ ]; 55 | 56 | # Setting overlays. 57 | os.nixpkgs.overlays = [ ]; 58 | 59 | # Using `os` to set Nixpkgs options. 60 | os = { }; 61 | 62 | # Set Home Manager username (Required to be set in at least one of the modules). 63 | hmUsername = "myname"; 64 | 65 | # Using `hm` to set Home Manager options. 66 | hm = { }; 67 | }; 68 | } 69 | ``` 70 | 71 | ## Examples 72 | #### Full configurations 73 | - https://github.com/FlafyDev/nixos-config 74 | #### Modules 75 | - https://github.com/FlafyDev/nixos-config/blob/main/modules/display/hyprland/default.nix 76 | 77 | 78 | ## Current limitations 79 | - Home Manager required and only a single user with Home Manager. 80 | - Nix must be patched. 81 | - Only for NixOS. 82 | 83 | ## Stability 84 | As of the time of writing, stable _enough_. 85 | While I'll use it for my configuraiton, I have not tested everything and cannot guarantee stability. 86 | There might be breaking changes. 87 | 88 | ## Setup 89 | 1. Patch Nix with the patches in the `nix-patches` directory. See more in the [Nix Patches section](#nix-patches). 90 | 2. Generate a template with `nix flake init -t github:FlafyDev/combined-manager#example`. 91 | 3. Run `nix flake metadata`. You might need to run it twice if there is no `flake.lock` file(A message will appear). 92 | 93 | ##### Running 94 | To bulid a VM: `nixos-rebuild build-vm --flake .#default`. 95 | To swtich: `sudo nixos-rebuild switch --flake .#default`. 96 | 97 | 98 | ## Nix Patches 99 | Combined Manager requires applying certain patches to Nix in order to work. 100 | Alternatively, you can use [Nix Super](https://forge.privatevoid.net/max/nix-super). 101 | 102 | #### Required: evaluable-flake.patch (2 line diff) 103 | This patch enables inputs(and the entire flake) to be evaluable. Solves [issue #3966](https://github.com/NixOS/nix/issues/3966). 104 | Combined Manager requires this since it evaluates `inputs` from all the modules. 105 | 106 | See [line 9 of the example flake](https://github.com/FlafyDev/combined-manager/blob/9474a2432b47c0e6fa0435eb612a32e28cbd99ea/templates/example/flake.nix#L9). 107 | 108 | ## FAQ 109 | 110 | #### I want to get started, but don't know how to patch Nix. 111 | You can add the following to your config: 112 | 113 | ```nix 114 | nix = { 115 | enable = true; 116 | package = let 117 | combinedManager = pkgs.fetchFromGitHub { 118 | owner = "flafydev"; 119 | repo = "combined-manager"; 120 | rev = "9474a2432b47c0e6fa0435eb612a32e28cbd99ea"; 121 | sha256 = ""; 122 | }; 123 | in 124 | pkgs.nix.overrideAttrs (old: { 125 | patches = 126 | (old.patches or []) 127 | ++ ( 128 | map 129 | (file: "${combinedManager}/nix-patches/${file}") 130 | (lib.attrNames (lib.filterAttrs (_: type: type == "regular") (builtins.readDir "${combinedManager}/nix-patches"))) 131 | ); 132 | }); 133 | }; 134 | ``` 135 | 136 | Once you start using Combined Manager, you'll be able to source the patches directly from your `combinedManager` module arg. 137 | 138 | #### Why does Combined Manager need to evaluate inputs? 139 | Each Combined Manager module has an `inputs` option. That option will eventually be merged and set as the inputs of the NixOS configuration. 140 | 141 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | let 2 | 3 | evalModules = import ./eval-modules.nix; 4 | 5 | getLib = {lockFile}: let 6 | inherit ((builtins.fromJSON (builtins.readFile lockFile))) nodes; 7 | nixpkgsLock = nodes.nixpkgs.locked; 8 | lib = import ((builtins.fetchTarball { 9 | url = "https://github.com/NixOS/nixpkgs/archive/${nixpkgsLock.rev}.tar.gz"; 10 | sha256 = nixpkgsLock.narHash; 11 | }) 12 | + "/lib"); 13 | libFixed = import ((builtins.fetchTarball { 14 | url = "https://github.com/nix-community/nixpkgs.lib/archive/4833b4eb30dfe3abad5a21775bc5460322c8d337.tar.gz"; 15 | sha256 = "sha256:1ppr46pf1glp7irxcr8w4fzfffgl34cnsb0dyy8mm8khw1bzbb5z"; 16 | }) 17 | + "/lib"); 18 | in 19 | if (builtins.pathExists lockFile && nodes ? nixpkgs) 20 | then lib 21 | else libFixed; 22 | # else builtins.trace "Inputs need to be evaluated again." null; 23 | 24 | evaluateConfigInputs = configuration: lib: let 25 | configuration' = builtins.removeAttrs configuration ["inputOverrides"]; 26 | in 27 | (evalModules (configuration' 28 | // { 29 | inputs = { 30 | nixpkgs = { 31 | inherit lib; 32 | }; 33 | }; 34 | })) 35 | .config 36 | .inputs; 37 | 38 | combinedManagerSystem = { 39 | inputs, 40 | configuration, 41 | }: let 42 | configuration' = (builtins.removeAttrs configuration ["inputOverrides"]) // {inputs = inputs // ((configuration.inputOverrides or (_: {})) inputs);}; 43 | inherit ((evalModules configuration').config) osModules; 44 | 45 | evaluated = evalModules (configuration' 46 | // { 47 | inherit osModules; 48 | }); 49 | in {inherit (evaluated) config;}; 50 | 51 | nixosSystem = args: let cmConfig = (combinedManagerSystem args).config; in {config = cmConfig.os // {inherit cmConfig;};}; 52 | 53 | mkFlake = { 54 | lockFile, 55 | description, 56 | initialInputs, 57 | configurations, 58 | outputs ? (_: {}), 59 | }: let 60 | lib = getLib {inherit lockFile;}; 61 | 62 | evaluatedInputs = 63 | lib.foldl 64 | ( 65 | allInputs: configInputs: 66 | # This foldAttrs is basically `allInputs // configInputs` but with an assertion. 67 | lib.foldlAttrs ( 68 | allInputs: inputName: inputValue: 69 | assert (!(builtins.elem inputName (builtins.attrNames allInputs) && allInputs.${inputName} != inputValue)) || throw "The input \"${inputName}\" appears more than once and equals to different values!\nFirst definition: ${builtins.toJSON inputValue}\nSecond definition: ${builtins.toJSON allInputs.${inputName}}"; 70 | allInputs // {${inputName} = inputValue;} 71 | ) 72 | allInputs 73 | configInputs 74 | ) {} 75 | (map (config: evaluateConfigInputs config lib) 76 | (builtins.attrValues configurations)); 77 | in 78 | assert builtins.elem "nixpkgs" (builtins.attrNames initialInputs) || throw "nixpkgs input not found in initialInputs" {}; 79 | assert ((builtins.any (config: config.useHomeManager or true) (builtins.attrValues configurations)) && (builtins.elem "home-manager" (builtins.attrNames initialInputs))) || throw "home-manager input not found in initialInputs" {}; { 80 | inherit description; 81 | inputs = evaluatedInputs // initialInputs; 82 | outputs = inputs: 83 | (outputs inputs) 84 | // { 85 | nixosConfigurations = let 86 | allConfigurations = builtins.mapAttrs (_host: config: config.config) ( 87 | (lib.mapAttrs (_name: config: 88 | combinedManagerSystem { 89 | configuration = config // {specialArgs = (config.specialArgs or {}) // {configs = allConfigurations;};}; 90 | inherit inputs; 91 | }) 92 | configurations) 93 | // (outputs inputs).nixosConfigurations or {} 94 | ); 95 | in 96 | (lib.mapAttrs (_name: config: 97 | nixosSystem { 98 | configuration = config // {specialArgs = (config.specialArgs or {}) // {configs = allConfigurations;};}; 99 | inherit inputs; 100 | }) 101 | configurations) 102 | // (outputs inputs).nixosConfigurations or {}; 103 | }; 104 | }; 105 | in {inherit mkFlake nixosSystem;} 106 | -------------------------------------------------------------------------------- /eval-modules.nix: -------------------------------------------------------------------------------- 1 | { 2 | modules ? [], 3 | inputs, 4 | system, 5 | useHomeManager ? true, 6 | specialArgs ? {}, 7 | osModules ? [], 8 | prefix ? [], 9 | }: let 10 | inherit (inputs.nixpkgs) lib; 11 | inherit (lib) mkOption types evalModules; 12 | osModule = let 13 | baseModules = import "${inputs.nixpkgs}/nixos/modules/module-list.nix"; 14 | in 15 | types.submoduleWith { 16 | description = "Nixpkgs modules"; 17 | specialArgs = { 18 | inherit baseModules; 19 | modulesPath = "${inputs.nixpkgs}/nixos/modules"; 20 | modules = osModules; # TODO: figure out if this is really what it should be equal to. 21 | }; 22 | modules = 23 | baseModules 24 | ++ osModules 25 | ++ [ 26 | {nixpkgs.system = system;} 27 | ]; 28 | }; 29 | in 30 | evalModules { 31 | inherit prefix; 32 | specialArgs = 33 | { 34 | inherit inputs; 35 | combinedManager = ./.; 36 | } 37 | // specialArgs; 38 | modules = 39 | [ 40 | ({lib, ...}: let 41 | self = inputs.nixpkgs; 42 | in { 43 | os.system.nixos.versionSuffix = ".${lib.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}.${self.shortRev or "dirty"}"; 44 | os.system.nixos.revision = lib.mkIf (self ? rev) self.rev; 45 | }) 46 | 47 | { 48 | options = { 49 | inputs = mkOption { 50 | type = with types; attrs; 51 | default = {}; 52 | description = "Inputs"; 53 | }; 54 | }; 55 | } 56 | 57 | # Combined Manager module 58 | ({ 59 | config, 60 | osConfig, 61 | ... 62 | }: { 63 | options.combinedManager = { 64 | osPassedArgs = lib.mkOption { 65 | type = lib.types.attrs; 66 | default = { 67 | osOptions = "options"; 68 | pkgs = "pkgs"; 69 | }; 70 | visible = "hidden"; 71 | }; 72 | osExtraPassedArgs = lib.mkOption { 73 | type = lib.types.attrs; 74 | default = {}; 75 | visible = "hidden"; 76 | }; 77 | }; 78 | 79 | config = { 80 | _module.args = 81 | config.os._combinedManager.args 82 | // { 83 | osConfig = config.os; 84 | }; 85 | os = let 86 | cmConfig = config; 87 | in 88 | {config, ...} @ args: { 89 | options = { 90 | _combinedManager.args = mkOption { 91 | type = types.attrs; 92 | default = {}; 93 | visible = "hidden"; 94 | }; 95 | }; 96 | config._combinedManager.args = 97 | lib.mapAttrs ( 98 | _name: value: config._module.args.${value} or args.${value} 99 | ) 100 | ( 101 | cmConfig.combinedManager.osExtraPassedArgs 102 | // cmConfig.combinedManager.osPassedArgs 103 | ); 104 | }; 105 | }; 106 | }) 107 | 108 | (_: { 109 | options = { 110 | os = lib.mkOption { 111 | type = osModule; 112 | default = {}; 113 | visible = "shallow"; 114 | description = '' 115 | Nixpkgs configuration. 116 | ''; 117 | }; 118 | 119 | osModules = mkOption { 120 | type = with types; listOf raw; 121 | default = []; 122 | description = "Top level system modules."; 123 | }; 124 | }; 125 | }) 126 | ] 127 | ++ ( 128 | lib.optional useHomeManager 129 | ({ 130 | options, 131 | config, 132 | osConfig, 133 | lib, 134 | ... 135 | }: { 136 | options = { 137 | hm = lib.mkOption { 138 | type = lib.types.deferredModule; 139 | default = {}; 140 | description = '' 141 | Home Manager configuration. 142 | ''; 143 | }; 144 | 145 | hmUsername = lib.mkOption { 146 | type = lib.types.str; 147 | default = "user"; 148 | description = '' 149 | Username used for hm. 150 | ''; 151 | }; 152 | 153 | hmModules = lib.mkOption { 154 | type = with types; listOf raw; 155 | default = []; 156 | description = "Home Manager modules."; 157 | }; 158 | }; 159 | 160 | config = { 161 | _module.args.hmConfig = osConfig.home-manager.users.${config.hmUsername}; 162 | osModules = [inputs.home-manager.nixosModules.home-manager]; 163 | os.home-manager = { 164 | useGlobalPkgs = true; 165 | useUserPackages = true; 166 | users.${config.hmUsername} = config.hm; 167 | sharedModules = config.hmModules; 168 | extraSpecialArgs = {inherit inputs;}; 169 | }; 170 | }; 171 | }) 172 | ) 173 | ++ modules; 174 | } 175 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Combined Manager"; 3 | 4 | outputs = _: { 5 | inherit (import ./.) nixosSystem evaluateInputs; 6 | 7 | templates = rec { 8 | bare = { 9 | path = ./templates/bare; 10 | description = "A bare nixos config using Combined Manager."; 11 | welcomeText = builtins.readFile ./README.md; 12 | }; 13 | example = { 14 | path = ./templates/example; 15 | description = "An example nixos config using Combined Manager."; 16 | welcomeText = builtins.readFile ./README.md; 17 | }; 18 | default = example; 19 | }; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /nix-patches/2.16.2/evaluable-flake.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc 2 | index 60bb6a7..13e517b 100644 3 | --- a/src/libexpr/flake/flake.cc 4 | +++ b/src/libexpr/flake/flake.cc 5 | @@ -74,7 +74,7 @@ static std::tuple fetchOrSubstituteTree( 6 | 7 | static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) 8 | { 9 | - if (value.isThunk() && value.isTrivial()) 10 | + if (value.isThunk()) // HACK: always forceValue, even if not trivial 11 | state.forceValue(value, pos); 12 | } 13 | 14 | @@ -222,7 +222,7 @@ static Flake getFlake( 15 | throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir); 16 | 17 | Value vInfo; 18 | - state.evalFile(CanonPath(flakeFile), vInfo, true); // FIXME: symlink attack 19 | + state.evalFile(CanonPath(flakeFile), vInfo, false); // FIXME: symlink attack 20 | 21 | expectType(state, nAttrs, vInfo, state.positions.add({CanonPath(flakeFile)}, 1, 1)); 22 | 23 | -------------------------------------------------------------------------------- /nix-patches/2.19.2/evaluable-flake.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc 2 | index 54de53e0b..66776f0f6 100644 3 | --- a/src/libexpr/flake/flake.cc 4 | +++ b/src/libexpr/flake/flake.cc 5 | @@ -77,7 +77,7 @@ static std::tuple fetchOrSubstituteTree( 6 | 7 | static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) 8 | { 9 | - if (value.isThunk() && value.isTrivial()) 10 | + if (value.isThunk()) // HACK: always forceValue, even if not trivial 11 | state.forceValue(value, pos); 12 | } 13 | 14 | @@ -230,7 +230,7 @@ static Flake getFlake( 15 | throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir); 16 | 17 | Value vInfo; 18 | - state.evalFile(state.rootPath(CanonPath(flakeFile)), vInfo, true); // FIXME: symlink attack 19 | + state.evalFile(state.rootPath(CanonPath(flakeFile)), vInfo, false); // FIXME: symlink attack 20 | 21 | expectType(state, nAttrs, vInfo, state.positions.add({state.rootPath(CanonPath(flakeFile))}, 1, 1)); 22 | 23 | -------------------------------------------------------------------------------- /nix-patches/evaluable-flake.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc 2 | index 60bb6a7..13e517b 100644 3 | --- a/src/libexpr/flake/flake.cc 4 | +++ b/src/libexpr/flake/flake.cc 5 | @@ -74,7 +74,7 @@ static std::tuple fetchOrSubstituteTree( 6 | 7 | static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) 8 | { 9 | - if (value.isThunk() && value.isTrivial()) 10 | + if (value.isThunk()) // HACK: always forceValue, even if not trivial 11 | state.forceValue(value, pos); 12 | } 13 | 14 | @@ -222,7 +222,7 @@ static Flake getFlake( 15 | throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir); 16 | 17 | Value vInfo; 18 | - state.evalFile(CanonPath(flakeFile), vInfo, true); // FIXME: symlink attack 19 | + state.evalFile(CanonPath(flakeFile), vInfo, false); // FIXME: symlink attack 20 | 21 | expectType(state, nAttrs, vInfo, state.positions.add({CanonPath(flakeFile)}, 1, 1)); 22 | 23 | -------------------------------------------------------------------------------- /templates/bare/flake.nix: -------------------------------------------------------------------------------- 1 | let 2 | combinedManager = import (builtins.fetchTarball { 3 | url = "https://github.com/flafydev/combined-manager/archive/71d2bc7553b59f69315328ba31531ffdc8c3ded2.tar.gz"; 4 | sha256 = "sha256:0dkjcy3xknncl4jv0abqhqspnk91hf6ridb5xb7da5f29xn60mnf"; 5 | }); 6 | in 7 | combinedManager.mkFlake { 8 | description = "NixOS configuration"; 9 | 10 | lockFile = ./flake.lock; 11 | 12 | initialInputs = { 13 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 14 | home-manager = { 15 | url = "github:nix-community/home-manager"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | }; 18 | }; 19 | 20 | configurations = {}; 21 | } 22 | -------------------------------------------------------------------------------- /templates/example/configuration.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | osConfig, 5 | hmConfig, 6 | inputs, 7 | ... 8 | }: { 9 | # Adding inputs 10 | inputs = { 11 | flake-utils.url = "github:numtide/flake-utils"; 12 | }; 13 | 14 | # Adding top level system modules 15 | osModules = [ 16 | ./hardware-configuration.nix 17 | ]; 18 | 19 | # Adding home modules 20 | hmModules = []; 21 | 22 | # Setting overlays 23 | os.nixpkgs.overlays = [ 24 | (_final: prev: { 25 | customCat = prev.bat; 26 | }) 27 | ]; 28 | 29 | # Using `os` to set Nixpkgs options. 30 | os = { 31 | users.users.root = { 32 | group = "root"; 33 | password = "root"; 34 | isSystemUser = true; 35 | }; 36 | users.users.a = { 37 | group = "a"; 38 | password = "a"; 39 | isNormalUser = true; 40 | }; 41 | users.mutableUsers = false; 42 | }; 43 | os.programs.vim.defaultEditor = false; 44 | os.environment.systemPackages = with pkgs; 45 | lib.mkIf (!osConfig.programs.vim.defaultEditor) [ 46 | customCat 47 | ]; 48 | 49 | # Set Home Manager username 50 | hmUsername = "a"; 51 | 52 | # Using `hm` to set Home Manager options. 53 | hm.xdg.configFile."somebody.txt".text = "once told me"; 54 | 55 | hm.home.stateVersion = "23.05"; 56 | os.system.stateVersion = "23.05"; 57 | } 58 | -------------------------------------------------------------------------------- /templates/example/flake.nix: -------------------------------------------------------------------------------- 1 | let 2 | combinedManager = import (builtins.fetchTarball { 3 | url = "https://github.com/flafydev/combined-manager/archive/71d2bc7553b59f69315328ba31531ffdc8c3ded2.tar.gz"; 4 | sha256 = "sha256:0dkjcy3xknncl4jv0abqhqspnk91hf6ridb5xb7da5f29xn60mnf"; 5 | }); 6 | in 7 | combinedManager.mkFlake { 8 | description = "NixOS configuration"; 9 | 10 | lockFile = ./flake.lock; 11 | 12 | initialInputs = { 13 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 14 | home-manager = { 15 | url = "github:nix-community/home-manager"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | }; 18 | }; 19 | 20 | configurations = { 21 | default = { 22 | system = "x86_64-linux"; 23 | modules = [./configuration.nix]; 24 | }; 25 | }; 26 | 27 | # Optional 28 | # outputs = _inputs: { }; 29 | } 30 | -------------------------------------------------------------------------------- /templates/example/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | modulesPath, 5 | ... 6 | }: { 7 | } 8 | --------------------------------------------------------------------------------