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>
This commit is contained in:
2026-05-03 20:55:14 -04:00
commit bda568b25c
39 changed files with 3067 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
FROM golang:1.23-bookworm AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /provisioning ./cmd/provisioning
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
dnsmasq \
openssh-client \
ipxe \
ca-certificates \
dmidecode \
curl \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /provisioning /usr/local/bin/provisioning
RUN mkdir -p /data /etc/provisioning/keys
EXPOSE 8080
VOLUME ["/data", "/etc/provisioning"]
ENTRYPOINT ["/usr/local/bin/provisioning"]
CMD ["-config", "/etc/provisioning/provisioning.yaml"]
+40
View File
@@ -0,0 +1,40 @@
server:
bind: "0.0.0.0:8080"
public_url: "http://192.168.1.100:8080"
database:
path: "./data/provisioning.db"
pxe:
enabled: true
interface: "eth0"
subnet: "192.168.1.0/24"
runtime_dir: "./data/pxe"
tftp_root: "./data/tftp"
dnsmasq_bin: "/usr/sbin/dnsmasq"
images:
dir: "./data/images"
proxmox:
existing_node: "192.168.1.10"
cluster_name: "homelab"
join_fingerprint: "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
credentials:
ssh_private_key_path: "/etc/provisioning/keys/id_ed25519"
ssh_public_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAEXAMPLE provisioning@homelab"
root_password_hash: "$6$rounds=5000$randomsalt$hashedpasswordhere"
infrastructure:
base_url: "http://192.168.1.50:3000"
room_id: 1
server_type_map:
minisforum-ms-01: 1
minisforum-um790: 2
timeout_seconds: 10
locks:
ttl_minutes: 60
server_types_path: "./server-types.yaml"
+22
View File
@@ -0,0 +1,22 @@
server_types:
minisforum-ms-01:
display_name: "Minisforum MS-01"
boot_disk: "/dev/nvme0n1"
management_nic: "enp2s0"
gpu: false
hostname_prefix: "pve-ms"
expected_nics:
- name: "enp2s0"
speed: "2500"
- name: "enp3s0"
speed: "2500"
minisforum-um790:
display_name: "Minisforum UM790 Pro"
boot_disk: "/dev/nvme0n1"
management_nic: "enp1s0"
gpu: true
hostname_prefix: "pve-um"
expected_nics:
- name: "enp1s0"
speed: "2500"