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]>
100 lines
2.8 KiB
TOML
100 lines
2.8 KiB
TOML
[workspace]
|
|
resolver = "2"
|
|
members = [
|
|
"crates/core",
|
|
"crates/dhcp-proxy",
|
|
"crates/tftp",
|
|
"crates/http-api",
|
|
"crates/iso-store",
|
|
"crates/ipxe-assets",
|
|
"crates/webui",
|
|
"crates/openpxe",
|
|
]
|
|
|
|
[workspace.package]
|
|
version = "0.4.69"
|
|
edition = "2021"
|
|
rust-version = "1.95"
|
|
license = "MIT OR Apache-2.0"
|
|
repository = "https://gitea.milesward.dev/mward4/OpenPXE"
|
|
authors = ["OpenPXE contributors"]
|
|
|
|
[workspace.dependencies]
|
|
tokio = { version = "1.40", features = ["full"] }
|
|
tokio-util = { version = "0.7", features = ["io"] }
|
|
tokio-stream = { version = "0.1", features = ["sync"] }
|
|
futures = "0.3"
|
|
async-trait = "0.1"
|
|
|
|
dhcproto = "0.12"
|
|
socket2 = { version = "0.5", features = ["all"] }
|
|
bytes = "1.7"
|
|
nom = "7.1"
|
|
|
|
axum = { version = "0.7", features = ["macros", "multipart", "http2"] }
|
|
tower = "0.5"
|
|
tower-http = { version = "0.6", features = ["fs", "trace", "cors", "limit"] }
|
|
hyper = "1.4"
|
|
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "stream"] }
|
|
mime = "0.3"
|
|
mime_guess = "2.0"
|
|
|
|
serde = { version = "1.0", features = ["derive"] }
|
|
serde_json = "1.0"
|
|
toml = "0.8"
|
|
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
|
|
|
anyhow = "1.0"
|
|
thiserror = "1.0"
|
|
clap = { version = "4.5", features = ["derive", "env"] }
|
|
uuid = { version = "1.10", features = ["v4", "serde"] }
|
|
time = { version = "0.3", features = ["serde", "serde-human-readable", "formatting", "macros"] }
|
|
sha2 = "0.10"
|
|
hex = "0.4"
|
|
bcrypt = "0.15"
|
|
once_cell = "1.19"
|
|
parking_lot = "0.12"
|
|
rust-embed = { version = "8.5", features = ["include-exclude"] }
|
|
|
|
# v0.4.67: pure-Rust NFSv3 client. Replaces the (deleted-in-v0.4.65)
|
|
# kernel-mount NFS path with an in-process implementation that works
|
|
# in any container — no kernel modules, no CAP_SYS_ADMIN, no
|
|
# subprocess. Ships alongside the userspace SMB consumer; operators
|
|
# pick whichever protocol their NAS prefers.
|
|
nfs3_client = { version = "0.9", features = ["tokio"] }
|
|
nfs3_types = "0.5"
|
|
|
|
openpxe-core = { path = "crates/core" }
|
|
openpxe-dhcp-proxy = { path = "crates/dhcp-proxy" }
|
|
openpxe-tftp = { path = "crates/tftp" }
|
|
openpxe-http-api = { path = "crates/http-api" }
|
|
openpxe-iso-store = { path = "crates/iso-store" }
|
|
openpxe-ipxe-assets = { path = "crates/ipxe-assets" }
|
|
openpxe-webui = { path = "crates/webui" }
|
|
|
|
[workspace.lints.rust]
|
|
unsafe_code = "deny"
|
|
rust_2018_idioms = { level = "warn", priority = -1 }
|
|
|
|
[workspace.lints.clippy]
|
|
pedantic = { level = "warn", priority = -1 }
|
|
module_name_repetitions = "allow"
|
|
missing_errors_doc = "allow"
|
|
missing_panics_doc = "allow"
|
|
must_use_candidate = "allow"
|
|
doc_markdown = "allow"
|
|
items_after_statements = "allow"
|
|
cast_possible_truncation = "allow"
|
|
cast_lossless = "allow"
|
|
cast_sign_loss = "allow"
|
|
similar_names = "allow"
|
|
too_many_lines = "allow"
|
|
|
|
[profile.release]
|
|
lto = "thin"
|
|
codegen-units = 1
|
|
strip = "symbols"
|
|
opt-level = 3
|