Merge pull request #264 from divnix/api-next

Implement new api and rebase on flake-utils-plus
This commit is contained in:
Pacman99 2021-04-27 16:55:13 -07:00 committed by GitHub
commit 62c9b126d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 948 additions and 593 deletions

View file

@ -1,45 +1,42 @@
# External Art # External Art
When you need to use a module, overlay, or pass a value from one of your inputs When you need to use a module, overlay, or pass a value from one of your inputs
to the rest of your NixOS configuration, [extern][extern] is where you do it. to the rest of your NixOS configuration, you can make use of a couple arguments.
It is encouraged to add external art directly in your `flake.nix` so the file
represents a complete dependency overview of your flake.
Modules and overlays are self explanatory, and the `specialArgs` attribute is ## Overlays
used to extend the arguments passed to all NixOS modules, allowing for External overlays can directly be added to a channel's `overlays` list.
arbitrary values to be passed from flake inputs to the rest of your
configuration.
## Home Manager
There is also an `hmModules` attribute set for pulling home-manager modules in
from the outside world:
### Declare:
flake.nix: flake.nix:
```nix ```nix
{ {
inputs.doom-emacs.url = "github:vlaci/nix-doom-emacs"; channels.nixos.overlays = [ inputs.agenix.overlay ];
} }
``` ```
These overlays will be automatically filtered by inspecting the `inputs` argument.
extern/default.nix: ## Modules
There is a dedicated `nixos.hostDefaults.externalModules` argument for external
modules.
flake.nix:
```nix ```nix
with inputs;
{ {
hmModules = { nixos.hostDefaults.externalModules = [ inputs.agenix.nixosModules.age ];
doom-emacs = doom-emacs.hmModule;
};
} }
``` ```
### Use: ## Home Manager
users/nixos/default.nix: Since there isn't a `hosts` concept for home-manager, externalModules is just a
top-level argument in the `home` namespace.
flake.nix:
```nix ```nix
{ hmModules, ... }:
{ {
home-manager.users.nixos = { home.externalModules = [ doom-emacs = doom-emacs.hmModule ];
imports = [ hmModules.doom-emacs ] ;
programs.doom-emacs.enable = true;
};
} }
``` ```
[extern]: https://github.com/divnix/devos/tree/core/extern/default.nix > ##### Note:
> The optimal solution would be to automatically export modules that were created in
> your flake. But this is not possible due to NixOS/nix#4740.

View file

@ -15,6 +15,11 @@ attribute to the name of the file minus the _.nix_ extension. This is for
convenience, since `nixos-rebuild` automatically searches for a configuration convenience, since `nixos-rebuild` automatically searches for a configuration
matching the current systems hostname if one is not specified explicitly. matching the current systems hostname if one is not specified explicitly.
You can set channels, systems, and add extra modules to each host by editing the
`nixos.hosts` argument in flake.nix. This is the perfect place to import
host specific modules from external sources, such as the
[nixos-hardware][nixos-hardware] repository.
It is recommended that the host modules only contain configuration information It is recommended that the host modules only contain configuration information
specific to a particular piece of hardware. Anything reusable across machines specific to a particular piece of hardware. Anything reusable across machines
is best saved for [profile modules](./profiles.md). is best saved for [profile modules](./profiles.md).
@ -22,20 +27,29 @@ is best saved for [profile modules](./profiles.md).
This is a good place to import sets of profiles, called [suites](./suites.md), This is a good place to import sets of profiles, called [suites](./suites.md),
that you intend to use on your machine. that you intend to use on your machine.
Additionally, this is the perfect place to import anything you might need from
the [nixos-hardware][nixos-hardware] repository.
> ##### _Note:_
> Set `nixpkgs.system` to the architecture of this host, default is "x86_64-linux".
> Keep in mind that not all packages are available for all architectures.
## Example ## Example
flake.nix:
```nix
{
nixos.hosts = mkMerge [
(devos.lib.importHosts ./hosts)
{
librem = {
channelName = "latest";
modules = [ hardware.purism-librem-13v3 ];
};
}
];
}
```
hosts/librem.nix: hosts/librem.nix:
```nix ```nix
{ suites, hardware, ... }: { suites, ... }:
{ {
imports = suites.laptop ++ [ hardware.purism-librem-13v3 ]; imports = suites.laptop;
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;

View file

@ -1,47 +1,36 @@
# Overrides # Overrides
By default, the NixOS systems are based on unstable. While it is trivial to Each NixOS host follows one channel. But many times it is useful to get packages
change this to a stable release, or any other branch of nixpkgs by or modules from different channels.
changing the flake url, sometimes all we want is a single package from another
branch.
This is what the overrides are for. By default, they are pulled directly from ## Packages
nixpkgs/master, but you can change the `override` flake input url to You can make use of `overlays/overrides.nix` to override specific packages in the
nixos-unstable, or even a specific sha revision. default channel to be pulled from other channels. That file is simply an example
of how any overlay can get `channels` as their first argument.
They are defined in the `extern/overrides.nix` file. You can add overlays to any channel to override packages from other channels.
## Example Pulling the manix package from the `latest` channel:
### Packages
The override packages are defined as a regular overlay with an extra arguement
`pkgs`. This refers to the packages built from the `override` flake.
Pulling the manix package from the override flake:
```nix ```nix
{ channels: final: prev: {
packages = pkgs: final: prev: { inherit (pkgs.latest) manix;
inherit (pkgs) manix;
};
} }
``` ```
### Modules ## Modules
You can also pull modules from override. Simply specify their path relative to You can also pull modules from other channels. All modules have access to the
the nixpkgs [modules][nixpkgs-modules] directory. The old version will be added `modulesPath` for each channel as `<channelName>ModulesPath`. And you can use
to `disabledModules` and the new version imported into the configuration. `disabledModules` to remove modules from the current channel.
Pulling the zsh module from the override flake: Pulling the zsh module from the `latest` channel:
```nix ```nix
{ { latestModulesPath }: {
modules = [ "programs/zsh/zsh.nix" ]; modules = [ "${latestModulesPath}/programs/zsh/zsh.nix" ];
disabledModules = [ "programs/zsh/zsh.nix" ];
} }
``` ```
> ##### _Note:_ > ##### _Note:_
> Sometimes a modules name will change from one branch to another. This is what > Sometimes a modules name will change from one branch to another.
> the `disabledModules` list is for. If the module name changes, the old
> version will not automatically be disabled, so simply put it's old name in
> this list to disable it.
[nixpkgs-modules]: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules [nixpkgs-modules]: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules

View file

@ -6,7 +6,13 @@ profiles. For good examples, check out the suites defined in the community
In the future, we will use suites as a mechanism for deploying various machine In the future, we will use suites as a mechanism for deploying various machine
types which don't depend on hardware, such as vm's and containers. types which don't depend on hardware, such as vm's and containers.
They are defined in `profiles/suites.nix`. They are defined with the `suites` argument in either `home` or `nixos` namespace.
Suites should be passed as a function that take profiles as an argument.
The profiles are passed based on the folder names and list passed to the relevant
`profiles` argument. In the template's flake.nix `profiles` is set as
`[ ./profiles ./users ]` and that corresponds to the `{ profiles, users }` argument
pattern.
## Definition ## Definition
```nix ```nix

407
doc/mkFlakeOptions.md Normal file
View file

@ -0,0 +1,407 @@
## channels
nixpkgs channels to create
*_Type_*:
attribute set of submodules
*_Default_*
```
{}
```
## channels.\<name\>.config
nixpkgs config for this channel
*_Type_*:
attribute set or path convertible to it
*_Default_*
```
{}
```
## channels.\<name\>.input
nixpkgs flake input to use for this channel
*_Type_*:
nix flake
*_Default_*
```
"inputs.<name>"
```
## channels.\<name\>.overlays
overlays to apply to this channel
these will get exported under the 'overlays' flake output
as \<channel\>/\<name\> and any overlay pulled from ${inputs}
will be filtered out
*_Type_*:
list of valid Nixpkgs overlay or path convertible to its or anything convertible to it
*_Default_*
```
[]
```
## channelsConfig
nixpkgs config for all channels
*_Type_*:
attribute set or path convertible to it
*_Default_*
```
{}
```
## home
hosts, modules, suites, and profiles for home-manager
*_Type_*:
submodule
*_Default_*
```
{}
```
## home.externalModules
modules to include that won't be exported
meant importing modules from external flakes
*_Type_*:
list of valid module or path convertible to its
*_Default_*
```
[]
```
## home.modules
modules to include in all hosts and export to homeModules output
*_Type_*:
list of path to a modules or anything convertible to it or path convertible to it
*_Default_*
```
[]
```
## home.profiles
profile folders that can be collected into suites
the name of the argument passed to suites is based
on the folder name.
[ ./profiles ] => { profiles }:
*_Type_*:
list of paths
*_Default_*
```
[]
```
## home.suites
Function that takes profiles and returns suites for this config system
These can be accessed through the 'suites' special argument.
*_Type_*:
function that evaluates to a(n) attrs or path convertible to it
*_Default_*
```
"<function>"
```
## inputs
inputs for this flake
used to set channel defaults and create registry
*_Type_*:
attribute set of nix flakes
## nixos
hosts, modules, suites, and profiles for nixos
*_Type_*:
submodule
*_Default_*
```
{}
```
## nixos.hostDefaults
Defaults for all hosts.
the modules passed under hostDefaults will be exported
to the 'nixosModules' flake output.
They will also be added to all hosts.
*_Type_*:
submodule
*_Default_*
```
{}
```
## nixos.hostDefaults.channelName
Channel this host should follow
*_Type_*:
a channel defined in `channels`
*_Default_*
```
null
```
## nixos.hostDefaults.externalModules
modules to include that won't be exported
meant importing modules from external flakes
*_Type_*:
list of valid module or path convertible to its
*_Default_*
```
[]
```
## nixos.hostDefaults.modules
modules to include in all hosts and export to nixosModules output
*_Type_*:
list of path to a modules or anything convertible to it or path convertible to it
*_Default_*
```
[]
```
## nixos.hostDefaults.system
system for this host
*_Type_*:
system defined in `supportedSystems`
*_Default_*
```
null
```
## nixos.hosts
configurations to include in the nixosConfigurations output
*_Type_*:
attribute set of submodules
*_Default_*
```
{}
```
## nixos.hosts.\<name\>.channelName
Channel this host should follow
*_Type_*:
a channel defined in `channels`
*_Default_*
```
null
```
## nixos.hosts.\<name\>.modules
modules to include
*_Type_*:
list of valid module or path convertible to its or anything convertible to it
*_Default_*
```
[]
```
## nixos.hosts.\<name\>.system
system for this host
*_Type_*:
system defined in `supportedSystems`
*_Default_*
```
null
```
## nixos.profiles
profile folders that can be collected into suites
the name of the argument passed to suites is based
on the folder name.
[ ./profiles ] => { profiles }:
*_Type_*:
list of paths
*_Default_*
```
[]
```
## nixos.suites
Function that takes profiles and returns suites for this config system
These can be accessed through the 'suites' special argument.
*_Type_*:
function that evaluates to a(n) attrs or path convertible to it
*_Default_*
```
"<function>"
```
## self
The flake to create the devos outputs for
*_Type_*:
nix flake
## supportedSystems
The systems supported by this flake
*_Type_*:
list of strings
*_Default_*
```
["aarch64-linux","i686-linux","x86_64-darwin","x86_64-linux"]
```

View file

@ -4,7 +4,7 @@ we want to keep the process as simple and straightforward as possible.
Any _.nix_ files declared in this directory will be assumed to be a valid Any _.nix_ files declared in this directory will be assumed to be a valid
overlay, and will be automatically imported into all [hosts](../concepts/hosts.md), and overlay, and will be automatically imported into all [hosts](../concepts/hosts.md), and
exported via `overlays.<file-basename>` _as well as_ exported via `overlays.<channel>/<pkgName>` _as well as_
`packages.<system>.<pkgName>` (for valid systems), so all you have to do is `packages.<system>.<pkgName>` (for valid systems), so all you have to do is
write it. write it.

View file

@ -10,10 +10,18 @@ flk up
This will make a new file `hosts/up-$(hostname).nix`, which you can edit to This will make a new file `hosts/up-$(hostname).nix`, which you can edit to
your liking. your liking.
You must then add a host to `nixos.hosts` in flake.nix:
```nix
{
nixos.hosts = {
modules = hosts/NixOS.nix;
};
}
```
Make sure your `i18n.defaultLocale` and `time.timeZone` are set properly for Make sure your `i18n.defaultLocale` and `time.timeZone` are set properly for
your region. Keep in mind that `networking.hostName` with be automatically your region. Keep in mind that `networking.hostName` with be automatically
set to the filename of your hosts file, so `hosts/my-host.nix` will have the set to the name of your host;
hostname `my-host`.
Now might be a good time to read the docs on [suites](../concepts/suites.md) and Now might be a good time to read the docs on [suites](../concepts/suites.md) and
[profiles](../concepts/profiles.md) and add or create any that you need. [profiles](../concepts/profiles.md) and add or create any that you need.

View file

@ -7,7 +7,7 @@ configuration, and, optionally, run them in
## Lib Tests ## Lib Tests
You can easily write tests for your own library functions in the You can easily write tests for your own library functions in the
___tests/lib.nix___ file and they will be run on every `nix flake check` or lib/___tests/lib.nix___ file and they will be run on every `nix flake check` or
during a CI run. during a CI run.
## Unit Tests ## Unit Tests

25
extern/default.nix vendored
View file

@ -1,25 +0,0 @@
{ inputs }: with inputs;
{
modules = [
home.nixosModules.home-manager
ci-agent.nixosModules.agent-profile
];
overlays = [
nur.overlay
pkgs.overlay
];
# passed to all nixos modules
specialArgs = {
overrideModulesPath = "${override}/nixos/modules";
hardware = nixos-hardware.nixosModules;
};
# added to home-manager
userModules = [
];
# passed to all home-manager modules
userSpecialArgs = { };
}

33
extern/overrides.nix vendored
View file

@ -1,33 +0,0 @@
# override defaults to nixpkgs/master
{
# modules to pull from override, stable version is automatically disabled
modules = [ ];
# if a modules name changed in override, add the old name here
disabledModules = [ ];
# packages pulled from override
packages = pkgs: final: prev: {
inherit (pkgs)
cachix
dhall
discord
element-desktop
manix
nixpkgs-fmt
qutebrowser
signal-desktop
starship;
haskellPackages = prev.haskellPackages.override {
overrides = hfinal: hprev:
let version = prev.lib.replaceChars [ "." ] [ "" ] prev.ghc.version;
in
{
# same for haskell packages, matching ghc versions
inherit (pkgs.haskell.packages."ghc${version}")
haskell-language-server;
};
};
};
}

View file

@ -12,7 +12,7 @@
"nixos" "nixos"
], ],
"nixos-unstable": [ "nixos-unstable": [
"override" "latest"
], ],
"pre-commit-hooks-nix": "pre-commit-hooks-nix" "pre-commit-hooks-nix": "pre-commit-hooks-nix"
}, },
@ -33,7 +33,7 @@
"darwin": { "darwin": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"override" "latest"
] ]
}, },
"locked": { "locked": {
@ -81,7 +81,7 @@
"utils": "utils_2" "utils": "utils_2"
}, },
"locked": { "locked": {
"narHash": "sha256-t14TKUtw83dZ2mbqjRpeUvdAx4zpe/ySr5KhPhB1JMU=", "narHash": "sha256-hpvEXcpq85cDKi0F5UUsuMVISKlk8hgVJiz5FF29RwA=",
"path": "./lib", "path": "./lib",
"type": "path" "type": "path"
}, },
@ -138,6 +138,21 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"locked": {
"lastModified": 1619345332,
"narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home": { "home": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -158,10 +173,24 @@
"type": "github" "type": "github"
} }
}, },
"latest": {
"locked": {
"lastModified": 1619400530,
"narHash": "sha256-7ZO7B+b9i1wFbHw62EFT+iwuBBpXeA/fcHlR63Z4J0w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e8dc8adab655eb27957859c62bef11484b53f639",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"naersk": { "naersk": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"override" "latest"
] ]
}, },
"locked": { "locked": {
@ -182,7 +211,7 @@
"naersk_2": { "naersk_2": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"override" "latest"
] ]
}, },
"locked": { "locked": {
@ -259,20 +288,6 @@
"type": "indirect" "type": "indirect"
} }
}, },
"override": {
"locked": {
"lastModified": 1615926763,
"narHash": "sha256-yeq8A3EPNuQVlsxlEQrIRsklfJwJK0Us6jtcG/u8wNs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b702a56d417647de4090ac56c0f18bdc7e646610",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"pkgs": { "pkgs": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -312,11 +327,11 @@
"devos": "devos", "devos": "devos",
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_2",
"home": "home", "home": "home",
"latest": "latest",
"naersk": "naersk_2", "naersk": "naersk_2",
"nixos": "nixos", "nixos": "nixos",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nur": "nur", "nur": "nur",
"override": "override",
"pkgs": "pkgs" "pkgs": "pkgs"
} }
}, },
@ -336,17 +351,21 @@
} }
}, },
"utils_2": { "utils_2": {
"inputs": {
"flake-utils": "flake-utils"
},
"locked": { "locked": {
"lastModified": 1618868421, "lastModified": 1619532520,
"narHash": "sha256-vyoJhLV6cJ8/tWz+l9HZLIkb9Rd9esE7p+0RL6zDR6Y=", "narHash": "sha256-+xIFAW5J0AcxwAflAX1gg/C8kfaqeZbS4XAZusCrZPY=",
"owner": "numtide", "owner": "gytis-ivaskevicius",
"repo": "flake-utils", "repo": "flake-utils-plus",
"rev": "eed214942bcfb3a8cc09eb3b28ca7d7221e44a94", "rev": "8eb7f9206713a528174c20c5133521dc37e2bfb1",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "numtide", "owner": "gytis-ivaskevicius",
"repo": "flake-utils", "ref": "staging",
"repo": "flake-utils-plus",
"type": "github" "type": "github"
} }
} }

View file

@ -4,7 +4,7 @@
inputs = inputs =
{ {
nixos.url = "nixpkgs/nixos-unstable"; nixos.url = "nixpkgs/nixos-unstable";
override.url = "nixpkgs"; latest.url = "nixpkgs";
devos.url = "path:./lib"; # TODO: outfactor into separate repo devos.url = "path:./lib"; # TODO: outfactor into separate repo
devos.inputs = { devos.inputs = {
nixpkgs.follows = "nixos"; nixpkgs.follows = "nixos";
@ -17,38 +17,71 @@
ci-agent = { ci-agent = {
url = "github:hercules-ci/hercules-ci-agent"; url = "github:hercules-ci/hercules-ci-agent";
inputs = { nix-darwin.follows = "darwin"; flake-compat.follows = "flake-compat"; nixos-20_09.follows = "nixos"; nixos-unstable.follows = "override"; }; inputs = { nix-darwin.follows = "darwin"; flake-compat.follows = "flake-compat"; nixos-20_09.follows = "nixos"; nixos-unstable.follows = "latest"; };
}; };
darwin.url = "github:LnL7/nix-darwin"; darwin.url = "github:LnL7/nix-darwin";
darwin.inputs.nixpkgs.follows = "override"; darwin.inputs.nixpkgs.follows = "latest";
flake-compat.url = "github:BBBSnowball/flake-compat/pr-1";
flake-compat.flake = false;
home.url = "github:nix-community/home-manager"; home.url = "github:nix-community/home-manager";
home.inputs.nixpkgs.follows = "nixos"; home.inputs.nixpkgs.follows = "nixos";
naersk.url = "github:nmattia/naersk"; naersk.url = "github:nmattia/naersk";
naersk.inputs.nixpkgs.follows = "override"; naersk.inputs.nixpkgs.follows = "latest";
nixos-hardware.url = "github:nixos/nixos-hardware"; nixos-hardware.url = "github:nixos/nixos-hardware";
pkgs.url = "path:./pkgs"; pkgs.url = "path:./pkgs";
pkgs.inputs.nixpkgs.follows = "nixos"; pkgs.inputs.nixpkgs.follows = "nixos";
}; };
outputs = inputs@{ self, devos, nixos, nur, ... }: outputs = inputs@{ self, pkgs, devos, nixos, ci-agent, home, nixos-hardware, nur, ... }:
devos.lib.mkFlake { devos.lib.mkFlake {
inherit self inputs nixos; inherit self inputs;
hosts = ./hosts;
packages = import ./pkgs; channelsConfig = { allowUnfree = true; };
suites = import ./profiles/suites.nix;
extern = import ./extern; channels = {
overrides = import ./extern/overrides.nix; nixos = {
overlays = ./overlays; overlays = [
profiles = ./profiles; (devos.lib.pathsIn ./overlays)
userProfiles = ./users/profiles; ./pkgs/default.nix
modules = import ./modules/module-list.nix; pkgs.overlay # for `srcs`
userModules = import ./users/modules/module-list.nix; nur.overlay
} // { ];
defaultTemplate = self.templates.flk; };
latest = { };
};
nixos = {
hostDefaults = {
system = "x86_64-linux";
channelName = "nixos";
modules = ./modules/module-list.nix;
externalModules = [
ci-agent.nixosModules.agent-profile
home.nixosModules.home-manager
];
};
hosts = nixos.lib.mkMerge [
(devos.lib.importHosts ./hosts)
{ /* set host specific properties here */ }
];
profiles = [ ./profiles ./users ];
suites = { profiles, users, ... }: with profiles; {
base = [ cachix core users.nixos users.root ];
};
};
home = {
modules = ./users/modules/module-list.nix;
externalModules = [ ];
profiles = [ ./users/profiles ];
suites = { profiles, ... }: with profiles; {
base = [ direnv git ];
};
};
#defaultTemplate = self.templates.flk;
templates.flk.path = ./.; templates.flk.path = ./.;
templates.flk.description = "flk template"; templates.flk.description = "flk template";
};
}
;
} }

View file

@ -30,6 +30,14 @@ rec {
value = import path; value = import path;
}); });
importHosts = dir:
lib.os.recImport {
inherit dir;
_import = base: {
modules = import "${toString dir}/${base}.nix";
};
};
concatAttrs = lib.fold (attr: sum: lib.recursiveUpdate sum attr) { }; concatAttrs = lib.fold (attr: sum: lib.recursiveUpdate sum attr) { };
# Filter out packages that support given system and follow flake check requirements # Filter out packages that support given system and follow flake check requirements
@ -41,5 +49,6 @@ rec {
in in
lib.filterAttrs filter packages; lib.filterAttrs filter packages;
safeReadDir = path: lib.optionalAttrs (builtins.pathExists path) (builtins.readDir path); safeReadDir = path:
lib.optionalAttrs (builtins.pathExists (toString path)) (builtins.readDir (toString path));
} }

View file

@ -1,12 +1,10 @@
let let
inherit (lock.nodes.flake-compat.locked) rev narHash; rev = "e7e5d481a0e15dcd459396e55327749989e04ce0";
lock = builtins.fromJSON (builtins.readFile "${../..}/flake.lock");
flake = (import flake = (import
( (
fetchTarball { fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${rev}.tar.gz"; url = "https://github.com/edolstra/flake-compat/archive/${rev}.tar.gz";
sha256 = narHash; sha256 = "0zd3x46fswh5n6faq4x2kkpy6p3c6j593xbdlbsl40ppkclwc80x";
} }
) )
{ {

View file

@ -1,31 +1,40 @@
{ lib }: { lib }:
{ self, nixos, inputs, modules, ... } @ allArgs: # dependencies to return a builder
let args = builtins.removeAttrs allArgs [ "self" "nixos" "inputs" ]; in { self, inputs }:
lib.nixosSystem (args // {
{ modules, specialArgs, ... } @ args:
let inherit (specialArgs.channel.input.lib) nixosSystem; in
nixosSystem
(args // {
modules = modules =
let let
moduleList = builtins.attrValues modules; fullHostConfig = (nixosSystem (args // { inherit modules; })).config;
fullHostConfig = (lib.nixosSystem (args // { modules = moduleList; })).config; isoConfig = (nixosSystem
isoConfig = (lib.nixosSystem
(args // { (args // {
modules = moduleList ++ [ modules = modules ++ [
(lib.modules.iso { inherit self nixos inputs fullHostConfig; }) (lib.modules.iso { inherit self inputs fullHostConfig; })
]; ];
})).config; })).config;
hmConfig = (lib.nixosSystem
hmConfig = (nixosSystem
(args // { (args // {
modules = moduleList ++ [ modules = modules ++ [
(lib.modules.hmConfig) (lib.modules.hmConfig)
]; ];
})).config; })).config;
in in
moduleList ++ [{ modules ++ [{
system.build = { system.build = {
iso = isoConfig.system.build.isoImage; iso = isoConfig.system.build.isoImage;
homes = hmConfig.home-manager.users; homes = hmConfig.home-manager.users;
}; };
lib = {
inherit specialArgs;
testModule = {
imports = modules;
};
};
}]; }];
}) })

View file

@ -1,20 +1,20 @@
{ lib }: { lib }:
{ users, profiles, userProfiles, suites } @ args: { suites, profiles } @ args:
let let
inherit (lib) os; inherit (lib) os;
definedSuites = suites { profileSet = lib.genAttrs' profiles (path: {
inherit (args) users profiles userProfiles; name = baseNameOf path;
}; value = os.mkProfileAttrs (toString path);
});
allProfiles = lib.collectProfiles profiles; definedSuites = suites profileSet;
allUsers = lib.collectProfiles users;
createSuites = _: suites: lib.mapAttrs (_: v: os.profileMap v) suites // {
inherit allProfiles allUsers;
};
allProfiles = lib.collectProfiles profileSet;
in in
lib.mapAttrs createSuites definedSuites lib.mapAttrs (_: v: os.profileMap v) definedSuites // {
inherit allProfiles;
}

View file

@ -52,6 +52,21 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"locked": {
"lastModified": 1619345332,
"narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"naersk": { "naersk": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -127,17 +142,21 @@
} }
}, },
"utils_2": { "utils_2": {
"inputs": {
"flake-utils": "flake-utils"
},
"locked": { "locked": {
"lastModified": 1618868421, "lastModified": 1619532520,
"narHash": "sha256-vyoJhLV6cJ8/tWz+l9HZLIkb9Rd9esE7p+0RL6zDR6Y=", "narHash": "sha256-+xIFAW5J0AcxwAflAX1gg/C8kfaqeZbS4XAZusCrZPY=",
"owner": "numtide", "owner": "gytis-ivaskevicius",
"repo": "flake-utils", "repo": "flake-utils-plus",
"rev": "eed214942bcfb3a8cc09eb3b28ca7d7221e44a94", "rev": "8eb7f9206713a528174c20c5133521dc37e2bfb1",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "numtide", "owner": "gytis-ivaskevicius",
"repo": "flake-utils", "ref": "staging",
"repo": "flake-utils-plus",
"type": "github" "type": "github"
} }
} }

View file

@ -5,7 +5,7 @@
{ {
deploy.url = "github:serokell/deploy-rs"; deploy.url = "github:serokell/deploy-rs";
devshell.url = "github:numtide/devshell"; devshell.url = "github:numtide/devshell";
utils.url = "github:numtide/flake-utils"; utils.url = "github:gytis-ivaskevicius/flake-utils-plus/staging";
}; };
outputs = inputs@{ self, nixpkgs, deploy, devshell, utils, ... }: outputs = inputs@{ self, nixpkgs, deploy, devshell, utils, ... }:
@ -35,12 +35,11 @@
inherit deploy; inherit deploy;
}; };
evalArgs = import ./mkFlake/evalArgs.nix { lib = nixpkgs.lib // self; }; evalArgs = import ./mkFlake/evalArgs.nix { lib = nixpkgs.lib // self; };
evalOldArgs = import ./mkFlake/evalOldArgs.nix { lib = nixpkgs.lib // self; };
}; };
pkgs-lib = import ./pkgs-lib { pkgs-lib = import ./pkgs-lib {
lib = nixpkgs.lib // self; lib = nixpkgs.lib // self;
inherit nixpkgs deploy devshell; inherit deploy devshell;
}; };
inherit (attrs) inherit (attrs)
@ -49,8 +48,9 @@
safeReadDir safeReadDir
pathsToImportedAttrs pathsToImportedAttrs
concatAttrs concatAttrs
filterPackages; filterPackages
inherit (lists) pathsIn collectProfiles; importHosts;
inherit (lists) pathsIn collectProfiles unifyOverlays;
inherit (strings) rgxToString; inherit (strings) rgxToString;
inherit modules; inherit modules;
} }
@ -61,7 +61,7 @@
{ {
lib = utils.lib // { lib = utils.lib // {
inherit (lib) inherit (lib)
mkFlake; mkFlake pathsIn importHosts;
}; };
} }
@ -83,7 +83,7 @@
mkFlakeDoc = pkgs.writeText "mkFlakeOptions.md" mkFlakeDoc = pkgs.writeText "mkFlakeOptions.md"
( (
pkgs.nixosOptionsDoc { pkgs.nixosOptionsDoc {
inherit (lib.mkFlake.evalArgs { nixos = "nixos"; args = { }; }) options; inherit (lib.mkFlake.evalArgs { args = { }; }) options;
} }
).optionsMDDoc; ).optionsMDDoc;
}; };

View file

@ -16,4 +16,6 @@
fullPath = name: "${toString dir}/${name}"; fullPath = name: "${toString dir}/${name}";
in in
map fullPath (lib.attrNames (lib.safeReadDir dir)); map fullPath (lib.attrNames (lib.safeReadDir dir));
unifyOverlays = channels: map (o: if builtins.isFunction (o null null) then o channels else o);
} }

View file

@ -1,64 +1,94 @@
{ lib, deploy }: { lib, deploy }:
let let
inherit (lib) os; inherit (lib) os;
inherit (builtins) mapAttrs attrNames attrValues head isFunction;
in in
_: { self, inputs, nixos, ... } @ args: _: { self, inputs, ... } @ args:
let let
cfg = ( config = lib.mkFlake.evalArgs {
lib.mkFlake.evalOldArgs inherit args;
{ inherit self inputs args; }
).config;
multiPkgs = os.mkPkgs
{
inherit self inputs nixos;
inherit (cfg) extern overrides;
}; };
outputs = { cfg = config.config;
nixosConfigurations = os.mkHosts
otherArguments = removeAttrs args (attrNames config.options);
defaultModules = with lib.modules; [
(hmDefaults {
inherit (cfg.home) suites;
modules = cfg.home.modules ++ cfg.home.externalModules;
})
(globalDefaults {
inherit self inputs;
})
];
stripChannel = channel: removeAttrs channel [
# arguments in our channels api that shouldn't be passed to fup
"overlays"
];
getDefaultChannel = channels: channels.${cfg.nixos.hostDefaults.channelName};
# evalArgs sets channelName and system to null by default
# but for proper default handling in fup, null args have to be removed
stripHost = args: removeAttrs (lib.filterAttrs (_: arg: arg != null) args) [
# arguments in our hosts/hostDefaults api that shouldn't be passed to fup
"externalModules"
];
hosts = lib.mapAttrs (_: stripHost) cfg.nixos.hosts;
hostDefaults = stripHost cfg.nixos.hostDefaults;
in
lib.systemFlake (lib.recursiveUpdate
otherArguments
{ {
inherit self inputs nixos multiPkgs; inherit self inputs hosts;
inherit (cfg) extern suites overrides; inherit (cfg) channelsConfig supportedSystems;
dir = cfg.hosts;
channels = mapAttrs
(name: channel:
stripChannel (channel // {
# pass channels if "overlay" has three arguments
overlaysBuilder = channels: lib.unifyOverlays channels channel.overlays;
})
)
cfg.channels;
hostDefaults = lib.mergeAny hostDefaults {
specialArgs.suites = cfg.nixos.suites;
modules = cfg.nixos.hostDefaults.externalModules ++ defaultModules;
builder = os.devosSystem { inherit self inputs; };
}; };
nixosModules = lib.exporter.modulesFromList cfg.nixos.hostDefaults.modules;
homeModules = lib.exporter.modulesFromList cfg.home.modules;
homeConfigurations = os.mkHomeConfigurations self.nixosConfigurations; homeConfigurations = os.mkHomeConfigurations self.nixosConfigurations;
nixosModules = cfg.modules;
homeModules = cfg.userModules;
overlay = cfg.packages;
inherit (cfg) overlays;
deploy.nodes = os.mkNodes deploy self.nixosConfigurations; deploy.nodes = os.mkNodes deploy self.nixosConfigurations;
overlays = lib.exporter.overlaysFromChannelsExporter {
# since we can't detect overlays owned by self
# we have to filter out ones exported by the inputs
# optimally we would want a solution for NixOS/nix#4740
inherit inputs;
inherit (self) pkgs;
}; };
systemOutputs = lib.eachDefaultSystem (system: packagesBuilder = lib.builder.packagesFromOverlaysBuilderConstructor self.overlays;
let
pkgs = multiPkgs.${system}; checksBuilder = channels:
pkgs-lib = lib.pkgs-lib.${system}; lib.pkgs-lib.tests.mkChecks {
# all packages that are defined in ./pkgs pkgs = getDefaultChannel channels;
legacyPackages = os.mkPackages {
inherit pkgs;
inherit (self) overlay overlays;
};
in
{
checks = pkgs-lib.tests.mkChecks {
inherit (self.deploy) nodes; inherit (self.deploy) nodes;
hosts = self.nixosConfigurations; hosts = self.nixosConfigurations;
homes = self.homeConfigurations; homes = self.homeConfigurations;
}; };
inherit legacyPackages; devShellBuilder = channels:
packages = lib.filterPackages system legacyPackages; lib.pkgs-lib.shell {
pkgs = getDefaultChannel channels;
devShell = pkgs-lib.shell; };
}); }
in )
outputs // systemOutputs

View file

@ -1,11 +1,12 @@
{ lib }: { lib }:
{ nixos, args }: { args }:
let let
argOpts = with lib; { config, ... }: argOpts = with lib; { config, ... }:
let let
inherit (lib) os; inherit (lib) os;
cfg = config;
inherit (config) self; inherit (config) self;
maybeImport = obj: maybeImport = obj:
@ -20,6 +21,12 @@ let
inherit (submodule { }) check; inherit (submodule { }) check;
description = "valid module"; description = "valid module";
}); });
# to export modules we need paths to get the name
exportModuleType = with types;
(addCheck path (x: moduleType.check (import x))) // {
description = "path to a module";
};
overlayType = pathTo (types.anything // { overlayType = pathTo (types.anything // {
check = builtins.isFunction; check = builtins.isFunction;
description = "valid Nixpkgs overlay"; description = "valid Nixpkgs overlay";
@ -33,46 +40,37 @@ let
# To simplify apply keys and improve type checking # To simplify apply keys and improve type checking
pathTo = elemType: with types; coercedTo path maybeImport elemType; pathTo = elemType: with types; coercedTo path maybeImport elemType;
# Accepts single item or a list pathToListOf = elemType: with types; pathTo (listOf elemType);
# apply keys end up with a list
# This should not be used if expecting a nested list
# all lists will get flattened by this
coercedListOf = elemType:
let coerceToList = x: flatten (singleton x); in
with types; coercedTo elemType coerceToList (listOf elemType);
pathToListOf = x: pathTo (coercedListOf x); coercedListOf = elemType: with types;
coercedTo anything (x: flatten (singleton x)) (listOf elemType);
/* Submodules needed for API containers */ /* Submodules needed for API containers */
channelsModule = { channelsModule = { name, ... }: {
options = with types; { options = with types; {
input = mkOption { input = mkOption {
type = flakeType; type = flakeType;
default = nixos; default = cfg.inputs.${name};
defaultText = "inputs.<name>";
description = '' description = ''
nixpkgs flake input to use for this channel nixpkgs flake input to use for this channel
''; '';
}; };
overlays = mkOption { overlays = mkOption {
type = pathToListOf overlayType; type = coercedListOf overlayType;
default = [ ]; default = [ ];
description = '' description = escape [ "<" ">" ] ''
overlays to apply to this channel overlays to apply to this channel
these will get exported under the 'overlays' flake output as <channel>/<name> these will get exported under the 'overlays' flake output
''; as <channel>/<name> and any overlay pulled from ''\${inputs}
}; will be filtered out
externalOverlays = mkOption {
type = pathToListOf overlayType;
default = [ ];
description = ''
overlays to apply to the channel that don't get exported to the flake output
useful to include overlays from inputs
''; '';
}; };
config = mkOption { config = mkOption {
type = pathTo attrs; type = pathTo attrs;
default = { }; default = { };
apply = lib.recursiveUpdate cfg.channelsConfig;
description = '' description = ''
nixpkgs config for this channel nixpkgs config for this channel
''; '';
@ -82,21 +80,25 @@ let
hostModule = { hostModule = {
options = with types; { options = with types; {
# anything null in hosts gets filtered out by mkFlake
system = mkOption { system = mkOption {
type = systemType; type = (nullOr systemType) // {
default = "x86_64-linux"; description = "system defined in `supportedSystems`";
};
default = null;
description = '' description = ''
system for this host system for this host
''; '';
}; };
channelName = mkOption { channelName = mkOption {
type = types.enum (builtins.attrValues config.channels); type = (nullOr (types.enum (builtins.attrNames config.channels))) // {
default = "nixpkgs"; description = "a channel defined in `channels`";
};
default = null;
description = '' description = ''
Channel this host should follow Channel this host should follow
''; '';
}; };
}; };
}; };
@ -105,10 +107,11 @@ let
externalModulesModule = { externalModulesModule = {
options = { options = {
externalModules = mkOption { externalModules = mkOption {
type = pathToListOf moduleType; type = with types; listOf moduleType;
default = [ ]; default = [ ];
description = '' description = ''
The configuration for this host modules to include that won't be exported
meant importing modules from external flakes
''; '';
}; };
}; };
@ -117,7 +120,7 @@ let
modulesModule = { modulesModule = {
options = { options = {
modules = mkOption { modules = mkOption {
type = pathToListOf moduleType; type = with types; coercedListOf moduleType;
default = [ ]; default = [ ];
description = '' description = ''
modules to include modules to include
@ -126,13 +129,31 @@ let
}; };
}; };
exportModulesModule = name: {
options = {
modules = mkOption {
type = with types; pathTo (coercedListOf exportModuleType);
default = [ ];
description = ''
modules to include in all hosts and export to ${name}Modules output
'';
};
};
};
# Home-manager's configs get exported automatically from nixos.hosts # Home-manager's configs get exported automatically from nixos.hosts
# So there is no need for a host options in the home namespace # So there is no need for a host options in the home namespace
# This is only needed for nixos # This is only needed for nixos
includeHostsModule = { name, ... }: { includeHostsModule = name: {
options = with types; { options = with types; {
hostDefaults = mkOption { hostDefaults = mkOption {
type = submodule [ hostModule externalModulesModule modulesModule ]; type = submodule [
hostModule
externalModulesModule
(exportModulesModule name)
];
default = { }; default = { };
description = '' description = ''
Defaults for all hosts. Defaults for all hosts.
@ -152,16 +173,17 @@ let
}; };
# profiles and suites - which are profile collections # profiles and suites - which are profile collections
profilesModule = { name, ... }: { profilesModule = { config, ... }: {
options = with types; { options = with types; {
profiles = mkOption { profiles = mkOption {
type = coercedListOf path; type = listOf path;
default = [ ]; default = [ ];
apply = list: description = ''
# Merge a list of profiles to one set profile folders that can be collected into suites
let profileList = map (x: os.mkProfileAttrs (toString x)) list; in the name of the argument passed to suites is based
foldl (a: b: a // b) { } profileList; on the folder name.
description = "path to profiles folder that can be collected into suites"; [ ./profiles ] => { profiles }:
'';
}; };
suites = mkOption { suites = mkOption {
type = pathTo (functionTo attrs); type = pathTo (functionTo attrs);
@ -171,8 +193,7 @@ let
inherit (config) profiles; inherit (config) profiles;
}; };
description = '' description = ''
Function with the input of 'profiles' that returns an attribute set Function that takes profiles and returns suites for this config system
with the suites for this config system.
These can be accessed through the 'suites' special argument. These can be accessed through the 'suites' special argument.
''; '';
}; };
@ -180,11 +201,22 @@ let
}; };
in in
{ {
# this does not get propagated to submodules
# to allow passing flake outputs directly to mkFlake
config._module.check = false;
options = with types; { options = with types; {
self = mkOption { self = mkOption {
type = flakeType; type = flakeType;
description = "The flake to create the devos outputs for"; description = "The flake to create the devos outputs for";
}; };
inputs = mkOption {
type = attrsOf flakeType;
description = ''
inputs for this flake
used to set channel defaults and create registry
'';
};
supportedSystems = mkOption { supportedSystems = mkOption {
type = listOf str; type = listOf str;
default = lib.defaultSystems; default = lib.defaultSystems;
@ -192,31 +224,33 @@ let
The systems supported by this flake The systems supported by this flake
''; '';
}; };
channels = channelsConfig = mkOption {
let type = pathTo attrs;
default = { default = { };
nixpkgs = { description = ''
input = nixos; nixpkgs config for all channels
'';
}; };
}; channels = mkOption {
in
mkOption {
type = attrsOf (submodule channelsModule); type = attrsOf (submodule channelsModule);
inherit default; default = { };
apply = x: default // x;
description = '' description = ''
nixpkgs channels to create nixpkgs channels to create
''; '';
}; };
os = mkOption { nixos = mkOption {
type = submodule [ includeHostsModule profilesModule ]; type = submodule [ (includeHostsModule "nixos") profilesModule ];
default = { }; default = { };
description = '' description = ''
hosts, modules, suites, and profiles for nixos hosts, modules, suites, and profiles for nixos
''; '';
}; };
home = mkOption { home = mkOption {
type = submodule [ profilesModule modulesModule ]; type = submodule [
profilesModule
(exportModulesModule "home")
externalModulesModule
];
default = { }; default = { };
description = '' description = ''
hosts, modules, suites, and profiles for home-manager hosts, modules, suites, and profiles for home-manager

View file

@ -1,162 +0,0 @@
{ lib }:
{ self, inputs, args }:
let
argOpts = with lib; { config, options, ... }:
let
inherit (lib) os;
inherit (config) self;
inputAttrs = with types; functionTo attrs;
moduleType = with types; anything // {
inherit (submodule { }) check;
description = "valid module";
};
in
{
options = with types; {
self = mkOption {
type = addCheck attrs lib.isStorePath;
description = "The flake to create the devos outputs for";
};
nixos = mkOption {
type = addCheck attrs lib.isStorePath;
description = "The default nixpkgs channel of the devos";
};
inputs = mkOption {
type = addCheck attrs lib.isStorePath;
description = "All inptus of the devos";
};
hosts = mkOption {
type = path;
default = "${self}/hosts";
defaultText = "\${self}/hosts";
apply = toString;
description = ''
Path to directory containing host configurations that will be exported
to the 'nixosConfigurations' output.
'';
};
packages = mkOption {
# functionTo changes arg names which breaks flake check
type = types.anything // {
check = builtins.isFunction;
description = "Nixpkgs overlay";
};
default = (final: prev: { });
defaultText = "(final: prev: {})";
description = ''
Overlay for custom packages that will be included in treewide 'pkgs'.
This should follow the standard nixpkgs overlay format - two argument function
that returns an attrset.
These packages will be exported to the 'packages' and 'legacyPackages' outputs.
'';
};
modules = mkOption {
type = listOf moduleType;
default = [ ];
apply = lib.pathsToImportedAttrs;
description = ''
list of modules to include in confgurations and export in 'nixosModules' output
'';
};
userModules = mkOption {
type = listOf moduleType;
default = [ ];
apply = lib.pathsToImportedAttrs;
description = ''
list of modules to include in home-manager configurations and export in
'homeModules' output
'';
};
profiles = mkOption {
type = path;
default = "${self}/profiles";
defaultText = "\${self}/profiles";
apply = x: os.mkProfileAttrs (toString x);
description = "path to profiles folder that can be collected into suites";
};
userProfiles = mkOption {
type = path;
default = "${self}/users/profiles";
defaultText = "\${self}/users/profiles";
apply = x: os.mkProfileAttrs (toString x);
description = "path to user profiles folder that can be collected into userSuites";
};
suites =
let
defaults = { user = { }; system = { }; };
in
mkOption {
type = inputAttrs;
default = { ... }: defaults;
defaultText = "{ user = {}; system = {}; }";
apply = suites: defaults // os.mkSuites {
inherit suites;
inherit (config) profiles users userProfiles;
};
description = ''
Function with inputs 'users' and 'profiles' that returns attribute set
with user and system suites. The former for Home Manager and the latter
for nixos configurations.
These can be accessed through the 'suites' specialArg in each config system.
'';
};
users = mkOption {
type = path;
default = "${self}/users";
defaultText = "\${self}/users";
apply = x: os.mkProfileAttrs (toString x);
description = ''
path to folder containing profiles that define system users
'';
};
extern =
let
defaults = {
modules = [ ];
overlays = [ ];
specialArgs = { };
userModules = [ ];
userSpecialArgs = { };
};
in
mkOption {
type = inputAttrs;
default = { ... }: defaults;
defaultText = ''
{ modules = []; overlays = []; specialArgs = []; userModules = []; userSpecialArgs = []; }
'';
# So unneeded extern attributes can safely be deleted
apply = x: defaults // (x { inputs = inputs // self.inputs; });
description = ''
Function with argument 'inputs' that contains all devos and ''${self}'s inputs.
The function should return an attribute set with modules, overlays, and
specialArgs to be included across nixos and home manager configurations.
Only attributes that are used should be returned.
'';
};
overlays = mkOption {
type = path;
default = "${self}/overlays";
defaultText = "\${self}/overlays";
apply = x: lib.pathsToImportedAttrs (lib.pathsIn (toString x));
description = ''
path to folder containing overlays which will be applied to pkgs and exported in
the 'overlays' output
'';
};
overrides = mkOption rec {
type = attrs;
default = { modules = [ ]; disabledModules = [ ]; packages = _: _: _: { }; };
defaultText = "{ modules = []; disabledModules = []; packages = {}; }";
apply = x: default // x;
description = "attrset of packages and modules that will be pulled from nixpkgs master";
};
};
};
in
lib.evalModules {
modules = [ argOpts args ];
}

View file

@ -1,28 +1,16 @@
{ lib }: { lib }:
{ {
modOverrides = { overrides }: hmDefaults = { suites, modules }: {
{ config, overrideModulesPath, ... }:
let
inherit (overrides) modules disabledModules;
in
{
disabledModules = modules ++ disabledModules;
imports = map
(path: "${overrideModulesPath}/${path}")
modules;
};
hmDefaults = { userSuites, extern, homeModules }: {
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = extern.userSpecialArgs // { suites = userSuites; }; extraSpecialArgs = { inherit suites; };
sharedModules = extern.userModules ++ (builtins.attrValues homeModules); sharedModules = modules;
}; };
}; };
globalDefaults = { self, nixos, inputs, multiPkgs }: globalDefaults = { self, inputs }:
let let
experimentalFeatures = [ experimentalFeatures = [
"flakes" "flakes"
@ -31,49 +19,41 @@
"ca-derivations" "ca-derivations"
]; ];
in in
{ config, pkgs, ... }: { { channel, config, pkgs, ... }: {
users.mutableUsers = lib.mkDefault false; users.mutableUsers = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true; hardware.enableRedistributableFirmware = lib.mkDefault true;
nix.nixPath = [ nix.nixPath = [
"nixpkgs=${nixos}" "nixpkgs=${channel.input}"
"nixos-config=${self}/lib/compat/nixos" "nixos-config=${self}/lib/compat/nixos"
"home-manager=${inputs.home}" "home-manager=${inputs.home}"
]; ];
nixpkgs.pkgs = lib.mkDefault multiPkgs.${config.nixpkgs.system};
nix.registry = { nix.registry = {
devos.flake = self; devos.flake = self;
nixos.flake = nixos; nixos.flake = channel.input;
override.flake = inputs.override;
}; };
nix.package = pkgs.nixFlakes;
nix.extraOptions = '' nix.extraOptions = ''
experimental-features = ${lib.concatStringsSep " " experimental-features = ${lib.concatStringsSep " "
experimentalFeatures experimentalFeatures
} }
''; '';
_module.args = {
inherit self;
hosts = builtins.mapAttrs (_: host: host.config)
(removeAttrs self.nixosConfigurations [ config.networking.hostName ]);
};
system.configurationRevision = lib.mkIf (self ? rev) self.rev; system.configurationRevision = lib.mkIf (self ? rev) self.rev;
}; };
cachix = { self }: isoConfig = { self, inputs, fullHostConfig }:
let rootCachix = "${self}/cachix.nix"; in { config, modulesPath, suites, ... }: {
if builtins.pathExists rootCachix
then rootCachix
else { };
flakeModules = { self, extern }: { imports = builtins.attrValues self.nixosModules ++ extern.modules; }; imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal-new-kernel.nix" ];
isoConfig = { self, nixos, inputs, fullHostConfig }:
{ config, suites, ... }: {
imports = let modpath = "nixos/modules"; in
[ "${nixos}/${modpath}/installer/cd-dvd/installation-cd-minimal-new-kernel.nix" ];
# avoid unwanted systemd service startups # avoid unwanted systemd service startups
# all strings in disabledModules get appended to modulesPath # all strings in disabledModules get appended to modulesPath
# so convert each to list which can be coerced to string # so convert each to list which can be coerced to string

View file

@ -1,13 +1,6 @@
{ lib, nixpkgs, deploy, devshell }: { lib, deploy, devshell }:
lib.genAttrs
lib.defaultSystems
(system:
let
pkgs = import nixpkgs { inherit system; };
in
{ {
tests = import ./tests { inherit lib deploy nixpkgs pkgs system; }; tests = import ./tests { inherit lib deploy; };
shell = import ./shell { inherit lib devshell deploy nixpkgs system; }; shell = import ./shell { inherit lib devshell deploy; };
} }
)

View file

@ -1,27 +1,30 @@
{ lib, nixpkgs, devshell, deploy, system }: { lib, devshell, deploy }:
{ pkgs }:
let let
overlays = [ overlays = [
devshell.overlay devshell.overlay
(final: prev: { (final: prev: {
deploy-rs = deploy-rs =
deploy.packages.${prev.system}.deploy-rs; deploy.packages.${prev.system}.deploy-rs;
}) })
]; ];
pkgs = import nixpkgs { inherit system overlays; config = { }; }; pkgs' = import pkgs.path {
inherit (pkgs) system;
inherit overlays;
};
flk = pkgs.callPackage ./flk.nix { }; flk = pkgs'.callPackage ./flk.nix { };
installPkgs = (lib.nixosSystem { installPkgs = (lib.nixosSystem {
inherit system; inherit (pkgs') system;
modules = [ ]; modules = [ ];
}).config.system.build; }).config.system.build;
in in
pkgs.devshell.mkShell { pkgs'.devshell.mkShell {
imports = [ (pkgs.devshell.importTOML ./devshell.toml) ]; imports = [ (pkgs'.devshell.importTOML ./devshell.toml) ];
packages = with installPkgs; [ packages = with installPkgs; [
nixos-install nixos-install
@ -33,13 +36,13 @@ pkgs.devshell.mkShell {
pre-commit.text = lib.fileContents ./pre-commit.sh; pre-commit.text = lib.fileContents ./pre-commit.sh;
}; };
commands = with pkgs; [ commands = with pkgs'; [
{ package = flk; } { package = flk; }
{ {
name = "nix"; name = "nix";
help = pkgs.nixFlakes.meta.description; help = pkgs'.nixFlakes.meta.description;
command = '' command = ''
${pkgs.nixFlakes}/bin/nix --experimental-features "nix-command flakes ca-references" "${"\${@}"}" ${pkgs'.nixFlakes}/bin/nix --experimental-features "nix-command flakes ca-references" "${"\${@}"}"
''; '';
} }
] ]

View file

@ -1,25 +1,28 @@
{ lib, nixpkgs, pkgs, deploy, system }: { lib, deploy }:
let let
mkChecks = { hosts, nodes, homes ? { } }: mkChecks = { pkgs, hosts, nodes, homes ? { } }:
let let
deployHosts = lib.filterAttrs deployHosts = lib.filterAttrs
(n: _: hosts.${n}.config.nixpkgs.system == system) (n: _: hosts.${n}.config.nixpkgs.system == pkgs.system)
nodes; nodes;
deployChecks = deploy.lib.${system}.deployChecks { nodes = deployHosts; }; deployChecks = deploy.lib.${pkgs.system}.deployChecks { nodes = deployHosts; };
tests = tests =
lib.optionalAttrs (deployHosts != { }) lib.optionalAttrs (deployHosts != { })
{ {
profilesTest = profilesTest (hosts.${(builtins.head (builtins.attrNames deployHosts))}); profilesTest = profilesTest {
inherit pkgs;
host = hosts.${(builtins.head (builtins.attrNames deployHosts))};
};
} // lib.mapAttrs (n: v: v.activationPackage) homes; } // lib.mapAttrs (n: v: v.activationPackage) homes;
in in
lib.recursiveUpdate tests deployChecks; lib.recursiveUpdate tests deployChecks;
mkTest = host: mkTest = { pkgs, host }:
let let
nixosTesting = nixosTesting =
(import "${nixpkgs}/nixos/lib/testing-python.nix" { (import "${toString pkgs.path}/nixos/lib/testing-python.nix" {
inherit system; inherit (pkgs) system;
inherit (host.config.lib) specialArgs; inherit (host.config.lib) specialArgs;
inherit pkgs; inherit pkgs;
extraConfigurations = [ extraConfigurations = [
@ -40,15 +43,15 @@ let
in in
nixosTesting.makeTest calledTest; nixosTesting.makeTest calledTest;
profilesTest = host: mkTest host { profilesTest = args@{ host, ... }: mkTest args {
name = "profiles"; name = "profiles";
machine = { suites, ... }: { machine = { suites, ... }: {
imports = suites.allProfiles ++ suites.allUsers; imports = suites.allProfiles;
}; };
testScript = '' testScript = ''
machine.systemctl("is-system-running --wait") ${host.config.networking.hostName}.systemctl("is-system-running --wait")
''; '';
}; };
in in

View file

@ -71,23 +71,19 @@ lib.runTests {
}; };
}; };
testSuites = testSuites = {
let expr = os.mkSuites {
profiles = os.mkProfileAttrs (toString ./profiles); suites = { profiles, ... }: with profiles; {
users = ""; bar = [ foo ];
userProfiles = ""; };
suites = { profiles, ... }: { profiles = [ (./profiles) ];
system.bar = [ profiles.foo ];
}; };
in
{
expr = os.mkSuites { inherit profiles users userProfiles suites; };
expected = { expected = {
system = { bar = [ (toString ./profiles/foo) ];
bar = [ profiles.foo.default ]; allProfiles = [
allProfiles = [ profiles.foo.default profiles.t.default ]; (toString ./profiles/foo)
allUsers = [ ]; (toString ./profiles/t)
}; ];
}; };
}; };
} }

26
overlays/overrides.nix Normal file
View file

@ -0,0 +1,26 @@
channels: final: prev: {
inherit (channels.latest)
cachix
dhall
discord
element-desktop
manix
nixpkgs-fmt
qutebrowser
signal-desktop
starship;
haskellPackages = prev.haskellPackages.override {
overrides = hfinal: hprev:
let version = prev.lib.replaceChars [ "." ] [ "" ] prev.ghc.version;
in
{
# same for haskell packages, matching ghc versions
inherit (channels.latest.haskell.packages."ghc${version}")
haskell-language-server;
};
};
}