• mward4 released this 2026-05-28 12:56:52 -04:00 | 32 commits to main since this release

    OpenPXE v0.4.67

    NFS is back. Done right this time.

    TL;DR

    OpenPXE now supports both SMB and NFSv3 for remote ISO libraries,
    side-by-side. Pick whichever your NAS exposes. Both work in any
    container — no kernel modules, no CAP_SYS_ADMIN, no --privileged.
    Both are baked into the single OpenPXE image with zero additional
    dependencies for the operator to install.

    Why NFS, again

    The user asked for it after validating SMB works. Most NAS appliances
    (UniFi UNAS Pro, Synology, TrueNAS, OpenMediaVault) expose both
    protocols. Some shops prefer NFS for performance, some prefer SMB for
    the simpler auth model. v0.4.67 lets operators not have to choose.

    What's different from the v0.4.64 NFS path

    v0.4.64 shelled out to mount(8) and asked the kernel to attach the
    remote share. That required NFS client modules loaded on the host
    kernel. Containers on hosts without those modules — Unraid being the
    dominant case — failed regardless of container capabilities.

    v0.4.67 doesn't touch the kernel. The new NfsShareManager uses the
    nfs3_client Rust crate to
    speak NFSv3 over a plain TCP socket entirely in userspace. The crate
    runs in-process inside the openpxe binary — no subprocess, no
    mount.nfs, no PATH lookups. The kernel sees plain TCP traffic.

    Side-by-side with SMB

    Storage tab now has two cards stacked: SMB shares (v0.4.65,
    unchanged) and NFS shares (v0.4.67). Both forms use the same
    {error, stderr, hint} JSON error shape so the UI's "connect
    failed" banner renders identically for both protocols. Operators
    can run any mix of SMB and NFS shares simultaneously; the Available
    images table shows their ISOs intermixed with badges (smb:<id> /
    nfs:<id> / local).

    NFS has one architectural advantage over the SMB userspace path

    Range requests work. NFSv3 READ3 takes an explicit offset, so
    the HTTP ISO download handler can seek into the middle of a 5 GB
    ISO without reading what comes before. SMB-sourced ISOs still
    return 416 for ranges because smbclient -c 'get file -' is a
    sequential stream — that's a smbclient CLI limitation, not a
    protocol one. For PXE workloads (iPXE chain, casper sanboot,
    wimboot) it doesn't usually matter; for casper installers with
    iso-url=-style random-access reads, it does.

    What's the same

    • IsoStore::iso_path_for returns None for both SMB and NFS
      sources; the HTTP handler dispatches to the right share manager.
    • Hint translation is parallel: NT_STATUS_* for SMB, NFS3ERR_*
      for NFS, mapped to actionable operator-facing guidance.
    • Persistence: <work_dir>/smb_shares.json and
      <work_dir>/nfs_shares.json side by side.

    NFS auth (or lack thereof)

    NFSv3 uses AUTH_SYS — the client tells the server "I'm uid X" and
    the server decides whether to trust that. There's nothing for the UI
    to ask for, because access control is on the server side by client
    IP. The form is just two fields: server and export path.

    If your server demands privileged-port clients (sub-1024 source
    port), add insecure to the export in /etc/exports. OpenPXE runs
    as uid 10001 and can't bind sub-1024 source ports — the hint
    translation calls this out specifically when a MOUNT3 fails.

    Terminal

    The nfs command is back, this time as in-process:

    nfs list
    nfs add 10.0.0.5:/srv/isos
    nfs add 10.0.0.5:/srv/isos 2049
    nfs scan <id>
    nfs remove <id>
    

    The v0.4.64 nfs command (kernel mount) and the v0.4.67 nfs
    command (in-process via nfs3_client) share the name but not the
    mechanism. v0.4.64 was deleted in v0.4.65; this is the new
    implementation.

    Hints for the common NFSv3 errors

    Wire error UI hint
    NFS3ERR_ACCES The server rejected this client. Most likely your export is restricted by client IP — add this OpenPXE host (or its subnet) to the export's allowed-clients list on the server.
    NFS3ERR_NOENT / NFS3ERR_NOTDIR The export path doesn't exist on the server, or it isn't a directory. UniFi UNAS Pro exposes shares under /var/nfs/shared/<name>.
    NFS3ERR_STALE / NFS3ERR_BADHANDLE The server's view of the share changed under us. Re-scan; if that doesn't help, remove and re-add the share.
    connect timed out Verify IP, port (default 2049), and firewall.
    connection refused Make sure nfsd is running and (for v3) portmap on port 111 is reachable.
    mount denied /etc/exports may need insecure — OpenPXE runs as uid 10001 and uses non-privileged source ports.

    Quality

    • 160 tests passing (was 150 in v0.4.66, +10).
    • cargo clippy --workspace --all-targets -- -D warnings clean.
    • nfs3_client is at 0.9.0 (MIT/Unlicense, rust-version 1.88 — we're
      on 1.95).

    Image

    • gitea.milesward.dev/mward4/openpxe:0.4.67
    • gitea.milesward.dev/mward4/openpxe:latest

    linux/amd64; static-musl /openpxe binary. Image grows by the size
    of the linked nfs3_client + nfs3_types crates (small, <500 KiB on
    disk).

    What about v0.5

    v0.5 ships once a few more operators have validated SMB and NFS in
    production. Likely scope: an Audit/Logs tab, the iVentoy-style
    themed PXE menu (the rebuilt iPXE with IMAGE_PNG from native
    x86_64 hardware that's been queued since v0.4.61), and whatever
    operator-reported issues land between now and then. This v0.4.67 is
    the last feature drop before that consolidation.

    Compatibility

    • API is additive — every v0.4.66 client keeps working.
    • No data file format changes; auth.json, branding.json,
      sso.json, hosts.json, meta.json, smb_shares.json all load
      identically.
    • The Prometheus nfs_active gauge now sums SMB + NFS reachable
      shares (it had been re-purposed to track SMB only in v0.4.65;
      v0.4.67 brings it back to "external storage shares reachable"
      which matches the original v0.4.4 intent).
    Downloads