Advance forge rollout, Ethereum rails, and NBC sources

This commit is contained in:
every.channel 2026-04-01 15:58:49 -07:00
parent be26313225
commit 7d84510eac
No known key found for this signature in database
88 changed files with 11230 additions and 302 deletions

View file

@ -0,0 +1,377 @@
{ lib, config, pkgs, ... }:
let
cfg = config.services.every-channel.ipxe-qemu;
scriptsRoot = ../..;
firstDns = lib.head cfg.boot.userNet.dnsServers;
qemuBin = "${cfg.package}/bin/qemu-system-x86_64";
qemuImgBin = "${cfg.package}/bin/qemu-img";
bootNetdevArg = lib.escapeShellArg "user,id=boot0,dns=${firstDns},hostname=${cfg.boot.userNet.hostname},tftp=${cfg.boot.userNet.tftpDir},bootfile=${cfg.boot.userNet.bootFilename}";
bootDeviceArg = lib.escapeShellArg "${cfg.boot.userNet.model},netdev=boot0";
lanNetdevArg = lib.escapeShellArg "tap,id=lan0,fd=3";
lanDeviceArg = lib.escapeShellArg "${cfg.lan.model},netdev=lan0";
driveArg = lib.escapeShellArg "if=virtio,format=qcow2,file=${cfg.disk.path}";
effectiveChainUrl =
if cfg.boot.chainUrl != null
then cfg.boot.chainUrl
else "http://10.0.2.2:${toString cfg.boot.http.port}/netboot.ipxe";
bootScript = pkgs.writeText "every-channel-qemu.ipxe" ''
#!ipxe
dhcp
set dns ${firstDns}
chain ${effectiveChainUrl} || shell
'';
bootAsset = pkgs.ipxe.override {
embedScript = bootScript;
additionalTargets = {
"bin/undionly.kpxe" = null;
};
firmwareBinary = "undionly.kpxe";
};
bootExtraArgs = lib.concatMapStringsSep "\n" (arg: " cmd+=(${lib.escapeShellArg arg})") cfg.extraArgs;
runner = pkgs.writeShellApplication {
name = "every-channel-ipxe-qemu";
runtimeInputs = [
pkgs.coreutils
pkgs.iproute2
cfg.package
];
text = ''
set -euo pipefail
state_dir=${lib.escapeShellArg cfg.stateDir}
tftp_dir=${lib.escapeShellArg cfg.boot.userNet.tftpDir}
boot_file=${lib.escapeShellArg cfg.boot.userNet.bootFilename}
disk_path=${lib.escapeShellArg cfg.disk.path}
disk_size=${lib.escapeShellArg cfg.disk.size}
lan_ifname=${lib.escapeShellArg cfg.lan.macvtap.name}
enable_kvm=${lib.escapeShellArg (lib.boolToString cfg.enableKvm)}
enable_lan=${lib.escapeShellArg (lib.boolToString cfg.lan.enable)}
serve_http=${lib.escapeShellArg (lib.boolToString cfg.boot.http.enable)}
http_bind_ip=${lib.escapeShellArg cfg.boot.http.bindIp}
http_port=${toString cfg.boot.http.port}
http_root=${lib.escapeShellArg cfg.boot.http.root}
cleanup() {
if [[ "$enable_lan" == true ]]; then
ip link del "$lan_ifname" 2>/dev/null || true
fi
}
terminate() {
if [[ -n "''${http_pid:-}" ]]; then
kill "$http_pid" 2>/dev/null || true
wait "$http_pid" 2>/dev/null || true
fi
if [[ -n "''${qemu_pid:-}" ]]; then
kill "$qemu_pid" 2>/dev/null || true
wait "$qemu_pid" 2>/dev/null || true
fi
exit 0
}
trap cleanup EXIT
trap terminate TERM INT
install -d -m 0755 "$state_dir" "$tftp_dir" "$(dirname "$disk_path")"
install -m 0644 ${bootAsset}/undionly.kpxe "$tftp_dir/$boot_file"
if [[ "$serve_http" == true ]]; then
if [[ ! -d "$http_root" ]]; then
echo "error: boot HTTP root not found: $http_root" >&2
exit 1
fi
${pkgs.python3}/bin/python3 ${scriptsRoot}/scripts/netboot-http-server.py \
--bind-ip "$http_bind_ip" \
--port "$http_port" \
--root "$http_root" &
http_pid=$!
fi
if [[ ! -f "$disk_path" ]]; then
${qemuImgBin} create -f qcow2 "$disk_path" "$disk_size" >/dev/null
fi
cmd=(
${lib.escapeShellArg qemuBin}
-name ${lib.escapeShellArg cfg.name}
-machine ${lib.escapeShellArg cfg.machine}
-cpu ${lib.escapeShellArg cfg.cpu}
-smp ${toString cfg.vcpus}
-m ${toString cfg.memoryMiB}
-nographic
-boot ${lib.escapeShellArg cfg.boot.order}
-serial ${lib.escapeShellArg cfg.serial}
-device virtio-rng-pci
)
if [[ "$enable_kvm" == true ]]; then
cmd+=(-enable-kvm)
fi
cmd+=(
-netdev ${bootNetdevArg}
-device ${bootDeviceArg}
)
if [[ "$enable_lan" == true ]]; then
ip link del "$lan_ifname" 2>/dev/null || true
ip link add link ${lib.escapeShellArg cfg.lan.macvtap.interface} name "$lan_ifname" type macvtap mode ${lib.escapeShellArg cfg.lan.macvtap.mode}
ip link set "$lan_ifname" up
tap_index="$(< /sys/class/net/$lan_ifname/ifindex)"
exec 3<>"/dev/tap''${tap_index}"
cmd+=(
-netdev ${lanNetdevArg}
-device ${lanDeviceArg}
)
fi
cmd+=(
-drive ${driveArg}
)
${bootExtraArgs}
"''${cmd[@]}" &
qemu_pid=$!
wait "$qemu_pid"
'';
};
in
{
options.services.every-channel.ipxe-qemu = {
enable = lib.mkEnableOption "every.channel iPXE/QEMU boot VM";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.qemu_kvm;
description = "QEMU package providing qemu-system-x86_64 and qemu-img.";
};
name = lib.mkOption {
type = lib.types.str;
default = "every-channel-ipxe";
description = "QEMU guest name.";
};
machine = lib.mkOption {
type = lib.types.str;
default = "q35,accel=kvm";
description = "QEMU machine string.";
};
cpu = lib.mkOption {
type = lib.types.str;
default = "host";
description = "QEMU CPU model.";
};
enableKvm = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Use KVM acceleration when available.";
};
vcpus = lib.mkOption {
type = lib.types.ints.positive;
default = 2;
description = "Virtual CPU count.";
};
memoryMiB = lib.mkOption {
type = lib.types.ints.positive;
default = 4096;
description = "Guest memory in MiB.";
};
serial = lib.mkOption {
type = lib.types.str;
default = "mon:stdio";
description = "Serial/monitor wiring passed to QEMU.";
};
stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/every-channel/ipxe-qemu";
description = "Persistent state directory for qcow2 disk and boot assets.";
};
disk = {
path = lib.mkOption {
type = lib.types.str;
default = "${cfg.stateDir}/disk.qcow2";
description = "Persistent qcow2 disk path.";
};
size = lib.mkOption {
type = lib.types.str;
default = "16G";
description = "Size used when initializing the qcow2 disk.";
};
};
boot = {
order = lib.mkOption {
type = lib.types.str;
default = "order=n";
description = "QEMU boot order, defaulting to network first.";
};
chainUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Optional explicit iPXE chain target fetched by the guest; defaults to the local boot.http server.";
};
http = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Serve a host-local HTTP root for the guest netboot flow.";
};
bindIp = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "Bind address used for the host-local boot HTTP server.";
};
port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = "Port used for the host-local boot HTTP server.";
};
root = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Directory containing kernel/initrd/netboot.ipxe served to the guest.";
};
};
userNet = {
hostname = lib.mkOption {
type = lib.types.str;
default = "every-channel-ipxe";
description = "Hostname advertised on the user-mode boot network.";
};
dnsServers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "1.1.1.1" ];
description = "DNS servers used by the user-mode boot NIC; the first entry is applied.";
};
tftpDir = lib.mkOption {
type = lib.types.str;
default = "${cfg.stateDir}/tftp";
description = "TFTP directory used by the user-mode boot NIC.";
};
bootFilename = lib.mkOption {
type = lib.types.str;
default = "undionly.kpxe";
description = "Boot asset filename exposed on the user-mode boot NIC.";
};
model = lib.mkOption {
type = lib.types.str;
default = "e1000";
description = "NIC model used for the boot network.";
};
};
};
lan = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Attach a second NIC to a real LAN using macvtap.";
};
model = lib.mkOption {
type = lib.types.str;
default = "virtio-net-pci";
description = "NIC model used for the LAN attachment.";
};
macvtap = {
interface = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Host interface used as the lower device for macvtap.";
};
name = lib.mkOption {
type = lib.types.str;
default = "ecqemu0";
description = "macvtap link name created while the guest runs.";
};
mode = lib.mkOption {
type = lib.types.enum [
"private"
"vepa"
"bridge"
"passthru"
"source"
];
default = "bridge";
description = "macvtap mode used for the LAN attachment.";
};
};
};
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Additional arguments appended to the QEMU command.";
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.boot.userNet.dnsServers != [ ];
message = "services.every-channel.ipxe-qemu.boot.userNet.dnsServers must not be empty";
}
{
assertion = (!cfg.lan.enable) || (cfg.lan.macvtap.interface != null);
message = "services.every-channel.ipxe-qemu.lan.macvtap.interface must be set when lan.enable is true";
}
{
assertion = (!cfg.boot.http.enable) || (cfg.boot.http.root != null);
message = "services.every-channel.ipxe-qemu.boot.http.root must be set when boot.http.enable is true";
}
];
environment.systemPackages = [ runner ];
systemd.tmpfiles.rules = [
"d ${cfg.stateDir} 0755 root root -"
"d ${cfg.boot.userNet.tftpDir} 0755 root root -"
];
systemd.services.every-channel-ipxe-qemu = {
description = "every.channel iPXE QEMU VM";
after = [ "local-fs.target" "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = [
pkgs.coreutils
pkgs.iproute2
cfg.package
];
serviceConfig = {
Type = "simple";
ExecStart = "${runner}/bin/every-channel-ipxe-qemu";
Restart = "always";
RestartSec = 5;
WorkingDirectory = cfg.stateDir;
};
};
};
}