nixfleet/hosts/module.nix

359 lines
12 KiB
Nix

# TODO Add per host:
# - apps to run as VMs
# - checks
# - deploy scripts (`nixos-rebuild`)
{
self,
lib,
config,
inputs,
...
}:
let
cfg = config.fleet;
in
{
options.fleet = {
darwinHosts = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "Host name";
type = lib.types.strMatching "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
default = name;
};
system = lib.mkOption {
description = "NixOS architecture (a.k.a. system)";
type = lib.types.str;
default = "x86_64-darwin";
};
nixpkgs = lib.mkOption {
description = "Used nixpkgs";
type = lib.types.anything;
default = inputs.nixpkgs;
};
extraModules = lib.mkOption {
description = "Extra NixOS modules";
type = lib.types.listOf lib.types.deferredModule;
default = [ ];
};
overlays = lib.mkOption {
description = "Enabled Nixpkgs overlays";
type = lib.types.listOf (
lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
}
);
default = [ ];
};
};
}
)
);
};
nixOnDroidHosts = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "Host name";
type = lib.types.strMatching "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
default = name;
};
system = lib.mkOption {
description = "NixOS architecture (a.k.a. system)";
type = lib.types.str;
default = "aarch64-linux";
};
nixpkgs = lib.mkOption {
description = "Used nixpkgs";
type = lib.types.anything;
default = inputs.nixpkgs;
};
extraModules = lib.mkOption {
description = "Extra NixOS modules";
type = lib.types.listOf lib.types.deferredModule;
default = [ ];
};
overlays = lib.mkOption {
description = "Enabled Nixpkgs overlays";
type = lib.types.listOf (
lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
}
);
default = [ ];
};
};
}
)
);
};
hosts = lib.mkOption {
description = "Host configuration";
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "Host name";
type = lib.types.strMatching "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
default = name;
};
system = lib.mkOption {
description = "NixOS architecture (a.k.a. system)";
type = lib.types.str;
default = "x86_64-linux";
};
nixpkgs = lib.mkOption {
description = "Used nixpkgs";
type = lib.types.anything;
default = inputs.nixpkgs;
};
homeManager = lib.mkOption {
description = "Used home-manager";
type = lib.types.anything;
default = inputs.homeManager;
};
vpn = {
ip = lib.mkOption {
description = "Wireguard VPN ip";
type = lib.types.str;
};
publicKey = lib.mkOption {
description = "Wireguard public key";
type = lib.types.str;
};
};
secrets = lib.mkOption {
description = "List of secrets names in the `secrets` folder";
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
owner = lib.mkOption {
type = lib.types.str;
default = "root";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
};
file = lib.mkOption {
type = lib.types.path;
default = "${self.outPath}/secrets/${name}.age";
};
mode = lib.mkOption {
# TODO improve type
type = lib.types.str;
default = "0440";
};
};
}
)
);
default = { };
};
enableHomeManager = lib.mkOption {
description = "Enable home-manager module";
type = lib.types.bool;
default = true;
};
overlays = lib.mkOption {
description = "Enabled Nixpkgs overlays";
type = lib.types.listOf (
lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
}
);
default = [ ];
};
extraModules = lib.mkOption {
description = "Extra NixOS modules";
type = lib.types.listOf lib.types.deferredModule;
default = [ ];
};
extraHmModules = lib.mkOption {
description = "Extra home-manager modules";
type = lib.types.listOf lib.types.deferredModule;
default = [ ];
};
extraHmModulesUser = lib.mkOption {
description = "User for which to import extraHmModulesUser";
type = lib.types.str;
default = "ccr";
};
};
config.overlays = with inputs; cfg.overlays;
}
)
);
default = { };
};
vpnExtra = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
ip = lib.mkOption {
description = "Wireguard VPN ip";
type = lib.types.str;
};
publicKey = lib.mkOption {
description = "Wireguard public key";
type = lib.types.str;
};
};
}
);
default = { };
};
_mkNixosConfiguration = lib.mkOption {
description = "Function returning a proper NixOS configuration";
type = lib.types.functionTo (lib.types.functionTo lib.types.attrs); # TODO improve this type
internal = true;
default =
hostname: config:
config.nixpkgs.lib.nixosSystem {
inherit (config) system;
modules =
[
(
{ lib, ... }:
{
networking.hostName = lib.mkForce hostname;
nixpkgs.overlays = config.overlays;
}
)
"${self.outPath}/hosts/${hostname}"
]
++ (lib.optionals (config.secrets != [ ]) [
inputs.agenix.nixosModules.default
(
{ lib, ... }:
let
allSecrets = lib.mapAttrs' (name: value: {
name = lib.removeSuffix ".age" name;
inherit value;
}) (import "${self.outPath}/secrets/secrets.nix");
filteredSecrets = lib.filterAttrs (name: _: builtins.hasAttr name config.secrets) allSecrets;
in
{
age.secrets = lib.mapAttrs' (name: _: {
name = builtins.baseNameOf name;
value = {
inherit (config.secrets.${name})
owner
group
file
mode
;
};
}) filteredSecrets;
}
)
])
++ (lib.optionals config.enableHomeManager (
let
user = config.extraHmModulesUser;
extraHmModules = config.extraHmModules;
in
[
config.homeManager.nixosModules.home-manager
(
{
config,
...
}:
{
home-manager.users."${user}" = {
imports = extraHmModules;
_module.args = {
age = config.age or { };
fleetFlake = self;
};
};
}
)
]
))
++ config.extraModules;
specialArgs = {
fleetModules = builtins.map (moduleName: "${self.outPath}/modules/${moduleName}");
fleetHmModules = builtins.map (moduleName: "${self.outPath}/hmModules/${moduleName}");
fleetFlake = self;
vpn = cfg.vpnExtra // (lib.mapAttrs (_: host: host.vpn) cfg.hosts);
};
};
};
_mkDarwinConfiguration = lib.mkOption {
description = "Function returning a proper Darwin configuration";
type = lib.types.functionTo (lib.types.functionTo lib.types.attrs); # TODO improve this type
internal = true;
default =
hostname: config:
inputs.nixDarwin.lib.darwinSystem {
modules = [
(
{
lib,
...
}:
{
networking.hostName = lib.mkForce hostname;
nixpkgs.overlays = config.overlays;
nixpkgs.hostPlatform = config.system;
}
)
"${self.outPath}/hosts/${hostname}"
];
};
};
_mkNixOnDroidConfiguration = lib.mkOption {
description = "Function returning a proper nix-on-droid configuration";
type = lib.types.functionTo (lib.types.functionTo lib.types.attrs); # TODO improve this type
internal = true;
default =
hostname: config:
inputs.nix-on-droid.lib.nixOnDroidConfiguration {
pkgs = inputs.nixpkgs.legacyPackages.aarch64-linux;
modules = [
(
{
...
}:
{
nixpkgs.overlays = config.overlays;
_module.args.fleetFlake = self;
}
)
"${self.outPath}/hosts/${hostname}"
];
};
};
};
config = {
flake.nixosConfigurations = lib.mapAttrs config.fleet._mkNixosConfiguration config.fleet.hosts;
flake.darwinConfigurations = lib.mapAttrs config.fleet._mkDarwinConfiguration config.fleet.darwinHosts;
flake.nixOnDroidConfigurations = lib.mapAttrs config.fleet._mkNixOnDroidConfiguration config.fleet.nixOnDroidHosts;
};
}