Commit Graph

14 Commits

Author SHA1 Message Date
josh e2dd78d8f9 Embed ISO in initrd for PXE boot with loop-mount wrapper
build-and-push / test (push) Successful in 35s
build-and-push / build-and-push (push) Successful in 1m8s
Instead of sanboot (which can't pass kernel params for automation),
switch back to kernel/initrd boot. The ISO is embedded in the initrd
as a CPIO append. A pxe-init wrapper script loop-mounts the ISO
before handing off to the original init, so the installer finds it
as a block device. Uses rdinit=/pxe-init kernel parameter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 12:11:18 -04:00
josh a8f8801a90 Switch to sanboot for PXE ISO delivery
build-and-push / test (push) Successful in 36s
build-and-push / build-and-push (push) Successful in 1m7s
Proxmox has no kernel parameter for HTTP ISO fetch. Instead, use
iPXE's sanboot command to present the ISO as a virtual CD over HTTP.
The installer finds it as a block device and boots normally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 11:23:48 -04:00
josh 81abb94806 Serve full ISO for PXE boot via proxmox-iso-url kernel param
build-and-push / test (push) Successful in 34s
build-and-push / build-and-push (push) Successful in 1m11s
The Proxmox installer needs the full ISO to access packages and
installer data. Previously the ISO was deleted after extracting
kernel+initrd. Now we keep it as original.iso and serve it via HTTP.
The iPXE script passes proxmox-iso-url=<url> so the installer
fetches the ISO over the network instead of scanning block devices.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 11:11:45 -04:00
josh 44c358a89b Fix initrd loading with explicit iPXE name binding
build-and-push / test (push) Successful in 34s
build-and-push / build-and-push (push) Successful in 1m14s
iPXE needs --name on the initrd command and initrd=<name> on the
kernel line to properly pass the initrd to the kernel. Without this,
the kernel never receives the initrd, causing VFS mount failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 11:03:03 -04:00
josh 846b6847a5 Fix kernel panic by adding ramdisk_size to iPXE kernel params
build-and-push / test (push) Successful in 35s
build-and-push / build-and-push (push) Successful in 1m12s
The Proxmox initrd is too large for the default ramdisk allocation,
causing VFS to fail mounting root. Add ramdisk_size=16777216 (16GB)
along with rw, quiet, and splash=verbose for proper installer boot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 10:55:34 -04:00
josh 5ff1cff7d4 Fix iPXE chainload loop by excluding iPXE from pxe-service
build-and-push / test (push) Successful in 37s
build-and-push / build-and-push (push) Successful in 1m12s
iPXE was stuck in a loop: boot iPXE -> DHCP -> get ipxe.0 again ->
boot iPXE -> repeat. Add tag:!ipxe to pxe-service directives so
iPXE clients get the HTTP script URL via dhcp-boot instead of being
served the bootloader again.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 10:23:49 -04:00
josh c3a1cf99f9 Switch to pxe-service for proxy DHCP boot and restore host filtering
build-and-push / test (push) Successful in 37s
build-and-push / build-and-push (push) Successful in 1m14s
dhcp-boot alone does not send PXE vendor extensions (option 43) that
PXE clients need in proxy DHCP mode. Switch to pxe-service directives
for initial PXE boot, keep dhcp-boot only for iPXE chainloading.
Create .0 symlinks for pxe-service filename convention. Restore
dhcp-ignore=tag:!known filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 23:04:29 -04:00
josh df78f881bb Remove dhcp-ignore filter to debug proxy DHCP non-response
build-and-push / test (push) Successful in 36s
build-and-push / build-and-push (push) Successful in 1m14s
dnsmasq sees PXE requests but never responds. Remove the known-host
filter to determine if tag matching is the issue or if the problem
is elsewhere in the proxy DHCP flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 22:35:29 -04:00
josh dfcf91c949 Fix dhcp-hostsfile to explicitly set known tag for PXE clients
build-and-push / test (push) Successful in 37s
build-and-push / build-and-push (push) Successful in 1m34s
Bare MACs in dhcp-hostsfile were not auto-setting the known tag in
proxy DHCP mode, causing dhcp-ignore=tag:!known to drop all requests.
Explicitly write set:known per host entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 22:08:48 -04:00
josh ba5440a481 Fix dnsmasq not responding to PXE clients and seed iPXE binaries
build-and-push / test (push) Successful in 42s
build-and-push / build-and-push (push) Successful in 1m17s
Remove tag:known filter from dhcp-range — in proxy DHCP mode the tag
filter prevents responses. dhcp-ignore=tag:!known still filters
unknown hosts. Also copy ipxe.efi and undionly.kpxe from the system
ipxe package into the TFTP root at startup so clients can actually
download the bootloader.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 22:01:01 -04:00
josh 05bb242f50 Fix dnsmasq crash by creating tftp-root dir and using subnet config
build-and-push / test (push) Successful in 38s
build-and-push / build-and-push (push) Successful in 1m22s
dnsmasq exited with status 3 because the tftp-root directory didn't
exist at startup. Also replaced hardcoded 192.168.1.0 in dhcp-range
with the configured subnet value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-13 21:47:07 -04:00
josh 4774600040 Add boot image management with ISO extraction and serving
build-and-push / test (push) Successful in 34s
build-and-push / build-and-push (push) Successful in 1m7s
Upload Proxmox ISOs via API or dashboard UI, extract kernel+initrd
using pure-Go iso9660 library, store on disk, and serve over HTTP
for PXE booting. Dynamic kernel/initrd filenames per image replace
the previous hardcoded paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-09 21:26:31 -04:00
josh b23ef64ee1 Use ephemeral SSH keys per rebuild instead of static config keys
build-and-push / test (push) Successful in 9m57s
build-and-push / build-and-push (push) Has been cancelled
Generate a fresh ed25519 key pair at rebuild time, inject the public key
into the Proxmox answer file, use the private key for cluster join over
SSH, then remove the key from both the remote host and the database.
This eliminates the need to manage static SSH keys in config/secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 21:09:22 -04:00
josh bda568b25c Initial implementation: host lifecycle + PXE + admin dashboard
Go service for Proxmox homelab cluster provisioning. Handles PXE boot,
Proxmox autoinstall (answer file generation), cluster join via SSH,
and Infrastructure API registration.

- Host state machine (registered → pxe_ready → installing → ready)
- dnsmasq supervisor with MAC-based allowlist
- iPXE script and Proxmox answer file generation
- First-boot phone-home → cluster join → infra registration
- Operation locking with expiry (409 on conflict)
- SSE event hub for real-time dashboard updates
- Admin dashboard (host grid, detail, registration form)
- Config-driven server types with hot-reload
- Docker deployment (multi-stage fat image)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 20:55:14 -04:00