refactor(metal): install nodes with nixie

This commit is contained in:
Khue Doan
2026-09-08 09:09:20 +07:00
parent 779a151c89
commit 76512cc1e1
6 changed files with 118 additions and 137 deletions

View File

@@ -4,16 +4,28 @@
KUBECONFIG = $(shell pwd)/metal/kubeconfig.yaml
KUBE_CONFIG_PATH = $(KUBECONFIG)
PXE_INTERFACE ?= eth0
PXE_ADDRESS = $(shell ip -4 -o address show dev $(PXE_INTERFACE) scope global | awk '{ sub(/\/.*/, "", $$4); print $$4 }')
SSH_KEY = ${HOME}/.ssh/id_ed25519
default: metal system external smoke-test post-install clean fmt
default: metal system external smoke-test post-install fmt
configure:
./scripts/configure
git status
metal:
@echo 'Running PXE server as root for privileged ports'
sudo nix run .#homelabInstall
@test -n "${PXE_ADDRESS}" || { \
echo "${PXE_INTERFACE} has no IPv4 address" >&2; \
exit 1; \
}
sudo env "PATH=$$PATH" nixie \
--address "${PXE_ADDRESS}" \
--installer .#nixosConfigurations.installer \
--flake . \
--hosts metal/hosts.json \
--install-ssh-key "${SSH_KEY}" \
--deployment-ssh-key "${SSH_KEY}"
system:
make -C system
@@ -47,4 +59,3 @@ git-hooks:
fmt:
treefmt
cd tools && go fmt ./...

61
flake.lock generated
View File

@@ -38,7 +38,64 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixie",
"nixpkgs"
]
},
"locked": {
"lastModified": 1770585520,
"narHash": "sha256-yBz9Ozd5Wb56i3e3cHZ8WcbzCQ9RlVaiW18qDYA/AzA=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "1201ddd1279c35497754f016ef33d5e060f3da8d",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixie": {
"inputs": {
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1788757556,
"narHash": "sha256-rKm0QAWDoV2g3NRXqy/R8N9eGlB6pefXWa/5Yu7s1w4=",
"owner": "khuedoan",
"repo": "nixie",
"rev": "6c494d642297a2f1dee17cfd7f6aba56bb4efd69",
"type": "github"
},
"original": {
"owner": "khuedoan",
"repo": "nixie",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1779102034,
"narHash": "sha256-vZJZjLo513IeI8hjzHFc6TDezUd4uCE2Eq4SNO3DNNg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "687f05a9184cad4eaf905c48b63649e3a86f5433",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1788690626,
"narHash": "sha256-+v4I4LawmRD/mVxO7QIAerRrCkElp3YImzWkkUnvOTg=",
@@ -57,8 +114,8 @@
"root": {
"inputs": {
"disko": "disko",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
"nixie": "nixie",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {

View File

@@ -3,48 +3,29 @@
nixpkgs = {
url = "github:nixos/nixpkgs/nixos-26.05";
};
flake-utils = {
url = "github:numtide/flake-utils";
};
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nixie = {
url = "github:khuedoan/nixie";
};
};
outputs =
{
self,
nixpkgs,
flake-utils,
disko,
nixie,
...
}:
(flake-utils.lib.eachDefaultSystem (
system:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
installer = (import ./metal { inherit nixpkgs disko; }).installer;
build = installer.config.system.build;
homelabInstall = pkgs.buildGoModule {
pname = "homelab-install";
version = "0.1.0";
src = ./tools;
# TODO better way to build this shit
vendorHash = "sha256-rTJt3UWRUyhRDx1Sdno0fFBYMb4RPtzB7Z7sg45ZJ8o=";
postInstall = ''
wrapProgram $out/bin/homelab-install \
--add-flags "-kernel ${build.kernel}/bzImage" \
--add-flags "-initrd ${build.netbootRamdisk}/initrd" \
--add-flags "-init ${build.toplevel}/init" \
--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.nixos-anywhere ]}
'';
nativeBuildInputs = [ pkgs.makeWrapper ];
};
in
{
devShells.default = pkgs.mkShell {
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
dyff
gnumake
@@ -57,19 +38,13 @@
nixos-rebuild
openssh
opentofu
] ++ [
nixie.packages.${system}.default
];
};
packages = {
homelabInstall = homelabInstall;
nixosPxeServer = homelabInstall; # Alias for backwards compatibility
default = homelabInstall;
};
}
))
// {
nixosConfigurations = import ./metal {
inherit nixpkgs disko;
inherit nixpkgs disko nixie;
};
};
}

View File

@@ -1,9 +1,10 @@
{ nixpkgs, disko }:
{ nixpkgs, disko, nixie }:
{
installer = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
nixie.nixosModules.nixie-agent
./installer.nix
];
};

8
metal/hosts.json Normal file
View File

@@ -0,0 +1,8 @@
{
"metal1": {
"mac_address": "00:23:24:d1:f3:f0"
},
"metal2": {
"mac_address": "00:23:24:e7:04:60"
}
}

View File

@@ -1,86 +1,15 @@
{
pkgs,
lib,
config,
modulesPath,
...
}:
{ modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
];
networking.hostName = "nixos-installer";
services.openssh.enable = true;
installer.cloneConfig = false;
# Set root password to "nixos-installer" for initial SSH access
users.users.root = {
password = "nixos-installer";
initialHashedPassword = lib.mkForce null;
openssh.authorizedKeys.keys = [
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN5ue4np7cF34f6dwqH1262fPjkowHQ8irfjVC156PCG"
];
};
environment = {
systemPackages = with pkgs; [
btop
];
};
systemd.services."installer-callback" =
let
reportScript = pkgs.writeShellScript "installer-callback.sh" ''
set -euo pipefail
# Wait for default route to be ready
echo "Waiting for network to be ready..."
while true; do
if ${pkgs.iproute2}/bin/ip route show default > /dev/null 2>&1; then
iface=$(${pkgs.iproute2}/bin/ip route show default | ${pkgs.coreutils}/bin/cut -d ' ' -f 5)
if [ -n "$iface" ]; then
echo "Network is ready: interface=$iface"
break
fi
fi
sleep 1
done
mac=$(cat /sys/class/net/$iface/address)
# Get PXE API server from kernel command line
if [ ! -f /proc/cmdline ]; then
echo "Error: /proc/cmdline not found"
exit 1
fi
pxe_api=$(${pkgs.gnugrep}/bin/grep -oP 'pxe_api=\K[^ ]+' /proc/cmdline || true)
if [ -z "$pxe_api" ]; then
echo "Error: pxe_api parameter not found in kernel command line"
echo "Kernel command line: $(cat /proc/cmdline)"
exit 1
fi
echo "Using PXE API server from kernel cmdline: $pxe_api"
echo "Reporting MAC address: $mac"
${pkgs.curl}/bin/curl -sf -X POST "http://$pxe_api/report" \
--data-urlencode "mac=$mac"
'';
in
{
description = "Report IP address after PXE boot";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = [ reportScript ];
};
wantedBy = [ "multi-user.target" ];
};
# TODO
# system.stateVersion = config.system.nixos.version;
system.stateVersion = "25.05";
}