feat: add nix server provision

This commit is contained in:
eric
2026-03-18 02:44:54 +01:00
parent 6f55289ca4
commit 19f9b0594a
19 changed files with 3114 additions and 30 deletions

1350
pkgs/helpers/cli.py Normal file

File diff suppressed because it is too large Load Diff

32
pkgs/helpers/default.nix Normal file
View File

@@ -0,0 +1,32 @@
{
lib,
writeShellApplication,
python3,
openbao,
openssh,
gitMinimal,
nix,
}:
writeShellApplication {
name = "nodeiwest";
runtimeInputs = [
python3
openbao
openssh
gitMinimal
nix
];
text = ''
export NODEIWEST_HELPER_TEMPLATES=${./templates}
exec ${python3}/bin/python ${./cli.py} "$@"
'';
meta = with lib; {
description = "Safe VPS provisioning helper for the NodeiWest NixOS flake";
license = licenses.mit;
mainProgram = "nodeiwest";
platforms = platforms.unix;
};
}

View File

@@ -0,0 +1,23 @@
{ lib, ... }:
{
# Generated by nodeiwest host init.
imports = [
./disko.nix
./hardware-configuration.nix
];
networking.hostName = "@@HOST_NAME@@";
networking.useDHCP = lib.mkDefault true;
time.timeZone = "@@TIMEZONE@@";
@@BOOT_LOADER_BLOCK@@
nodeiwest.ssh.userCAPublicKeys = @@SSH_CA_KEYS@@;
nodeiwest.tailscale.openbao = {
enable = @@TAILSCALE_OPENBAO_ENABLE@@;
};
system.stateVersion = "@@STATE_VERSION@@";
}

View File

@@ -0,0 +1,41 @@
{
lib,
...
}:
{
# Generated by nodeiwest host init.
# Replace the disk only if the provider exposes a different primary device.
disko.devices = {
disk.main = {
type = "disk";
device = lib.mkDefault "@@DISK_DEVICE@@";
content = {
type = "gpt";
partitions = {
BIOS = {
priority = 1;
name = "BIOS";
start = "1MiB";
end = "2MiB";
type = "EF02";
};
swap = {
size = "@@SWAP_SIZE@@";
content = {
type = "swap";
resumeDevice = true;
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,47 @@
{
lib,
...
}:
{
# Generated by nodeiwest host init.
# Replace the disk only if the provider exposes a different primary device.
disko.devices = {
disk.main = {
type = "disk";
device = lib.mkDefault "@@DISK_DEVICE@@";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1MiB";
end = "512MiB";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
swap = {
size = "@@SWAP_SIZE@@";
content = {
type = "swap";
resumeDevice = true;
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,5 @@
{ ... }:
{
# Placeholder generated by nodeiwest host init.
# nixos-anywhere will replace this with the generated hardware config.
}

View File

@@ -0,0 +1,3 @@
path "@@POLICY_PATH@@" {
capabilities = ["read"]
}

View File

@@ -0,0 +1,50 @@
from __future__ import annotations
import importlib.util
import sys
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[3]
CLI_PATH = REPO_ROOT / "pkgs" / "helpers" / "cli.py"
spec = importlib.util.spec_from_file_location("nodeiwest_cli", CLI_PATH)
cli = importlib.util.module_from_spec(spec)
assert spec.loader is not None
sys.modules[spec.name] = cli
spec.loader.exec_module(cli)
class HelperCliTests(unittest.TestCase):
def test_disk_from_device_supports_sd_and_nvme(self) -> None:
self.assertEqual(cli.disk_from_device("/dev/sda2"), "/dev/sda")
self.assertEqual(cli.disk_from_device("/dev/nvme0n1p2"), "/dev/nvme0n1")
def test_lookup_colmena_target_host_reads_existing_inventory(self) -> None:
flake_text = (REPO_ROOT / "flake.nix").read_text()
self.assertEqual(cli.lookup_colmena_target_host(flake_text, "vps1"), "100.101.167.118")
def test_parse_existing_vps1_configuration(self) -> None:
configuration = cli.parse_existing_configuration(REPO_ROOT / "hosts" / "vps1" / "configuration.nix")
self.assertEqual(configuration.host_name, "vps1")
self.assertEqual(configuration.boot_mode, "uefi")
self.assertTrue(configuration.tailscale_openbao)
self.assertEqual(configuration.state_version, "25.05")
self.assertTrue(configuration.user_ca_public_keys)
def test_parse_existing_vps1_disko(self) -> None:
disko = cli.parse_existing_disko(REPO_ROOT / "hosts" / "vps1" / "disko.nix")
self.assertEqual(disko.disk_device, "/dev/sda")
self.assertEqual(disko.boot_mode, "uefi")
self.assertEqual(disko.swap_size, "4GiB")
def test_render_bios_disko_uses_bios_partition(self) -> None:
rendered = cli.render_disko(boot_mode="bios", disk_device="/dev/vda", swap_size="8GiB")
self.assertIn('type = "EF02";', rendered)
self.assertIn('device = lib.mkDefault "/dev/vda";', rendered)
self.assertIn('size = "8GiB";', rendered)
if __name__ == "__main__":
unittest.main()