93cd2a42a90b7d907d75e080f254ef04233e16b4
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3cb651be65 |
v0.5.0: Wake-on-LAN, webhook notifications, Advanced tab, login logo, update check
Closes the v0.4.x chapter — NFS works end to end. Five additions: ## Wake-on-LAN (Hosts → Bound hosts) - New core::wol module: parse any MAC form, build the 102-byte magic packet, broadcast it. No special capability needed (ephemeral source port; SO_BROADCAST). Sends to the limited broadcast (255.255.255.255) AND the server's own subnet broadcast (computed from advertised IP + detected mask) so it reaches the right VLAN. - POST /api/hosts/:mac/wol — only fires for *bound* MACs (404 otherwise) so it's not an open packet sprayer. - Bound-hosts table grows a "Wake" button with inline Waking…/Sent ✓ state. ## Webhook notifications (Advanced tab) - core::notify: NotifyConfig + NotifyStore (notify.json), one provider at a time — Slack / Discord / Teams (incoming-webhook JSON) or SMTP. SMTP password is persisted but redacted on GET behind a __keep__ sentinel the UI round-trips so the secret never leaves the box. - http-api::notify: delivery — reqwest POST for chat (provider-shaped bodies), lettre for SMTP (rustls, STARTTLS/implicit TLS, no plaintext). 10s timeout; every send is best-effort. - GET/PUT /api/notify, POST /api/notify/test. - Fired fire-and-forget on the canonical "machine is imaging" boot event and on WoL — never blocks the boot path. ## UI: Advanced tab - New nav item. Holds the webhook config card and the API reference block (relocated from the bottom of Settings). ## UI: login/setup logo (FleetDM treatment) - /api/me now returns has_custom_logo + logo_rev (public bootstrap). The login, setup, and connection-error cards render the uploaded logo full-width with the "OpenPXE" wordmark dropped — matching the sidebar. ## About: update check + licenses - "Check for updates" button → GET /api/updates/check queries the Gitea releases API (derived from CARGO_PKG_REPOSITORY) and compares to the running version. Strictly on-demand — no background polling, keeps the air-gapped promise. - License card documents the MIT OR Apache-2.0 dual license with links, plus a note on bundled components (iPXE GPLv2/UBDL, samba, wimtools). Deps: lettre (SMTP, rustls) + reqwest gains the json feature. Both rustls so the static musl binary stays OpenSSL-free. Tests: 179 passing (+notify round-trip/redaction, webhook validation, WoL-unbound-404, WoL packet loopback, version-compare). clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> |
||
|
|
f6eddd59f8 |
v0.4.69: PNG boot-menu background (iPXE built from source), NFS AUTH_SYS, FleetDM logo
Three things, headlined by the long-blocked graphical PXE menu.
## 1. Graphical PXE boot background — the iVentoy feature, finally
iVentoy paints a PNG background on the PXE screen using stock iPXE
built with CONSOLE_FRAMEBUFFER + IMAGE_PNG + CONSOLE_CMD; the public
iPXE binaries omit those, so `console --picture` is a no-op on them.
We now build our own iPXE from upstream with that thin config delta
(deploy/ipxe/local/{general,console}.h).
The 8-release blocker was cc1 segfaulting when an amd64 gcc ran under
QEMU emulation on the arm64 build host. Fix: a new `ipxe-build`
Dockerfile stage pinned to $BUILDPLATFORM (native arch — no emulation)
that cross-compiles x86_64 iPXE with CROSS_COMPILE=x86_64-linux-gnu-.
The compiler runs native and emits x86_64. Validated end-to-end:
png.o + fbcon.o + pixbuf.o all compile and link (confirmed via the
linked-ELF symbol table, not just strings), ~112s, no segfault. Host
tools needed libc6-dev (dropped by --no-install-recommends; without
it the native host compile falls through to iPXE's freestanding
headers and dies on bits/stdint.h — fixed).
Server side:
- pxe_logo.rs is now a full-screen background compositor: a dark field
(matching the WebUI theme) with the operator's uploaded logo across
the top, or — with no upload — a default OpenPXE rainbow disc drawn
with pure pixel math (no font/SVG deps). Always 1024x768 (iPXE
doesn't scale; this is the universal mode). WebP/JPEG/GIF/PNG in,
PNG out (iPXE only eats PNG).
- /branding/pxe-logo always returns a PNG now (default when no logo,
default when SVG) so the menu always has a background.
- render_menu uses `console --picture … --top 290 || console`: paints
the background and reserves the logo band on PNG-capable binaries
(x86_64 UEFI), cleanly falls back to text on the others. The ASCII
wordmark is GONE.
Only x86_64 UEFI is built from source (host-arch-agnostic cross build);
BIOS/i386/arm64 keep upstream-fetched no-PNG binaries + text fallback.
Modern clients are overwhelmingly x86_64 UEFI.
## 2. NFS AUTH_SYS credential — fixes NFS3ERR_ACCES
v0.4.68's privileged-port fix got past MNT3ERR_ACCES (mount); operators
then hit NFS3ERR_ACCES on READDIR because nfs3_client defaults to
AUTH_NONE and virtually every server exports sec=sys. We now present an
AUTH_UNIX credential (uid 0 / gid 0): no_root_squash servers treat us
as root, root_squash servers map us to anon which reads any
world-readable ISO share. Kept fixed (no UI knob) to stay dead-simple.
Hint updated: a remaining NFS3ERR_ACCES is now a server-side
permission/squash issue, not IP/auth-flavor.
## 3. FleetDM-style full-width logo (top-left)
When a custom logo is uploaded the sidebar header drops the bundled
mark + "OpenPXE" wordmark and lets the logo span the header
(left-aligned, capped 200x50, contain). Rendered server-side via a
brand-class in index_html (has_custom_logo) so there's no flash of the
default. The bundled-default case is unchanged.
Tests: 164 passing. clippy -D warnings clean. iPXE build stage
validated in isolation before the full image build.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
||
|
|
bd791462be |
v0.4.63: SSO row alignment, themed checkbox, dropdown affordance
Three UI nits the operator caught on v0.4.62, plus the queued PXE-theme research note for the next release. - SSO header grid is now a 4-column form-row matching the Administrator account card column-for-column (display name / logo URL / metadata source / metadata URL). Switching to XML mode collapses column 4 and drops the multi-line textarea on its own full-width row below. - Native form chrome (checkboxes, scroll bars) follows the active OpenPXE theme via CSS `color-scheme`; the inline meta tag was forcing dark form controls in light mode, which is why the "Enable single sign-on" checkbox rendered as an opaque black square against the light panel. - Checkbox itself is now custom-styled (16x16 rounded square, accent fill + tick on :checked) so the chrome reads identically across both palettes and browsers, not just on whichever WebKit happens to honor `accent-color`. - <select> dropdowns get a hand-drawn chevron via background-image SVG; with `-webkit-appearance: none` the native arrow had disappeared, making "Metadata source" look squished next to the inputs beside it. - Update credentials + Save SSO settings buttons get explicit top margins so they sit clearly under their input rows instead of butting against the field beneath. - `docs/queued/ipxe-pxe-menu-theme-research.md` captures findings on how iVentoy paints its boot menu (iPXE `console --picture` with baked-in per-resolution PNGs, no EDID auto-detect) and the recommended Rust architecture for the follow-up release. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
f8bfab3823 |
v0.4.6: iVentoy-style PXE menu, top-right user menu, Settings touchups
PXE boot menu polish (iVentoy-inspired):
- render_menu now opens with a best-effort `console --picture
<base>/branding/pxe-logo || console` line so iPXE builds with PNG
support paint the operator's uploaded raster logo as the background.
- ASCII OpenPXE wordmark banner sits at the top of the menu in
`item --gap` lines — always visible on every iPXE build, including
the snponly/undionly variants without graphics console.
- New footer line above `choose`: "OpenPXE v0.4.6 - <arch label>",
where <arch label> is mapped from iPXE's ${buildarch}/${platform}
to "x86 BIOS", "x86_64 UEFI", or "arm64 UEFI". No URL, per brief.
- New GET /branding/pxe-logo route serves the operator's PNG / JPEG /
WebP / GIF as-is for iPXE to consume. SVG uploads 404 here (iPXE
can't rasterize SVG) — the always-visible ASCII wordmark stands in.
Route stays public after admin setup so iPXE clients (no cookies)
can fetch it.
UI:
- Removed the bottom-left "signed in as / Sign out" row.
- Added a person-icon button next to the theme toggle in the topbar.
Click opens a small popover with: Name (display only), Edit account
(jumps to Settings), Sign out. Esc + click-outside close it.
- Settings → Account card form chrome made consistent. The previous
`label.field` selector only styled type=text/number, leaving
password inputs with default browser chrome. Switched to a
negation-list selector that covers every typed input we use, plus
-webkit-appearance:none + a 1px focus ring. Light + dark mode both
show the same border/padding/focus state across all four account
fields.
- Settings → SSO card now renders display name, IdP logo URL (new),
and metadata source on one 3-column row. The metadata <select>
inherits the same chrome as the text inputs so it baseline-aligns
with them. SsoConfig grew an idp_logo_url field, persisted to
sso.json, length-capped and validated to http(s) only.
Quality:
- 138 tests passing (was 132 in v0.4.5). +1 IdP-logo-URL validation,
+1 PXE menu polish regression guard, +4 /branding/pxe-logo
integration tests covering missing-config / SVG-fallback / raster-
serve / post-auth public-allowlist cases.
- cargo clippy --workspace --all-targets clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
||
|
|
4a354a8664 |
v0.4.5: VMware UEFI fix, static musl binary, Forms auth + SSO config
VMware UEFI / Casper boot fix:
- Linux cmdline for Debian/Ubuntu/Mint/Pop!_OS/elementary now uses the
canonical Casper `iso-url=` option and `ds=nocloud`, matching the
fix Bootimus shipped in v0.1.67. The previous
`boot=casper netboot=url url=… ip=dhcp ---` form booted fine on
bare-metal UEFI but hung at "cloud-init running" on VMware guests
because subiquity / cloud-init can't reach a metadata datasource
through PXE.
Static binary (matches Bootimus v0.1.70):
- Dockerfile build stage now compiles against
x86_64-unknown-linux-musl. The resulting /openpxe has no glibc
dependency at all; the runtime stage still ships Debian slim for the
samba/wimtools/nfs-common shellouts, but a future scratch/distroless
variant is now a one-line swap. Cuts a class of "GLIBC_2.39 not
found" surprises on older RHEL/Rocky hosts.
Forms auth (Sonarr/Radarr-style):
- New AdminStore in openpxe-core: single admin record persisted to
<work_dir>/auth.json, bcrypt-hashed credentials, rotation requires
current password.
- New SessionStore in openpxe-http-api: in-memory UUID-keyed sessions
with 24h sliding TTL, openpxe_session HttpOnly cookie.
- Endpoints: POST /api/setup (first-run), POST /api/login, POST
/api/logout, GET /api/me, PUT /api/me/credentials (rotates and
revokes every other session).
- Auth middleware gates /api/* once the admin is configured;
passes through entirely until then (tests + fresh installs ride this
path). Allowlists PXE-essential paths (/boot.ipxe, /iso/*, /ipxe/*,
/api/queue/join, /api/queue/poll/*) so iPXE clients still work
without a cookie they can't send.
- WebUI: first-run setup card, login card, logout chip in the sidebar
footer, Account card in Settings for rotating creds. Auth screen is
fully styled (centered narrow card, matches Sonarr layout).
SSO config (FleetDM-shaped, storage-only):
- New SsoStore in openpxe-core: { enabled, idp_name, metadata,
metadata_url } persisted to <work_dir>/sso.json with size caps and
URL-scheme validation.
- Endpoints: GET /api/sso, PUT /api/sso. Validation: enabling SSO
without either metadata or metadata_url returns 400.
- WebUI: SSO card in Settings with a URL-vs-XML mode switch and an
inert "Sign in with X" button on the login screen while runtime
flow is pending. Per the brief: no Entity ID field (defaults to the
advertised public_base_url internally when SAML wiring lands).
Quality:
- 132 tests passing (was 106 in v0.4.4): +5 auth unit tests, +5 SSO
unit tests, +7 auth integration tests, +1 SSO integration test, +1
regression guard pinning the new Casper cmdline.
- cargo clippy --workspace --all-targets clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
||
|
|
55d74662c2 |
v0.4.4: Settings tab, API reference, ISO category, branding, disk space
Settings:
- New top-level Settings tab. Carries a placeholder for the planned
LDAP / OIDC / user-management work, the new branding controls, and
the API reference at the bottom.
- Custom logo upload (PNG/SVG/JPEG/WebP/GIF up to 2 MB) replaces the
bundled brand mark via /assets/logo.svg; bytes live at
<work_dir>/branding/ and survive restart. The original "OpenPXE
v<x.y.z>" pins to the sidebar footer for support.
- API reference rendered from a new GET /api/docs into a per-method
coloured pill list grouped by area.
ISO category (Storage):
- New IsoCategory { Os, Tools } on IsoMeta with PUT
/api/isos/:id/category. Storage table's Type cell becomes a
dropdown; selecting Tools moves the ISO into the Tools submenu next
to memtest / shell / NIC info and removes it from the OS Installers
family submenu. Family detection still drives BIOS/UEFI / kernel
args; only the menu placement changes.
Storage telemetry:
- New IsoStore::disk_usage (libc::statvfs, lives in iso-store so the
http-api crate stays #![forbid(unsafe_code)]) and GET
/api/storage/disk. The Storage tab now shows free/used/total for
the volume hosting the ISO directory with an 80%/95% colour ramp.
UI polish:
- Brand block in the sidebar now matches the topbar height exactly,
so the divider runs straight across the top of the app rather than
stepping; version label moved out of the brand and pinned to the
sidebar footer ("OpenPXE v0.4.4").
- Light-mode terminal: --terminal-bg + per-level text colours track
the active theme rather than being hard-coded dark.
- About: lead paragraph spans the full content width; new Docs row
links to https://openpxe.com/.
106 tests passing (was 89 in v0.4.1, +17 across branding unit tests
and new integration coverage for category / disk / docs / branding).
cargo clippy --workspace --all-targets clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
||
|
|
55ace0c25c |
v0.4.1: harden ISO uploads and beta UI polish
Add browser-safe chunked ISO uploads with progress, partial-file visibility, offset validation, and abort cleanup while keeping the legacy multipart endpoint for API clients. Record host-log validation coverage, keep the queue/status UI copy clean, move release docs to 0.4.1, and tighten the dark theme to a near-black Netbox-style palette. |
||
|
|
2a284afd02 |
v0.4.0: upload telemetry, host log, jet-black UI
- Upload reliability + diagnostics:
- api_upload_iso now distinguishes clean EOF from mid-stream errors;
a truncated multipart body (proxy buffer cap, network drop) returns
400 with the cause and a "try the LAN IP" hint instead of silently
finalising a partial file.
- Per-stage tracing (begin/MB-watermark/finish/abort) so a stuck
upload is debuggable from the Terminal tab.
- Web upload UI surfaces bytes/total, percent, throughput, ETA, and
maps 413/502/504/network-drop to actionable hints.
- New BootLog feature under Hosts:
- openpxe-core::BootLog — bounded in-memory ring (500) + append-only
JSONL on disk, recording (timestamp, mac, ip, target_id,
target_title) every time a boot entry script is served.
- iPXE per-entry chain URLs grow ?mac=${mac}; password prompt
submission carries it through; host-binding short-circuit uses the
bound MAC. ConnectInfo<SocketAddr> wired for peer IP capture (with
optional fallback so tower::oneshot in tests still works).
- GET /api/boot-log endpoint + Host log table under the Hosts tab.
- UI changes:
- Queue card header "Forge" → "Status".
- Removed Tinkerbell attribution sentence from Hosts tab.
- Topbar readiness chip moved into the sidebar footer as
"Service status: Ready / Advertised to clients / <url>", grouping
advertised PXE URL with operator-relevant status.
- Jet-black dark palette (#000 / #0a0a0a / #141414 / #1c1c1c)
replacing the blue-tinted ramp; terminal toolbar/input recoloured
to match.
- 89 tests passing (was 85 in v0.3.2); cargo clippy --workspace
--all-targets clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
||
|
|
bbdbb8df43 |
v0.3.2: OpenPXE naming cleanup and beta hardening
- remove remaining PXEForge/Gate/anvil wording from code, docs, UI, and deployment examples - fix Queue tab view wiring and rename queue-facing terminal/API copy - harden raw ISO Range handling, iPXE fallback lines, and WinPE SMB reconnect behavior - bump workspace and deployment examples to 0.3.2 |
||
|
|
e3452fe976 |
v0.3.0 — rebrand: PXEForge → OpenPXE, Gated → Queued Deployment
Full rename to match the openpxe.com brand. The product now reads as a
polished open-source project rather than a personal-tool nickname:
the anvil/forge metaphor is gone, replaced with the rainbow-horizon
brand mark from the marketing site.
## Naming changes
**PXEForge → OpenPXE** everywhere it's user-visible or developer-
facing:
- All 8 crate package names (`pxeforge-*` → `openpxe-*`).
- The bin crate dir + binary (`crates/pxeforge` → `crates/openpxe`,
`bin = "openpxe"`).
- Env vars: `PXEFORGE_*` → `OPENPXE_*` (no compat shim — pre-beta).
- Tracing targets: `pxeforge::*` → `openpxe::*`.
- Prometheus metrics: `pxeforge_*` → `openpxe_*` (pre-beta; nobody
has dashboards on these yet).
- Container image: `gitea.milesward.dev/mward4/openpxe:0.3.0`.
- All in-tree paths: `/var/lib/openpxe/{isos,work,smb}`,
`/usr/share/openpxe/ipxe`, `/etc/openpxe/...`.
- Unraid template renamed `pxeforge.xml` → `openpxe.xml`.
- README, NEXT_PHASE.md, architecture.md, comments, and the WebUI
brand string.
**Gated Deployment → Queued Deployment** as the user-facing concept:
- `Settings::TimeoutAction::GatedDeployment` →
`QueuedDeployment` (with `#[serde(alias = "gated_deployment")]`
so v0.2.0 settings.json files keep deserializing).
- Rust types: `Gate` → `QueueEntry`, `GateQueue` → `DeploymentQueue`,
`GateInner` → `QueueEntryInner`.
- File: `crates/core/src/gate.rs` → `crates/core/src/queue.rs`.
- HTTP routes: `/api/gate/*` → `/api/queue/*`. The JSON list key
flipped from `"gates"` to `"entries"` to match.
- iPXE shortcut: `/boot/_gate.ipxe` → `/boot/_queue.ipxe`. The
top-level menu's item id is now `queue` instead of `gate`.
- WebUI sidebar tab: "Forge Gate" → "Queue".
- Field on `AppState`: `gates` → `queue`.
## Brand assets
The anvil + forging-sparks logos are dropped:
- `logo.svg` is now a 24×24 medallion filled with the
`rainbow-horizon` gradient from openpxe.com (sliding hue rotation
via SMIL on the gradient stops, no JS needed).
- `anvil-forge.svg` renamed to `loader.svg` and rebuilt as a 64×64
louder version of the same disc — used for page-load transitions
and the imaging-progress widget. Adds a subtle scale pulse and a
white inner-glow so it has dimensionality on either theme.
## CSS rename
- `.forge-progress` → `.queue-progress`
- `.forge-progress .anvil` → `.queue-progress .mark`
- `@keyframes forge-sheen` → `queue-sheen`
- `.loader .anvil` → `.loader .mark`
- "Heating the forge…" loader text → "Loading…"
The rest of the layout is untouched. Light/dark theme tokens and the
sidebar/topbar structure carry over from v0.2.0 unchanged — the
brief was "keeping the UI similar."
## Validation
- `cargo build --workspace` — clean.
- `cargo clippy --workspace --all-targets` — no warnings.
- `cargo test --workspace` — **66 tests passing**, same as v0.2.0.
- Local smoke run against the rebuilt release binary verifies:
- `/boot.ipxe` emits `Queued Deployment` + `item queue` + chains
`/boot/_queue.ipxe`
- `/api/queue` returns `{count, entries}`
- `/metrics` emits `openpxe_queue_count` (renamed)
- `/assets/logo.svg` and `/assets/loader.svg` serve the new
rainbow brand SVGs
- `/api/status` reports version `0.3.0`
## Migration notes for operators on v0.2.0
- Container image path changed: pull
`gitea.milesward.dev/mward4/openpxe:0.3.0` (not `pxeforge:`).
- Bind mounts: `/var/lib/openpxe/{isos,work,smb}` (not `pxeforge`).
Move the host path or update the template.
- Env vars: replace `PXEFORGE_*` with `OPENPXE_*`. The Unraid
template at `deploy/unraid/openpxe.xml` is already updated.
- `settings.json` carries over transparently — the
`gated_deployment` value is accepted as an alias.
- HTTP API: any external scripts that hit `/api/gate/*` need to
switch to `/api/queue/*`. The JSON envelope key is `entries`
instead of `gates`.
|
||
|
|
6d3d636fad |
v0.2.0 — pre-beta: per-MAC bindings, /metrics, themes, animated forge
This is the bulk pre-beta cleanup pass. Bumps the workspace to 0.2.0.
Test count is 56 -> 66 (+10), clippy is fully clean across the
workspace (was several dozen warnings).
## New features
**Per-MAC host bindings** (Tinkerbell smee pattern). New
`HostBindings` registry maps a MAC -> preferred boot target, persisted
to <work_dir>/hosts.json. The DHCP reply now embeds `?mac=${mac}` in
the boot.ipxe URL; iPXE substitutes the literal MAC client-side, so
the HTTP layer can short-circuit straight to the bound target instead
of rendering the menu. Reserved menu shortcuts (`_local`, `_gate`,
`_tools_menu`) are valid targets too. New /api/hosts CRUD + a Hosts
tab in the sidebar.
**Prometheus `/metrics`** endpoint. Tiny lock-free implementation —
just AtomicU64s and a Display impl, no `prometheus` / `metrics-rs`
dep. Counters: DHCP replies (per arch label), DHCP declined, TFTP
transfers (per status), TFTP bytes, HTTP requests (per route).
Gauges: ISO count, client count, gate count, gate-imaging, NFS active
mounts, uptime, build info. Plain text exposition format,
text/plain;version=0.0.4 content-type, no auth (all metric values are
non-sensitive counts).
**Light + dark themes**. CSS tokens on `:root` and
`:root[data-theme=light]`, swap by toggle button (top-right) or `T`
hotkey. Persisted in localStorage; pre-paint inline script avoids
dark<->light flash. Light palette designed against the Netbox Labs
reference screenshot — near-white surfaces, soft grey dividers,
accent unchanged for brand consistency. Terminal pane stays dark in
both themes (it's a console, that's the right read).
**Animated SVG logo + forge widget**. New `logo.svg` is a refined
silver/grey anvil. New `anvil-forge.svg` adds rising sparks and a
pulsing underglow via SMIL — pure SVG, no GIF, no JS animation loop.
Used:
- in the **forge progress** widget on Dashboard + Forge Gate, paired
with a `linear-gradient(warn -> accent)` bar with a moving sheen;
goes idle (greyscale, no sheen) at zero imaging load
- in the page-load `<div class=loader>` that replaces the old
"Loading..." text
## Code cleanup pass
`cargo clippy --workspace --all-targets` is now warning-free. Spot
fixes across the tree:
- `format!()`-into-`String` -> `std::fmt::Write::write!`
- manual reverse comparators -> `Reverse`
- `map_or(false, ...)` -> `is_some_and`
- redundant closures -> method references
- `r#"..."#` raw strings without `"` -> `r"..."`
- `std::io::Error::new(Other, ...)` -> `Error::other`
- `as i32` on `c.id()` -> `cast_signed()`
- merged identical match arms
## Windows workflow validation
New integration test synthesizes an ISO9660 with the SOURCES\\BOOT.WIM
sentinel, uploads it, asserts:
1. introspection labels it `windows_pe` with has_boot_wim=true,
2. the boot entry is `BootKind::Wimboot` with all five canonical
files (bootmgr, bootmgr.efi, bcd, boot.sdi, boot.wim),
3. the rendered iPXE script chains wimboot with `initrd --name`
entries for each file, and
4. NO trust-store strings appear in the rendered output: bcdedit,
testsigning, certutil, httpdisk, and test-signed are all
explicitly forbidden as a hard guarantee.
WinPE bootstrap (startnet.cmd) picks up the Bootimus v0.1.58 lessons:
explicit `net start Workstation` before `net use` to avoid the SMB
client lazy-init race, and surfaces errors instead of blind retries.
## Docs
architecture.md gains a "Phase 5" section explaining the host-bindings
+ metrics + theming + Windows-test work, plus a refreshed "deferred
to Phase 6" list (real-hardware integration, autounattend library,
distro profile manifest, WoL trigger, syslog receiver, IPv6).
README updates the status line, the "what it does" list, and adds
the new Hosts/Terminal tab names.
|
||
|
|
cc309da062 |
Initial commit: PXEForge Phases 1-4
Container-native PXE boot server in Rust, designed as a clean-room alternative to iVentoy that never touches the client OS trust store. This is the first commit of the project; it lands the full output of Phases 1, 2, 3, and 4 in one shot. ## Phase 1 — protocol stack - 8-crate workspace (core, dhcp-proxy, tftp, http-api, iso-store, ipxe-assets, webui, pxeforge bin). - DHCP proxy (RFC 4578): replies with boot info only, never leases — sidesteps CAP_NET_RAW. Architecture-aware bootfile selection from option 93 (BIOS, IA32, x64-UEFI alias 0x0007/0x0009, ARM64). - TFTP server with full OACK negotiation: blksize, tsize, windowsize. Without it a 1 MiB iPXE binary takes 2000 packets and unusably long. - Two-stage iPXE chain: firmware PXE -> TFTP iPXE binary -> iPXE re-DHCPs with user-class iPXE -> HTTP /boot.ipxe -> kernel+initrd. - HTTP server (axum) with byte-Range ISO streaming and an in-place ISO9660 lookup so kernel/initrd are served from inside the ISO without ever extracting it to disk. - Linux ISOs boot via kernel+initrd extraction (memdisk/sanboot fail for >1-2 GiB modern distros). Distro-family detection drives the cmdline (Debian/Ubuntu, RHEL/Fedora, openSUSE, Arch, Alpine). ## Phase 2 — UX + Windows - Hierarchical PXE menu (Default / Installers / Tools / Gated Deployment) generated from settings — no hand-written .ipxe paths surface in the UI. Number-key + letter hotkeys, BIOS+UEFI variants for some RHEL ISOs. - Gated Deployment "horse-race" queue: clients join, operator picks one ISO, every gate launches simultaneously via tokio::sync::Notify. - Bootimus-pattern Windows: WimPatcher injects a CRLF startnet.cmd into boot.wim so vanilla WinPE net-uses an SMB share and runs setup.exe. All Microsoft-signed; no test certs, no testsigning, no httpdisk.sys. SmbManager supervises smbd start/stop/SIGHUP. - Netbox-style dark UI, fully offline (no CDN, no external fonts). ## Phase 3 — MVP hardening - TFTP retransmit rewrite with explicit window tracking — UEFI SNP clients no longer hang on files that end mid-window. 4 new tests. - DHCP broadcast-flag honored per RFC 2131 §4.1. - Multi-arch container (linux/amd64 + linux/arm64). Entrypoint chowns bind-mounts as root then drops to uid 10001 via gosu. - /healthz + /readyz split from /api/status — readyz fails if no iPXE binaries are bundled. - pxeforge seed --from <path> CLI: same pipeline as web upload (slug, sha256, introspection, boot-entry). - All timestamps RFC 3339 (browser Date couldn't parse the 9-tuple). - Gate poll retains assignment until operator releases — clients that retry on transient network errors reuse the assignment instead of falling back to the menu. - Custom OpenShift SCC: hostNetwork + NET_BIND_SERVICE only, no NET_RAW. ## Phase 4 — UI restructure + remote storage - Web UI rebuilt around six tabs inspired by the iVentoy layout: Dashboard / Network / Forge Gate / Storage / Terminal / About. Old "Monitoring/Content/Configuration" sidebar groups are gone. - NFS share manager (crates/iso-store/src/nfs.rs): mount NFSv3 or NFSv4.1 shares as ISO sources instead of uploading every file into the PVC. New IsoSource enum on IsoMeta lets the store resolve Local vs NFS lazily. Persisted to <work_dir>/nfs.json; failed mounts surface in the UI rather than blocking startup. - Dockerfile gains nfs-common + iproute2; mounting NFS in-container also requires CAP_SYS_ADMIN. Documented in docs/architecture.md. - LogBus + tracing layer in core: 500-line ring buffer + broadcast channel feed an SSE endpoint at /api/log/stream. - Operator terminal at /api/terminal: whitelisted commands (status, isos, clients, gate, nfs, smb, log) — deliberately not a shell. Output mirrored onto the LogBus so the live tail and the terminal pane share one timeline. - Network tab: read-only nic_name / subnet_mask / gateway probed from `ip` at startup; only DNS server is editable. Editing IP/mask on a hot UI would silently break PXE for every client mid-boot. - Bootimus parity (releases v0.1.55 -> v0.1.62): amber row tint on un-bootable ISOs with inline reasons, dashboard "won't boot" panel. ## Tests 56 tests passing across the workspace: - 16 core (LogBus, gate, settings, arch, client) - 1 dhcp-proxy (raw option-93 extraction) - 8 http-api unit (range parsing, terminal split/format) - 13 http-api integration (gated deployment, range, settings, NFS, terminal, log SSE, network endpoint, ui assets, no-external-urls) - 12 iso-store (introspect, slugify, smb, windows wim, NFS options) - 6 tftp (RRQ parsing, plan_window edges) cargo build --workspace and cargo clippy --workspace --all-targets both finish clean (warnings only, no errors). |