• mward4 released this 2026-05-28 21:34:41 -04:00 | 31 commits to main since this release

    OpenPXE v0.4.68

    Bug-fix release addressing four issues from v0.4.67 field validation.

    1. NFS mount failed with MNT3ERR_ACCES even with the host IP allow-listed

    This is the big one. Operators added their UNAS Pro NFS export with
    the host IP correctly in the allow-list and still got
    connect failed: MNT3ERR_ACCES.

    Root cause: Linux kernel nfsd — which UniFi UNAS, Synology, TrueNAS,
    and essentially every appliance NAS run underneath — exports with the
    secure option by default. secure means the server only accepts
    mount/NFS requests whose TCP source port is privileged (< 1024). A
    client connecting from an ephemeral high port is denied at mount time,
    regardless of the allow-list.

    v0.4.67 deliberately connected from a non-privileged port on the
    mistaken assumption that uid 10001 couldn't bind low ports. But the
    OpenPXE binary carries CAP_NET_BIND_SERVICE (granted via setcap so
    it can bind the DHCP/TFTP/HTTP low ports as non-root), and that
    capability also lets it bind a privileged source port for an
    outbound connection.

    Fix: OpenPXE now connects from a privileged source port first (what
    every appliance NAS with default secure exports needs), and falls
    back to a non-privileged port for insecure exports or environments
    without the capability. Each attempt has its own connect timeout; a
    no-answer timeout on the first attempt skips the fallback so an
    unreachable server doesn't double your wait.

    For your UniFi UNAS Pro: with v0.4.68, server 192.168.1.51 +
    export /var/nfs/shared/isos (the full path the UNAS mount command
    shows — not just /isos) should now mount. No server-side change
    needed since your export uses the default secure option and OpenPXE
    now speaks it correctly.

    If a mount still fails, the error banner now distinguishes
    MNT3ERR_ACCES and spells out both checks: host IP in the allow-list,
    and adding insecure to the export if the server refuses privileged
    ports for some reason.

    2. Custom logo didn't update the top-left brand mark

    The WebUI brand mark and favicon were cache-busted only by the OpenPXE
    version (?v=0.4.67), which doesn't change when you upload a logo — so
    the browser kept serving the cached default mark.

    Fix: the branding store now carries a revision counter that bumps on
    every logo upload/clear and is woven into the brand-mark URL as a second
    cache-bust token. Upload a logo, the page reloads, the new mark appears
    immediately. Remove it, the default comes back. No hard refresh needed.

    About PXE-booting machines: this fixes the WebUI top-left mark. The
    PXE boot menu still shows the ASCII "OpenPXE" wordmark, not your
    uploaded image — painting a PNG in the iPXE menu requires an
    IMAGE_PNG-enabled iPXE build, which the stock boot.ipxe.org binaries
    don't include. The server-side compositor that prepares your logo for
    that paint (/branding/pxe-logo) is wired and ready; it goes live the
    moment the iPXE rebuild lands (queued for native x86_64 hardware). Until
    then, the boot menu wordmark is text-only by design.

    3. Disk-space card on the Dashboard

    The disk-space card from the Storage tab now also appears on the
    Dashboard, directly under the stat strip, so capacity is visible from
    the landing page. Same coloured bar, same 80%/95% warnings.

    4. NFS "Add share" button spacing

    The NFS shares form has a single row (vs the SMB form's two), so the Add
    share button sat flush against the input fields. Added top spacing to
    match the SMB card.

    Quality

    • 162 tests passing (+2: logo-revision bump, MNT3ERR_ACCES hint).
    • cargo clippy --workspace --all-targets -- -D warnings clean.

    Container image

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

    linux/amd64; static-musl /openpxe binary.

    Compatibility

    • Additive. No data-file format changes; branding.json gains a rev
      field that defaults to 0 on existing installs.
    • API and route surfaces unchanged.
    Downloads