feat: upstream node generation
This commit is contained in:
parent
f1a3f0303b
commit
93b08971cf
9 changed files with 268 additions and 48 deletions
6
flake-modules/default.nix
Normal file
6
flake-modules/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./globals.nix
|
||||||
|
./nodes.nix
|
||||||
|
];
|
||||||
|
}
|
74
flake-modules/globals.nix
Normal file
74
flake-modules/globals.nix
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.globals = {
|
||||||
|
optModules = mkOption {
|
||||||
|
type = types.listOf types.deferredModule;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
Modules defining global options.
|
||||||
|
These should not include any config only option declaration.
|
||||||
|
Will be included in the exported nixos Modules from this flake to be included
|
||||||
|
into the host evaluation.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
defModules = mkOption {
|
||||||
|
type = types.listOf types.deferredModule;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
Modules configuring global options.
|
||||||
|
These should not include any option declaration use {option}`optModules` for that.
|
||||||
|
Will not included in the exported nixos Modules.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
attrkeys = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
The toplevel attrNames for your globals.
|
||||||
|
Make sure the keys of this attrset are trivially evaluatable to avoid infinite recursion,
|
||||||
|
therefore we inherit relevant attributes from the config.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config.flake = flakeSubmod: {
|
||||||
|
globals =
|
||||||
|
let
|
||||||
|
globalsSystem = lib.evalModules {
|
||||||
|
prefix = [ "globals" ];
|
||||||
|
specialArgs = {
|
||||||
|
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
||||||
|
inherit inputs;
|
||||||
|
inherit (flakeSubmod.config) nodes;
|
||||||
|
};
|
||||||
|
modules =
|
||||||
|
config.globals.optModules
|
||||||
|
++ config.globals.defModules
|
||||||
|
++ [
|
||||||
|
../modules/globals.nix
|
||||||
|
(
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
globals = lib.mkMerge (
|
||||||
|
lib.concatLists (
|
||||||
|
lib.flip lib.mapAttrsToList flakeSubmod.config.nodes (
|
||||||
|
name: cfg:
|
||||||
|
builtins.addErrorContext "while aggregating globals from nixosConfigurations.${name} into flake-level globals:" cfg.config._globalsDefs
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.genAttrs config.globals.attrkeys (x: globalsSystem.config.globals.${x});
|
||||||
|
};
|
||||||
|
}
|
110
flake-modules/nodes.nix
Normal file
110
flake-modules/nodes.nix
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
self,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
topConfig = config;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.node = {
|
||||||
|
path = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "The path containing your host definitions";
|
||||||
|
};
|
||||||
|
nixpkgs = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = inputs.nixpkgs;
|
||||||
|
description = "The path to your nixpkgs.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config.flake =
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
concatMapAttrs
|
||||||
|
filterAttrs
|
||||||
|
flip
|
||||||
|
genAttrs
|
||||||
|
mapAttrs'
|
||||||
|
nameValuePair
|
||||||
|
;
|
||||||
|
|
||||||
|
# Creates a new nixosSystem with the correct specialArgs, pkgs and name definition
|
||||||
|
mkHost =
|
||||||
|
{ minimal }:
|
||||||
|
name:
|
||||||
|
let
|
||||||
|
pkgs = config.pkgs.x86_64-linux;
|
||||||
|
in
|
||||||
|
(import "${topConfig.node.nixpkgs}/nixos/lib/eval-config.nix") {
|
||||||
|
system = null;
|
||||||
|
specialArgs = {
|
||||||
|
# Use the correct instance lib that has our overlays
|
||||||
|
inherit (pkgs) lib;
|
||||||
|
inherit (config) nodes globals;
|
||||||
|
inherit minimal;
|
||||||
|
extraModules = [
|
||||||
|
../modules
|
||||||
|
] ++ topConfig.globals.optModules;
|
||||||
|
inputs = inputs // {
|
||||||
|
inherit (topConfig.node) nixpkgs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
modules = [
|
||||||
|
(
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
node.name = name;
|
||||||
|
node.secretsDir = topConfig.node.path + "/${name}/secrets";
|
||||||
|
nixpkgs.pkgs = self.pkgs.${config.nixpkgs.hostPlatform.system};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(topConfig.node.path + "/${name}")
|
||||||
|
../modules
|
||||||
|
] ++ topConfig.globals.optModules;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Load the list of hosts that this flake defines, which
|
||||||
|
# associates the minimum amount of metadata that is necessary
|
||||||
|
# to instanciate hosts correctly.
|
||||||
|
hosts = builtins.attrNames (
|
||||||
|
filterAttrs (_: type: type == "directory") (builtins.readDir topConfig.node.path)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
# Process each nixosHosts declaration and generatea nixosSystem definitions
|
||||||
|
{
|
||||||
|
nixosConfigurations = genAttrs hosts (mkHost {
|
||||||
|
minimal = false;
|
||||||
|
});
|
||||||
|
minimalConfigurations = genAttrs hosts (mkHost {
|
||||||
|
minimal = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
# True NixOS nodes can define additional guest nodes that are built
|
||||||
|
# together with it. We collect all defined guests from each node here
|
||||||
|
# to allow accessing any node via the unified attribute `nodes`.
|
||||||
|
guestConfigurations = flip concatMapAttrs config.nixosConfigurations (
|
||||||
|
_: node:
|
||||||
|
flip mapAttrs' (node.config.guests or { }) (
|
||||||
|
guestName: guestDef:
|
||||||
|
nameValuePair guestDef.nodeName (
|
||||||
|
if guestDef.backend == "microvm" then
|
||||||
|
node.config.microvm.vms.${guestName}.config
|
||||||
|
else
|
||||||
|
node.config.containers.${guestName}.nixosConfiguration
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
# All nixosSystem instanciations are collected here, so that we can refer
|
||||||
|
# to any system via nodes.<name>
|
||||||
|
nodes = config.nixosConfigurations // config.guestConfigurations;
|
||||||
|
};
|
||||||
|
}
|
|
@ -35,6 +35,10 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
flake.modules = {
|
flake.modules = {
|
||||||
|
flake = {
|
||||||
|
nixos-extra-modules = import ./flake-modules;
|
||||||
|
default = self.modules.flake.nixos-extra-modules;
|
||||||
|
};
|
||||||
nixos = {
|
nixos = {
|
||||||
nixos-extra-modules = import ./modules;
|
nixos-extra-modules = import ./modules;
|
||||||
default = self.modules.nixos.nixos-extra-modules;
|
default = self.modules.nixos.nixos-extra-modules;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{inputs, ...}: {
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
imports = [
|
imports = [
|
||||||
inputs.microvm.nixosModules.host
|
inputs.microvm.nixosModules.host
|
||||||
|
|
||||||
./boot.nix
|
./boot.nix
|
||||||
|
./globals.nix
|
||||||
./guests/default.nix
|
./guests/default.nix
|
||||||
./interface-naming.nix
|
./interface-naming.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
|
|
9
modules/globals.nix
Normal file
9
modules/globals.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{ lib, options, ... }:
|
||||||
|
{
|
||||||
|
options._globalsDefs = lib.mkOption {
|
||||||
|
type = lib.types.unspecified;
|
||||||
|
default = options.globals.definitions;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
_guestName: guestCfg: {lib, ...}: let
|
_guestName: guestCfg:
|
||||||
inherit
|
{ lib, ... }:
|
||||||
(lib)
|
let
|
||||||
|
inherit (lib)
|
||||||
mkForce
|
mkForce
|
||||||
nameValuePair
|
nameValuePair
|
||||||
listToAttrs
|
listToAttrs
|
||||||
flip
|
flip
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
node.name = guestCfg.nodeName;
|
node.name = guestCfg.nodeName;
|
||||||
node.type = guestCfg.backend;
|
node.type = guestCfg.backend;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
guestName: guestCfg: {
|
guestName: guestCfg:
|
||||||
|
{
|
||||||
config,
|
config,
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
|
extraModules,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
flip
|
flip
|
||||||
mapAttrs'
|
mapAttrs'
|
||||||
nameValuePair
|
nameValuePair
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
inherit (guestCfg.container) macvlans;
|
inherit (guestCfg.container) macvlans;
|
||||||
ephemeral = true;
|
ephemeral = true;
|
||||||
privateNetwork = true;
|
privateNetwork = true;
|
||||||
|
@ -65,6 +68,7 @@ in {
|
||||||
}
|
}
|
||||||
(import ./common-guest-config.nix guestName guestCfg)
|
(import ./common-guest-config.nix guestName guestCfg)
|
||||||
]
|
]
|
||||||
++ guestCfg.modules;
|
++ guestCfg.modules
|
||||||
|
++ extraModules;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
guestName: guestCfg: {
|
guestName: guestCfg:
|
||||||
|
{
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
|
extraModules,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
concatMapAttrs
|
concatMapAttrs
|
||||||
flip
|
flip
|
||||||
mapAttrs
|
mapAttrs
|
||||||
|
@ -13,17 +15,20 @@ guestName: guestCfg: {
|
||||||
mkForce
|
mkForce
|
||||||
replaceStrings
|
replaceStrings
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
specialArgs = guestCfg.extraSpecialArgs;
|
specialArgs = guestCfg.extraSpecialArgs;
|
||||||
pkgs = inputs.self.pkgs.${guestCfg.microvm.system};
|
pkgs = inputs.self.pkgs.${guestCfg.microvm.system};
|
||||||
inherit (guestCfg) autostart;
|
inherit (guestCfg) autostart;
|
||||||
config = {
|
config = {
|
||||||
imports =
|
imports =
|
||||||
guestCfg.modules
|
extraModules
|
||||||
|
++ guestCfg.modules
|
||||||
++ [
|
++ [
|
||||||
(import ./common-guest-config.nix guestName guestCfg)
|
(import ./common-guest-config.nix guestName guestCfg)
|
||||||
(
|
(
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
# Set early hostname too, so we can associate those logs to this host and don't get "localhost" entries in loki
|
# Set early hostname too, so we can associate those logs to this host and don't get "localhost" entries in loki
|
||||||
boot.kernelParams = [ "systemd.hostname=${config.networking.hostName}" ];
|
boot.kernelParams = [ "systemd.hostname=${config.networking.hostName}" ];
|
||||||
}
|
}
|
||||||
|
@ -47,11 +52,13 @@ in {
|
||||||
|
|
||||||
# MACVTAP bridge to the host's network
|
# MACVTAP bridge to the host's network
|
||||||
interfaces = flip mapAttrsToList guestCfg.microvm.interfaces (
|
interfaces = flip mapAttrsToList guestCfg.microvm.interfaces (
|
||||||
_: {
|
_:
|
||||||
|
{
|
||||||
mac,
|
mac,
|
||||||
hostLink,
|
hostLink,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
type = "macvtap";
|
type = "macvtap";
|
||||||
id = "vm-${replaceStrings [ ":" ] [ "" ] mac}";
|
id = "vm-${replaceStrings [ ":" ] [ "" ] mac}";
|
||||||
inherit mac;
|
inherit mac;
|
||||||
|
@ -84,7 +91,9 @@ in {
|
||||||
|
|
||||||
networking.renameInterfacesByMac = flip mapAttrs guestCfg.microvm.interfaces (_: { mac, ... }: mac);
|
networking.renameInterfacesByMac = flip mapAttrs guestCfg.microvm.interfaces (_: { mac, ... }: mac);
|
||||||
systemd.network.networks = flip concatMapAttrs guestCfg.microvm.interfaces (
|
systemd.network.networks = flip concatMapAttrs guestCfg.microvm.interfaces (
|
||||||
name: {mac, ...}: {
|
name:
|
||||||
|
{ mac, ... }:
|
||||||
|
{
|
||||||
"10-${name}".matchConfig = mkForce {
|
"10-${name}".matchConfig = mkForce {
|
||||||
MACAddress = mac;
|
MACAddress = mac;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue