feat: finish transition to flake-parts

This commit is contained in:
oddlama 2024-06-01 00:31:38 +02:00
parent 1424778bc2
commit 78b92f06cc
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
24 changed files with 237 additions and 277 deletions

View file

@ -122,7 +122,7 @@ but here's a quick breakdown of the what you will find where.
- Create a bootable iso disk image with `nix build --print-out-paths --no-link .#images.<target-system>.live-iso`, dd it to a stick and boot - Create a bootable iso disk image with `nix build --print-out-paths --no-link .#images.<target-system>.live-iso`, dd it to a stick and boot
- (Alternative) Use an official NixOS live-iso and setup ssh manually - (Alternative) Use an official NixOS live-iso and setup ssh manually
- Copy the installer from a local machine to the live system with `nix copy --to <target> .#packages.<target-system>.installer-package.<target>` - Copy the installer from a local machine to the live system with `nix copy --to <target> .#nixosConfigurationsMinimal.config.system.build.installFromLive`
Afterwards: Afterwards:

View file

@ -19,8 +19,6 @@ Make sure to utilize the github search if you know what you need!
Some hosts define guests that run as containerized or virtualized guests. Their configuration is usually just a single file Some hosts define guests that run as containerized or virtualized guests. Their configuration is usually just a single file
stored in `guests/<name>.nix`. Their secrets are usually stored in a subfolder of the host's secrets folder. stored in `guests/<name>.nix`. Their secrets are usually stored in a subfolder of the host's secrets folder.
- `lib/` contains extra library functions that are needed throughout the config.
- `modules/` contains modularized configuration. If you are interested in reusable parts of - `modules/` contains modularized configuration. If you are interested in reusable parts of
my configuration, this is probably the folder you are looking for. These will be regular my configuration, this is probably the folder you are looking for. These will be regular
reusable modules like those you would find in `nixpkgs/nixos/modules`. reusable modules like those you would find in `nixpkgs/nixos/modules`.

View file

@ -23,6 +23,7 @@
./home-manager.nix ./home-manager.nix
./impermanence.nix ./impermanence.nix
./inputrc.nix ./inputrc.nix
./installer.nix
./issue.nix ./issue.nix
./net.nix ./net.nix
./nftables.nix ./nftables.nix
@ -35,8 +36,13 @@
./users.nix ./users.nix
]; ];
nixpkgs.overlays = [ nixpkgs.config.allowUnfree = true;
inputs.nixvim.overlays.default nixpkgs.overlays =
inputs.wired-notify.overlays.default import ../pkgs/default.nix
]; ++ [
inputs.nix-topology.overlays.default
inputs.nixos-extra-modules.overlays.default
inputs.nixvim.overlays.default
inputs.wired-notify.overlays.default
];
} }

43
config/installer.nix Normal file
View file

@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
...
}: let
disko-script = pkgs.writeShellScriptBin "disko-script" "${config.system.build.diskoScript}";
disko-mount = pkgs.writeShellScriptBin "disko-mount" "${config.system.build.mountScript}";
disko-format = pkgs.writeShellScriptBin "disko-format" "${config.system.build.formatScript}";
install-system = pkgs.writeShellScriptBin "install-system" ''
set -euo pipefail
echo "Formatting disks..."
${disko-script}/bin/disko-script
echo "Installing system..."
nixos-install --no-root-password --system ${config.system.build.toplevel}
echo "Done!"
echo "DONT FORGET TO EXPORT YOUR ZFS POOL(S)!"
'';
installer-package = pkgs.symlinkJoin {
name = "installer-package-${config.node.name}";
paths = [
disko-script
disko-mount
disko-format
install-system
];
};
in {
options.system.build.installFromLive = lib.mkOption {
type = lib.types.package;
description = ''
A single script that can be used from a live system, which will
format disks and copy the derivation.
'';
default = installer-package;
readOnly = true;
};
}

6
flake.lock generated
View file

@ -51,11 +51,11 @@
"pre-commit-hooks": "pre-commit-hooks" "pre-commit-hooks": "pre-commit-hooks"
}, },
"locked": { "locked": {
"lastModified": 1716983518, "lastModified": 1717022817,
"narHash": "sha256-LdiPzaq6IwCfEpjaZfndO1CtW1ah1ONwyXKPs7s6UVk=", "narHash": "sha256-PHyHgQL5/b0+A/kmNCHVOM/WSJSGe1jZ+LFWfYNx31E=",
"owner": "oddlama", "owner": "oddlama",
"repo": "agenix-rekey", "repo": "agenix-rekey",
"rev": "8cf73841a6fa127a64392c8603ce51af1c63b33f", "rev": "c6c1ca5b9ceaaa40fd979fb25bb7043adf4554ad",
"type": "github" "type": "github"
}, },
"original": { "original": {

129
flake.nix
View file

@ -96,136 +96,19 @@
outputs = inputs: outputs = inputs:
inputs.flake-parts.lib.mkFlake {inherit inputs;} { inputs.flake-parts.lib.mkFlake {inherit inputs;} {
imports = [ imports = [
./nix/devshell.nix
./nix/agenix-rekey.nix ./nix/agenix-rekey.nix
./nix/devshell.nix
./nix/globals.nix ./nix/globals.nix
( ./nix/hosts.nix
{ ./nix/iso.nix
lib, ./nix/pkgs.nix
flake-parts-lib, ./nix/storage-box.nix
... ./topology/flake-module.nix
}:
flake-parts-lib.mkTransposedPerSystemModule {
name = "images";
file = ./flake.nix;
option = lib.mkOption {
type = lib.types.unspecified;
};
}
)
(
{
lib,
flake-parts-lib,
...
}:
flake-parts-lib.mkTransposedPerSystemModule {
name = "pkgs";
file = ./flake.nix;
option = lib.mkOption {
type = lib.types.unspecified;
};
}
)
]; ];
flake = {
config,
lib,
...
}: let
inherit
(lib)
foldl'
mapAttrs
mapAttrsToList
recursiveUpdate
;
in {
inherit
(import ./nix/hosts.nix inputs)
hosts
guestConfigs
nixosConfigurations
nixosConfigurationsMinimal
;
# All nixosSystem instanciations are collected here, so that we can refer
# to any system via nodes.<name>
nodes = config.nixosConfigurations // config.guestConfigs;
# Add a shorthand to easily target toplevel derivations
"@" = mapAttrs (_: v: v.config.system.build.toplevel) config.nodes;
# For each true NixOS system, we want to expose an installer package that
# can be used to do the initial setup on the node from a live environment.
# We use the minimal sibling configuration to reduce the amount of stuff
# we have to copy to the live system.
inherit
(foldl' recursiveUpdate {}
(mapAttrsToList
(import ./nix/generate-installer-package.nix inputs)
config.nixosConfigurationsMinimal))
packages
;
};
systems = [ systems = [
"x86_64-linux" "x86_64-linux"
"aarch64-linux" "aarch64-linux"
]; ];
perSystem = {
config,
pkgs,
system,
...
}: {
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
config.allowUnfree = true;
overlays =
import ./lib inputs
++ import ./pkgs/default.nix
++ [
inputs.nix-topology.overlays.default
inputs.nixos-extra-modules.overlays.default
];
};
inherit pkgs;
apps.setupHetznerStorageBoxes = import (inputs.nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") {
inherit pkgs;
nixosConfigurations = config.nodes;
decryptIdentity = builtins.head config.secretsConfig.masterIdentities;
};
#topology = import inputs.nix-topology {
# inherit pkgs;
# modules = [
# ./topology
# {
# inherit (inputs.self) nixosConfigurations;
# }
# ];
#};
# For each major system, we provide a customized installer image that
# has ssh and some other convenience stuff preconfigured.
# Not strictly necessary for new setups.
images.live-iso = inputs.nixos-generators.nixosGenerate {
inherit pkgs;
modules = [
./nix/installer-configuration.nix
./config/ssh.nix
];
format =
{
x86_64-linux = "install-iso";
aarch64-linux = "sd-aarch64-installer";
}
.${system};
};
};
}; };
} }

View file

@ -12,6 +12,7 @@
#./stalwart-mail.nix #./stalwart-mail.nix
]; ];
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "bios"; boot.mode = "bios";
users.groups.acme.members = ["nginx"]; users.groups.acme.members = ["nginx"];

View file

@ -32,7 +32,9 @@
./net.nix ./net.nix
]; ];
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "efi"; boot.mode = "efi";
boot.kernelModules = ["nvidia_uvm"]; # FIXME: For some reason this doesn't load automatically for me, causing CUDA_ERROR_UNKNOWN (999) issues when trying to cuInit
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"];
boot.binfmt.emulatedSystems = ["aarch64-linux"]; boot.binfmt.emulatedSystems = ["aarch64-linux"];
} }

View file

@ -27,6 +27,7 @@
./net.nix ./net.nix
]; ];
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "efi"; boot.mode = "efi";
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"];

View file

@ -16,6 +16,7 @@
./oauth2.nix ./oauth2.nix
]; ];
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "bios"; boot.mode = "bios";
wireguard.proxy-sentinel.firewallRuleForAll.allowedTCPPorts = [80 443]; wireguard.proxy-sentinel.firewallRuleForAll.allowedTCPPorts = [80 443];

View file

@ -22,6 +22,7 @@
topology.self.hardware.info = "AMD Ryzen Threadripper 1950X, 96GB RAM"; topology.self.hardware.info = "AMD Ryzen Threadripper 1950X, 96GB RAM";
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "efi"; boot.mode = "efi";
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "e1000e" "alx"]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "e1000e" "alx"];

View file

@ -24,6 +24,7 @@
topology.self.hardware.image = ../../topology/images/odroid-h3.png; topology.self.hardware.image = ../../topology/images/odroid-h3.png;
topology.self.hardware.info = "O-Droid H3, 64GB RAM"; topology.self.hardware.info = "O-Droid H3, 64GB RAM";
nixpkgs.hostPlatform = "x86_64-linux";
boot.mode = "efi"; boot.mode = "efi";
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" "r8169"]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" "r8169"];

View file

@ -28,6 +28,7 @@ in {
topology.self.hardware.image = ../../topology/images/odroid-n2plus.png; topology.self.hardware.image = ../../topology/images/odroid-n2plus.png;
topology.self.hardware.info = "O-Droid N2+"; topology.self.hardware.info = "O-Droid N2+";
nixpkgs.hostPlatform = "aarch64-linux";
boot.mode = "efi"; boot.mode = "efi";
meta.promtail = { meta.promtail = {

View file

@ -1,3 +0,0 @@
inputs: [
(import ./secrets.nix inputs)
]

View file

@ -1,33 +0,0 @@
inputs: final: prev: let
inherit
(prev.lib)
concatMapStrings
escapeShellArg
;
inherit
(final.lib)
isAbsolutePath
;
in {
lib =
prev.lib
// {
secrets = let
rageMasterIdentityArgs = concatMapStrings (x: "-i ${escapeShellArg x} ") inputs.self.secretsConfig.masterIdentities;
rageExtraEncryptionPubkeys =
concatMapStrings (
x:
if isAbsolutePath x
then "-R ${escapeShellArg x} "
else "-r ${escapeShellArg x} "
)
inputs.self.secretsConfig.extraEncryptionPubkeys;
in {
# TODO replace these by lib.agenix-rekey
# The arguments required to de-/encrypt a secret in this repository
rageDecryptArgs = "${rageMasterIdentityArgs}";
rageEncryptArgs = "${rageMasterIdentityArgs} ${rageExtraEncryptionPubkeys}";
};
};
}

View file

@ -1,35 +0,0 @@
{self, ...}: nodeName: nodeAttrs: let
inherit (self.hosts.${nodeName}) system;
pkgs = self.pkgs.${system};
disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript}";
disko-mount = pkgs.writeShellScriptBin "disko-mount" "${nodeAttrs.config.system.build.mountScript}";
disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript}";
install-system = pkgs.writeShellScriptBin "install-system" ''
set -euo pipefail
echo "Formatting disks..."
${disko-script}/bin/disko-script
echo "Installing system..."
nixos-install --no-root-password --system ${nodeAttrs.config.system.build.toplevel}
echo "Done!"
echo "DONT FORGET TO EXPORT YOUR ZFS POOL(S)!"
'';
installer-package = pkgs.symlinkJoin {
name = "installer-package-${nodeName}";
paths = [
disko-script
disko-mount
disko-format
install-system
];
};
in {
# Everything required for the installer as a single package,
# so it can be used from an existing live system by copying the derivation.
packages.${system}.installer-package.${nodeName} = installer-package;
}

View file

@ -1,70 +1,63 @@
inputs: let {inputs, ...}: {
inherit (inputs) self; flake = {
inherit config,
(inputs.nixpkgs.lib) lib,
concatMapAttrs ...
filterAttrs }: let
flip inherit
mapAttrs (lib)
mapAttrs' concatMapAttrs
nameValuePair filterAttrs
nixosSystem flip
; genAttrs
mapAttrs
mapAttrs'
nameValuePair
;
# Creates a new nixosSystem with the correct specialArgs, pkgs and name definition # Creates a new nixosSystem with the correct specialArgs, pkgs and name definition
mkHost = {minimal}: name: hostCfg: let mkHost = {minimal}: name: let
pkgs = self.pkgs.${hostCfg.system}; pkgs = config.pkgs.x86_64-linux; # FIXME: NOOOOOOOOOOOOOOOOOOOOOOO
in in
nixosSystem { inputs.nixpkgs.lib.nixosSystem {
specialArgs = { specialArgs = {
# Use the correct instance lib that has our overlays # Use the correct instance lib that has our overlays
inherit (pkgs) lib; inherit (pkgs) lib;
inherit (self) nodes globals; inherit (config) nodes globals;
inherit inputs minimal; inherit inputs minimal;
};
modules = [
{
node.name = name;
node.secretsDir = ../hosts/${name}/secrets;
}
../hosts/${name}
];
}; };
modules = [
{
# We cannot force the package set via nixpkgs.pkgs and
# inputs.nixpkgs.nixosModules.readOnlyPkgs, since some nixosModules
# like nixseparatedebuginfod depend on adding packages via nixpkgs.overlays.
# So we just mimic the options and overlays defined by the passed pkgs set.
nixpkgs.hostPlatform = hostCfg.system;
nixpkgs.overlays = pkgs.overlays;
nixpkgs.config = pkgs.config;
node.name = name;
node.secretsDir = ../hosts/${name}/secrets;
}
../hosts/${name}
];
};
# Load the list of hosts that this flake defines, which # Get all folders in hosts/
# associates the minimum amount of metadata that is necessary hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts));
# to instanciate hosts correctly. in {
hosts = builtins.fromTOML (builtins.readFile ../hosts.toml); nixosConfigurations = genAttrs hosts (mkHost {minimal = false;});
# Get all hosts of type "nixos" nixosConfigurationsMinimal = genAttrs hosts (mkHost {minimal = true;});
nixosHosts = filterAttrs (_: x: x.type == "nixos") hosts;
# Process each nixosHosts declaration and generatea nixosSystem definitions
nixosConfigurations = flip mapAttrs nixosHosts (mkHost {minimal = false;});
nixosConfigurationsMinimal = flip mapAttrs nixosHosts (mkHost {minimal = true;});
# True NixOS nodes can define additional guest nodes that are built # True NixOS nodes can define additional guest nodes that are built
# together with it. We collect all defined guests from each node here # together with it. We collect all defined guests from each node here
# to allow accessing any node via the unified attribute `nodes`. # to allow accessing any node via the unified attribute `nodes`.
guestConfigs = flip concatMapAttrs self.nixosConfigurations (_: node: guestConfigs = flip concatMapAttrs config.nixosConfigurations (_: node:
flip mapAttrs' (node.config.guests or {}) ( flip mapAttrs' (node.config.guests or {}) (
guestName: guestDef: guestName: guestDef:
nameValuePair guestDef.nodeName ( nameValuePair guestDef.nodeName (
if guestDef.backend == "microvm" if guestDef.backend == "microvm"
then node.config.microvm.vms.${guestName}.config then node.config.microvm.vms.${guestName}.config
else node.config.containers.${guestName}.nixosConfiguration else node.config.containers.${guestName}.nixosConfiguration
) )
)); ));
in {
inherit # All nixosSystem instanciations are collected here, so that we can refer
hosts # to any system via nodes.<name>
guestConfigs nodes = config.nixosConfigurations // config.guestConfigs;
nixosConfigurations # Add a shorthand to easily target toplevel derivations
nixosConfigurationsMinimal "@" = mapAttrs (_: v: v.config.system.build.toplevel) config.nodes;
; };
} }

24
nix/iso.nix Normal file
View file

@ -0,0 +1,24 @@
{inputs, ...}: {
perSystem = {
pkgs,
system,
...
}: {
# For each major system, we provide a customized installer image that
# has ssh and some other convenience stuff preconfigured.
# Not strictly necessary for new setups.
packages.live-iso = inputs.nixos-generators.nixosGenerate {
inherit pkgs;
modules = [
./installer-configuration.nix
../config/ssh.nix
];
format =
{
x86_64-linux = "install-iso";
aarch64-linux = "sd-aarch64-installer";
}
.${system};
};
};
}

37
nix/pkgs.nix Normal file
View file

@ -0,0 +1,37 @@
{inputs, ...}: {
imports = [
(
{
lib,
flake-parts-lib,
...
}:
flake-parts-lib.mkTransposedPerSystemModule {
name = "pkgs";
file = ./pkgs.nix;
option = lib.mkOption {
type = lib.types.unspecified;
};
}
)
];
perSystem = {
pkgs,
system,
...
}: {
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
config.allowUnfree = true;
overlays =
import ../pkgs/default.nix
++ [
inputs.nix-topology.overlays.default
inputs.nixos-extra-modules.overlays.default
];
};
inherit pkgs;
};
}

9
nix/storage-box.nix Normal file
View file

@ -0,0 +1,9 @@
{inputs, ...}: {
perSystem = {pkgs, ...}: {
apps.setupHetznerStorageBoxes = import (inputs.nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") {
inherit pkgs;
nixosConfigurations = inputs.self.nodes;
decryptIdentity = builtins.head inputs.self.secretsConfig.masterIdentities;
};
};
}

View file

@ -0,0 +1,8 @@
age-encryption.org/v1
-> ssh-ed25519 1tdZKQ 0RQGWMKdlizirGx6o2XbuYXsefdLosiN/8qCokgA/ng
q73P4XM9fPNJnviWcy/ibcaarU5+CZpRQbJq250BhVs
-> t'#gZ,S-grease _M} rhid"l
sjt6COcSzS4Tem2vMhAxhp4ewtoylcYC0RUgdTc8U5X0spJL+ckRzxI7z1gqnQCp
dxdWGpYRQp0
--- k6eZqMwv+RK28dHW9Q+mYXUhkYFOTRtHu2eUHskOhJg
Ùàó^zîÊ$äFÑíPnžä×¢¢ýåМT¤³�Z;}E2øÍ™P¾zÒv^.±:óLÏ97´êÐr±º*¬œ¢2’Ó.U¬Œ3`

View file

@ -1,8 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 NwOpTA Rq5PyLLJdiYKkL+9vW+BS7sbFHBFoLwdxxWgPTH+0wU
wr1wRFGKYVgziwtzOm95pO4ZPnzF+pTuXlhedNd7HoU
-> Or$Ir-grease =Z{2b= (FvA*6m iV4)_
tePL0HELOtPx9UAsd0K7CvKv/56vQP++Y/PI5LMIl1IP7Opv2tiOqlB+R5bqWClO
lzV5jX+CVtQNABFgyDrQDfeqUgrw
--- YYlss0gmwNI2pNYbukrJl0hZpdCC8xKh+trLpAeTqFg
?1Ý7©ˆåˆ§¡êdÒÛ=2P»(û˜­Uuø/98ÊÖ.ËŒ¯;gyþúÄNö]ÄkdÞ|L/QJÞ…6ÀûMUÝ$Ørs9

30
topology/flake-module.nix Normal file
View file

@ -0,0 +1,30 @@
{inputs, ...}: {
imports = [
(
{
lib,
flake-parts-lib,
...
}:
flake-parts-lib.mkTransposedPerSystemModule {
name = "topology";
file = ./flake-module.nix;
option = lib.mkOption {
type = lib.types.unspecified;
};
}
)
];
perSystem = {pkgs, ...}: {
topology = import inputs.nix-topology {
inherit pkgs;
modules = [
./topology
{
inherit (inputs.self) nixosConfigurations;
}
];
};
};
}