Skip to content

feat(extensions): add netboot extension for TFTP+NFS diskless boot#9656

Open
iav wants to merge 7 commits intoarmbian:mainfrom
iav:enh/netboot-extension
Open

feat(extensions): add netboot extension for TFTP+NFS diskless boot#9656
iav wants to merge 7 commits intoarmbian:mainfrom
iav:enh/netboot-extension

Conversation

@iav
Copy link
Copy Markdown
Contributor

@iav iav commented Apr 11, 2026

Summary

Adds an opt-in netboot extension that produces a full network-boot payload — kernel, DTB, optional uInitrd, pxelinux.cfg and an NFS-exportable rootfs — from a regular Armbian build. For netboot the only thing that has to live on the device's local storage is U-Boot itself: the kernel and DTB come from TFTP, / is mounted over NFS, nothing else on mmc/eMMC/USB is touched during early boot.

Today ROOTFS_TYPE=nfs alone only gives a hybrid image (kernel+DTB still on SD/eMMC, only / over NFS). This PR keeps that path working and layers a real netboot flow on top via a new ROOTFS_TYPE=nfs-root.

What changes

  • lib/functions/configuration/main-config.sh — new ROOTFS_TYPE=nfs-root case branch, symmetric with the existing fs-f2fs-support / fs-btrfs wiring: the branch auto-enables the netboot extension so ROOTFS_TYPE=nfs-root is the single switch that selects the full netboot flow. check_filesystem_compatibility_on_host is skipped for both nfs and nfs-root — the host-side check is a sanity net for block-device targets and falsely rejects valid NFS configurations.

  • extensions/netboot/netboot.sh — new, directory-based extension. Directory layout (rather than a single extensions/netboot.sh file) exists so the long-form usage guide can live next to the code as README.md; inlining documentation of that size into the script body would be unwieldy. Hooks:

    • extension_prepare_config — validate variables, compute defaults for NETBOOT_TFTP_PREFIX / NETBOOT_NFS_PATH (shared by LINUXFAMILY/BOARD/BRANCH/RELEASE, or per-host when NETBOOT_HOSTNAME is set), normalize NETBOOT_CLIENT_MAC to the 01-<mac> PXELINUX form, fail fast on bad ROOTFS_COMPRESSION/ROOTFS_EXPORT_DIR combinations before debootstrap.
    • custom_kernel_config — enable ROOT_NFS, NFS_FS, NFS_V3, IP_PNP, IP_PNP_DHCP so root=/dev/nfs ip=dhcp works without an initrd.
    • post_customize_image — drop armbian-resize-filesystem.service (meaningless on NFS root) and /root/.not_logged_in_yet (the armbian-firstlogin interactive wizard blocks bring-up when there is no interactive console). armbian-firstrun.service stays — it only regenerates SSH host keys.
    • host_pre_docker_launch — bind-mount ROOTFS_EXPORT_DIR into the build container when it lives outside ${SRC}, so the single-step builder-as-NFS-server workflow works the same inside and outside Docker.
    • pre_umount_final_image — assemble the TFTP tree (Image/zImage, dtb/, uInitrd), write pxelinux.cfg/{default.example | 01-<mac>} with the right FDT/FDTDIR line and an explicit INITRD directive when uInitrd is present (U-Boot's PXE parser only loads an initramfs when the stanza names it), expose a netboot_artifacts_ready hook for userpatches that deploy to a real server.
  • lib/functions/image/rootfs-to-image.sh — two new controls for NFS-rootfs builds (both ROOTFS_TYPE=nfs and nfs-root):

    • ROOTFS_COMPRESSION=zstd|gzip|none (default zstd). zstd.tar.zst, gzip.tar.gz, none → no archive at all. Rejected early if none is set without ROOTFS_EXPORT_DIR. The tar | pv | compressor pipeline now runs in a set -o pipefail subshell so a broken archive step actually fails the build instead of producing a silently truncated file.
    • ROOTFS_EXPORT_DIR=/abs/path — also (or only) rsync the rootfs tree into this directory. Can point anywhere on the build host's filesystem — inside or outside the Armbian tree (the extension bind-mounts external paths into the Docker container automatically). If the path is an NFS mount or any other network filesystem, the build writes directly to the remote server with no intermediate archive. The rsync uses --delete so a re-used export dir stays in sync with the new build instead of accumulating stale files from previous runs. Combined with ROOTFS_COMPRESSION=none this turns deploy-to-NFS-server into a single build step.
    • ROOTFS_ARCHIVE_PATH is exported so downstream hooks (the new netboot_artifacts_ready) can reference the produced archive.
  • lib/functions/image/partitioning.shprepare_partitions skips the root partition entry for nfs-root the same way it does for nfs, and the SD-size sanity check no longer applies to either (there is no image file to size).

  • config/templates/nfs-boot.cmd.template — previously sunxi/arm32-only (zImage + bootz). Made arch-agnostic so the hybrid ROOTFS_TYPE=nfs path builds for arm64 boards too.

  • extensions/netboot/README.md — long-form guide: variable reference, server setup (tftpd-hpa + nfs-kernel-server), DHCP 66/67 config (OpenWRT + others), per-host / per-MAC deployments, firstrun vs firstlogin, end-to-end helios64 example, troubleshooting.

Variables (quick reference)

All optional. ROOTFS_TYPE=nfs-root alone gives you a shared-rootfs build with a pxelinux.cfg/default.example file.

Variable Default Purpose
NETBOOT_SERVER (empty) TFTP/NFS server IP. Empty → nfsroot= keeps ${serverip} literal for U-Boot to fill from DHCP siaddr.
NETBOOT_TFTP_PREFIX armbian/${LINUXFAMILY}/${BOARD}/${BRANCH}-${RELEASE} Path prefix under TFTP root.
NETBOOT_NFS_PATH /srv/netboot/rootfs/shared/... or /srv/netboot/rootfs/hosts/<hostname> Absolute NFS path used in nfsroot=.
NETBOOT_HOSTNAME (empty) Per-host rootfs under hosts/<hostname>/ — each machine owns its own writable copy.
NETBOOT_CLIENT_MAC (empty) When set, PXE config is written as 01-<mac> (per-MAC PXELINUX override). Accepts : or -, normalized to lowercase.
ROOTFS_COMPRESSION zstd zstd / gzip / none.
ROOTFS_EXPORT_DIR (empty) When set, rsync the rootfs tree here in addition to (or instead of) the archive.

Test plan

Validated end-to-end on helios64 (rockchip64, edge/resolute, ttyS2 @ 1500000), Armbian 26.05:

  • Baseline build (ROOTFS_TYPE=nfs-root NETBOOT_SERVER=192.168.1.125, shared NFS path, FDTDIR fallback for boards without BOOT_FDT_FILE, no hardcoded console=). 6:57 min, all artifacts correct.
  • Per-host + per-MAC (NETBOOT_HOSTNAME=helios64-a NETBOOT_CLIENT_MAC=aa:bb:cc:dd:ee:ff). pxelinux.cfg/01-aa-bb-cc-dd-ee-ff contains nfsroot=.../hosts/helios64-a. 7:44 min.
  • ROOTFS_COMPRESSION=gzip — produces .tar.gz (default zstd.tar.zst). On the helios64 rootfs: 503 MB gzip vs 460 MB zstd.
  • ROOTFS_COMPRESSION=none ROOTFS_EXPORT_DIR=... — single-step tree workflow, 1.5 GB tree in export dir, no archive produced. 5:17 min.
  • ROOTFS_COMPRESSION=none without ROOTFS_EXPORT_DIR — fails fast in extension_prepare_config before debootstrap, not hours later.
  • End-to-end boot test: TFTP tree deployed to tftpd-hpa + NFS rootfs via rsync to nfs-kernel-server. DHCP options 66/67 on OpenWRT. Helios64 cold boot → U-Boot bootflow scan -lb → TFTP → booti → kernel → ip_auto_config → NFS mount → systemd graphical.target → login prompt on ttyS2@1500000. No armbian-firstlogin wizard, no resize2fs errors, armbian-firstrun.service regenerates SSH host keys normally. Verified twice: once with archive workflow + manual unpack, once with tree workflow + rsync deploy.
  • helios4 (mvebu, armhf, U-Boot v2025.10) — second SoC family. PXE netboot: DHCP → TFTP (zImage + DTB) → bootz → kernel → NFS root → systemd → login prompt. No initrd needed (see notes below).
  • Other boards / other SoC families — review welcome, especially from boards with BOOT_FDT_FILE set (the FDTDIR vs FDT code path is exercised by helios64's missing BOOT_FDT_FILE, but a board with it set should also work).

Known issues found during helios4 testing (not blockers for this PR):

  • RD image overlaps OS image on mvebu: ramdisk_addr_r (0x2880000) is only 8 MB above kernel_addr_r (0x2080000), but zImage 6.12 is 8.1 MB → U-Boot refuses to boot with initrd. Workaround: omit INITRD from PXE config — kernel with CONFIG_ROOT_NFS=y mounts NFS root directly without initrd.
  • DNS not working after NFS boot: kernel ip=dhcp writes DNS to /proc/net/pnp but systemd-resolved doesn't read it → "No DNS servers known". Workaround: resolvectl dns <iface> <gateway>. Needs a networkd .network file or oneshot service in post_customize_image (future improvement).

Post-review update: architecture reworked after CodeRabbit #1 — the extension no longer forces ROOTFS_TYPE from inside extension_prepare_config (too late in the config lifecycle); instead a new ROOTFS_TYPE=nfs-root case branch in main-config.sh enables the extension, symmetric with existing filesystem-support extensions. pipefail on the archive pipeline (#4), rsync --delete on the export dir (#5), and an explicit INITRD directive when uInitrd is present (#2) are all in.

Post-review update (round 3): archive creation moved from the early if/else block to after pre_umount_final_image hooks so the tarball/export tree captures the fully finalized rootfs (includes update_initramfs output and all hook edits). Split out as a separate pre-feature commit — also fixes the same bug in the original ROOTFS_TYPE=nfs hybrid flow. Additionally: the netboot extension now sets BOOTSIZE=0 for nfs-root, preventing the phantom /boot fstab entry at its source; the compensating pre_umount_final_image__100_netboot_clean_fstab hook is gone.

Post-review update (round 4): config/templates/nfs-boot.cmd.template now wraps the DTB load in an if load ... ; then true; else echo FATAL; reset; fi block so a missing/wrong dtb/${fdtfile} aborts the boot with a clear message instead of continuing with an invalid ${fdt_addr_r} — consistent with the ramdisk and kernel handling on the following lines.

Related work

A companion PR to armbian/documentation will add Developer-Guide_Netboot.md with the short overview + variable reference; this extension's README.md is the long-form guide and is linked from that page.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Full netboot workflow: staged TFTP/NFS artifacts, per-host/per-MAC PXE entries, selectable rootfs compression (zstd/gzip/none), export-directory support, Docker/container handling, and a build hook to signal ready artifacts.
    • New ROOTFS_TYPE=nfs-root build mode with image/name suffix, export-oriented output, and adjusted post-build flow (no local image produced).
  • Bug Fixes / Reliability

    • Hardened early-boot args, simplified DTB/initrd/kernel selection and initrd failure handling; fstab cleanup and disabled resize to avoid NFS boot hangs.
  • Documentation

    • Comprehensive netboot guide with setup, deployment examples and troubleshooting.

@iav iav requested review from a team, EvilOlaf, TRSx80, igorpecovnik and littlecxm as code owners April 11, 2026 23:32
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 11, 2026

📝 Walkthrough

Walkthrough

Adds a netboot extension to produce TFTP/NFS boot artifacts and NFS-root deployments, integrates nfs-root into build flow (image/export/partitioning/config), and updates the U-Boot NFS boot script template to load kernel/DTB/initrd from the active distro boot partition with arm64-aware kernel selection.

Changes

Cohort / File(s) Summary
U-Boot NFS boot template
config/templates/nfs-boot.cmd.template
Rewrote bootargs to avoid hardcoded console= params; quote-check nfs_root; load DTB and initrd from active distro boot partition (${devtype} ${devnum}:${distro_bootpart}); fatal+reset on DTB load failure; simplify initrd failure handling; try Image+booti then fallback to zImage+bootz with appropriate fdt_high.
Netboot docs
extensions/netboot/README.md
New comprehensive guide describing ROOTFS_TYPE=nfs-root behavior, build variables/defaults, artifact staging layout, hook interface, TFTP/DHCP/NFS constraints, server setup examples, workflows, and troubleshooting.
Netboot extension script
extensions/netboot/netboot.sh
New extension: defaults/validation for netboot variables (NETBOOT_SERVER, HOSTNAME, MAC formatting, TFTP prefix, NFS path), validate ROOTFS_COMPRESSION, require ROOTFS_EXPORT_DIR when none, force BOOTSIZE=0 for nfs-root, enable kernel NFS options, disable resize/skip first-login in image customization, ensure export dir is mounted in container builds, collect kernel (prefer Image then zImage/vmlinuz), DTBs and optional uInitrd into TFTP tree, generate per‑MAC or default PXELINUX entries, build nfsroot= (use ${serverip} placeholder when NETBOOT_SERVER empty), export artifact context and call netboot_artifacts_ready.
Rootfs image/export handling
lib/functions/image/rootfs-to-image.sh
Add _nfsroot suffix for nfs-root; treat nfs-root like nfs for packaging control flow (defer archive/export to post-step); implement ROOTFS_COMPRESSION handling (`gzip
Partitioning & main config
lib/functions/image/partitioning.sh, lib/functions/configuration/main-config.sh
Recognize nfs-root alongside nfs when skipping root partition creation and when bypassing host FS compatibility checks; set FIXED_IMAGE_SIZE=256 for nfs-root and enable netboot extension during main configuration.

Sequence Diagram(s)

sequenceDiagram
    participant Builder as Armbian Builder
    participant Ext as Netboot Extension
    participant KernelCfg as Kernel Config
    participant ImgGen as Image Generator
    participant TFTP as TFTP Staging
    participant Hook as netboot_artifacts_ready Hook

    Builder->>Ext: triggered with ROOTFS_TYPE=nfs-root
    Ext->>Ext: normalize & validate vars (NETBOOT_SERVER, NETBOOT_CLIENT_MAC, paths)
    Ext->>KernelCfg: enable NFS-root kernel options
    Ext->>ImgGen: customize image (disable resize service, skip firstlogin)
    ImgGen->>ImgGen: build rootfs
    Ext->>ImgGen: create/archive or export rootfs based on ROOTFS_COMPRESSION/ROOTFS_EXPORT_DIR
    Ext->>TFTP: collect kernel (Image→zImage→vmlinuz), DTBs, optional uInitrd
    Ext->>TFTP: generate PXELINUX entries (per-MAC or default)
    Ext->>Hook: invoke netboot_artifacts_ready with artifact context
Loading
sequenceDiagram
    participant DHCP as DHCP Server
    participant Client as Target Device
    participant UBoot as U-Boot
    participant TFTP as TFTP Server
    participant NFS as NFS Server

    Client->>DHCP: request IP + boot options
    DHCP->>Client: reply (serverip, bootfile)
    Client->>UBoot: obtain bootfile (pxe/extlinux)
    UBoot->>TFTP: fetch pxelinux.cfg, kernel, dtb, uInitrd
    TFTP->>UBoot: deliver artifacts
    UBoot->>NFS: mount nfsroot (from kernel cmdline)
    NFS->>Client: provide root filesystem
    Client->>Client: kernel boots with NFS root
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 I hopped through scripts, templates, and docs,

Staged kernels, DTBs, and tidy boxocks.
PXE and NFS weaved netboot's tune,
Builder sang, U‑Boot hummed in tune.
A rabbit’s cheer — artifacts in bloom!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly describes the main feature being added: a netboot extension for TFTP+NFS diskless boot, which aligns with the comprehensive changes introducing ROOTFS_TYPE=nfs-root, the netboot extension framework, and related infrastructure.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added 05 Milestone: Second quarter release size/large PR with 250 lines or more Needs review Seeking for review Hardware Hardware related like kernel, U-Boot, ... Framework Framework components Documentation Documentation changes or additions labels Apr 11, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extensions/netboot/netboot.sh`:
- Around line 38-42: The function
extension_prepare_config__netboot_force_nfs_rootfs sets ROOTFS_TYPE too late (it
runs during do_extra_configuration) so NFS-specific branches in
do_main_configuration never see it; move the ROOTFS_TYPE assignment earlier by
ensuring extension_prepare_config__netboot_force_nfs_rootfs (or its logic) runs
before do_main_configuration—either call that function in the init/startup hook
that executes prior to main configuration (e.g., extension_init or top-level
script before do_main_configuration) or export/set declare -g ROOTFS_TYPE="nfs"
at script initialization so the global variable is in effect for
do_main_configuration and the NFS setup in
lib/functions/configuration/main-config.sh executes.
- Around line 147-149: The PXE staging copies ${MOUNT}/boot/uInitrd but never
references it in the generated extlinux.cfg, so U-Boot won't load the initramfs;
modify the netboot stanza generation to set an initrd_line variable when the
file exists (mirror how fdt_line is created — e.g. check for
"${MOUNT}/boot/uInitrd", set initrd_line="INITRD ${tftp_prefix_dir}/uInitrd")
and then include ${initrd_line} in the emitted PXE stanza alongside fdt_line so
the INITRD directive is present for U-Boot.

In `@extensions/netboot/README.md`:
- Around line 137-155: The README has multiple unlabeled fenced code blocks
(e.g., the directory tree block showing "/srv/netboot/" and other blocks around
lines 159-164, 171-175, 465-489, 544-547); update each triple-backtick fence to
include an appropriate info string (for example use sh, ini, or text as
appropriate) so markdownlint stops flagging them—locate the fences by searching
for the blocks that display the directory tree and configuration snippets and
add the matching language tag to each opening ``` line.

In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 82-93: The rsync into ROOTFS_EXPORT_DIR can leave stale files
behind when the export tree is reused; update the rsync invocation in
rootfs-to-image.sh (the run_host_command_logged rsync call) to include --delete
(and optionally --delete-excluded) so files removed from the source are removed
from "${ROOTFS_EXPORT_DIR}" as well; add the flag either into $rsync_ea or
directly in the rsync command invocation to ensure exported NFS root mirrors the
built image.
- Around line 69-76: The archive creation pipeline (tar … | pv … |
${archive_filter} > "${ROOTFS_ARCHIVE_PATH}") must be guarded with pipefail so
failures in tar or pv aren't masked by a later stage; wrap that pipeline in a
shell context with set -o pipefail (or enable set -o pipefail locally before
running the pipeline) so a nonzero exit from tar or pv will cause the script to
fail and propagate the error from creating ROOTFS_ARCHIVE_PATH; update the block
around display_alert/ tar / pv / ${archive_filter} to ensure pipefail is active
for that pipeline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fca3bef5-36a8-4aaa-81dd-645853e7579e

📥 Commits

Reviewing files that changed from the base of the PR and between fdef407 and 2393977.

📒 Files selected for processing (5)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/rootfs-to-image.sh

Comment thread extensions/netboot/netboot.sh Outdated
Comment thread extensions/netboot/netboot.sh
Comment thread extensions/netboot/README.md Outdated
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
@iav iav marked this pull request as draft April 11, 2026 23:50
iav added a commit to iav/armbian that referenced this pull request Apr 12, 2026
`nfs-root` is a new rootfs type distinct from the existing `nfs` hybrid
mode. Selecting it wires the `netboot` extension from the core
`ROOTFS_TYPE` dispatch in `do_main_configuration`, so callers no longer
need a separate `ENABLE_EXTENSIONS=netboot`. The legacy `nfs` branch
(kernel+DTB on local boot partition, `/` over NFS) is untouched — both
paths coexist until the hybrid mode's future is decided.

Core plumbing mirrors the `nfs` branch for all paths where local root
storage would be meaningless: partition layout skip
(`prepare_partitions`), archive/export gate and version suffix
(`rootfs-to-image.sh`), and the host-side filesystem compatibility
check in `main-config.sh`.

Extension hooks now key on `ROOTFS_TYPE=nfs-root` instead of guessing
from `nfs`, removing the `force ROOTFS_TYPE=nfs` shim that ran too
late relative to `do_main_configuration`.

Also folded in from CodeRabbit review on PR armbian#9656:
- pipefail around tar|pv|compressor so truncated archives no longer
  slip through on an intermediate stage failure
- `rsync --delete` on `ROOTFS_EXPORT_DIR` so stale files from a
  previous build don't linger in the NFS export tree
- explicit `INITRD` directive in extlinux when `uInitrd` is staged;
  U-Boot only loads an initramfs when the stanza names it
- README updated to document `ROOTFS_TYPE=nfs-root` as the single
  switch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rpardini
Copy link
Copy Markdown
Member

Very nice. With recent u-boot (2026.04, thanks to Kwiboo), one can enable LWIP networking stack for better TFTP performance (loading kernel and initramfs) -- there's also some TFTP Window Size stuff that can be tuned. U-boot with LWIP + u-boot's wget offers the best performance, but is not integrated in pxe or dhcp boot target AFAIK.

@iav
Copy link
Copy Markdown
Contributor Author

iav commented Apr 12, 2026

Thanks for the pointer! Let's get this merged first — iterating on something that works is the easy part.

@iav iav force-pushed the enh/netboot-extension branch from a76e4b2 to fec99ac Compare April 12, 2026 17:14
@iav iav added the Work in progress Unfinished / work in progress label Apr 12, 2026
@iav iav force-pushed the enh/netboot-extension branch 5 times, most recently from a10feb4 to 4ff6016 Compare April 14, 2026 17:14
@iav
Copy link
Copy Markdown
Contributor Author

iav commented Apr 14, 2026

@coderabbitai review

@iav
Copy link
Copy Markdown
Contributor Author

iav commented Apr 15, 2026

Pull my Helios64 to v2026.04 in #9675

@iav iav force-pushed the enh/netboot-extension branch 4 times, most recently from a61ff64 to dac19c8 Compare April 15, 2026 17:19
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
extensions/netboot/netboot.sh (1)

196-199: Minor nit: display mentions uInitrd unconditionally.

Line 197 logs "(${kernel_name}, dtb/, uInitrd)" even when no initrd was staged. Consider making this conditional for accuracy:

-	display_alert "${EXTENSION}: TFTP payload" "${NETBOOT_TFTP_PREFIX}/ (${kernel_name}, dtb/, uInitrd)" "info"
+	display_alert "${EXTENSION}: TFTP payload" "${NETBOOT_TFTP_PREFIX}/ (${kernel_name}, dtb/${initrd_line:+, uInitrd})" "info"

This is purely cosmetic — the build works correctly either way.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extensions/netboot/netboot.sh` around lines 196 - 199, The TFTP payload log
always mentions "uInitrd" even when none was staged; update the display_alert
call that prints "(${kernel_name}, dtb/, uInitrd)" so the ", uInitrd" fragment
is added only when an initrd is actually present. Locate the display_alert
invocation that uses NETBOOT_TFTP_PREFIX and kernel_name and change it to build
the message conditionally (e.g., test a known initrd variable or check for the
uInitrd file under the tftp output directory) and pass the composed string to
display_alert so the log accurately reflects whether an initrd was staged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@extensions/netboot/netboot.sh`:
- Around line 196-199: The TFTP payload log always mentions "uInitrd" even when
none was staged; update the display_alert call that prints "(${kernel_name},
dtb/, uInitrd)" so the ", uInitrd" fragment is added only when an initrd is
actually present. Locate the display_alert invocation that uses
NETBOOT_TFTP_PREFIX and kernel_name and change it to build the message
conditionally (e.g., test a known initrd variable or check for the uInitrd file
under the tftp output directory) and pass the composed string to display_alert
so the log accurately reflects whether an initrd was staged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 65912e55-3fae-4c23-9547-0d3d74ad0f90

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and dac19c8.

📒 Files selected for processing (5)
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh

@iav iav force-pushed the enh/netboot-extension branch 3 times, most recently from 5b8d583 to 809e52f Compare April 15, 2026 18:16
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extensions/netboot/netboot.sh`:
- Around line 107-112: The containment check for ROOTFS_EXPORT_DIR is too
permissive and matches paths like ${SRC}-netboot; update the condition in
netboot.sh to only accept either exact equality to ${SRC} or a true descendant
under ${SRC} by checking for "${SRC}/" as the prefix (for example: [[
"${ROOTFS_EXPORT_DIR}" == "${SRC}" || "${ROOTFS_EXPORT_DIR}" == "${SRC}/"* ]]).
Keep the rest of the block (declaring container_export_dir, display_alert, mkdir
-p and adding DOCKER_EXTRA_ARGS with ROOTFS_EXPORT_DIR) unchanged.
- Around line 176-183: The PXE FDT stanza uses BOOT_FDT_FILE verbatim which can
be a .dts name (causing netboot to request non-existent .dts), so update the
fdt_line logic in the netboot script to normalize .dts to .dtb: when
BOOT_FDT_FILE is set and not "none", strip a trailing ".dts" (if present) and
append ".dtb" before constructing fdt_line="FDT
${NETBOOT_TFTP_PREFIX}/dtb/${...}"; keep the existing fallback to
fdt_line="FDTDIR ${NETBOOT_TFTP_PREFIX}/dtb" when BOOT_FDT_FILE is empty or
"none". Ensure you reference BOOT_FDT_FILE, NETBOOT_TFTP_PREFIX and fdt_line in
the change so K3 boards that declare .dts work correctly.

In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 68-70: The rootfs archive and netboot outputs are being written
directly to "${DEST}/images" (see ROOTFS_ARCHIVE_PATH set when
rootfs_compression != "none") and the nfs-root branch returns before
move_images_to_final_destination() runs, so artifacts never get routed to
FINALDEST; change the logic to construct ROOTFS_ARCHIVE_PATH under
"${FINALDEST}/images" when FINALDEST is set (or invoke
move_images_to_final_destination() before returning from the nfs-root branch),
and apply the same treatment to the TFTP tree staging in
extensions/netboot/netboot.sh; ensure both places respect FINALDEST (and/or call
move_images_to_final_destination()) so downstream collection/publish phases see
the artifacts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1c567eda-e752-4284-b13e-eef93a2aa3f5

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 809e52f.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/functions/image/partitioning.sh
  • config/templates/nfs-boot.cmd.template

Comment thread extensions/netboot/netboot.sh Outdated
Comment thread extensions/netboot/netboot.sh
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
@iav iav force-pushed the enh/netboot-extension branch from 809e52f to 3e87696 Compare April 16, 2026 00:05
@armbian armbian deleted a comment from coderabbitai bot Apr 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@extensions/netboot/netboot.sh`:
- Around line 85-95: The current
post_customize_image__netboot_skip_firstlogin_wizard function unconditionally
removes /root/.not_logged_in_yet for nfs-root images, leaving devices booting
with default root/1234; change this to require explicit opt-in or a provisioning
artifact: update post_customize_image__netboot_skip_firstlogin_wizard to check a
clear opt-in flag (e.g., an environment variable like NETBOOT_SKIP_FIRSTLOGIN or
a builder config key) or the presence of a non-interactive credential
provisioning file before calling run_host_command_logged rm -f
"${SDCARD}/root/.not_logged_in_yet", and log the decision with EXTENSION so the
action is explicit.

In `@lib/functions/image/partitioning.sh`:
- Around line 124-125: Add a fail-fast check in partitioning.sh to reject the
combination of ROOTFS_TYPE == nfs-root with any storage extension that requires
a real root partition (e.g. the LVM extension); specifically, detect when
ROOTFS_TYPE is nfs-root and the LVM extension is enabled or present
(extensions/lvm.sh) and then error out with a clear message and non-zero exit
instead of leaving rootpart unset; reference ROOTFS_TYPE, rootpart, and
extensions/lvm.sh (which calls "parted ... set ${rootpart} lvm on") so
maintainers can find and fix the mismatch.

In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 76-80: The tar --exclude pattern fails because exclude_home
contains literal quotes, so when used in the pipeline tar receives
--exclude="/home/*" (including quotes) and the pattern doesn't match; fix by
constructing exclude_home without embedded quotes (use --exclude=/home/* or
--exclude="${HOME_DIR:-/home}/*" when defining exclude_home) and then pass the
variable unquoted in the tar invocation (keep $exclude_home as shown) so tar
gets the raw pattern; update the code that sets the exclude_home variable (and
any callers that build it) to remove surrounding single/double quotes so the
exclusion works when creating ROOTFS_ARCHIVE_PATH.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 374db431-d7e9-4286-8677-9385b8e02f2f

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 3e87696.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/functions/configuration/main-config.sh

Comment thread extensions/netboot/netboot.sh
Comment thread lib/functions/image/partitioning.sh
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
@iav iav force-pushed the enh/netboot-extension branch from 3e87696 to 2ab3495 Compare April 16, 2026 01:29
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/templates/nfs-boot.cmd.template`:
- Around line 27-36: The DTB is being loaded unconditionally with load
${boot_dev} ${fdt_addr_r} dtb/${fdtfile} which can silently fail; change it to
check the load result (like the kernel load if-block around load ${boot_dev}
${kernel_addr_r} and the ramdisk's "|| setenv ramdisk_addr_r \"-\"") by wrapping
the DTB load in an if load ...; then ...; else ...; fi block — on failure either
setenv fdt_addr_r "-" (or echo an explicit error message and abort/exit) so
downstream boot commands don't use an invalid ${fdt_addr_r}.

In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 55-102: The nfs-root archive/export is created too early (before
pre_update_initramfs and pre_umount_final_image hooks) so later rootfs changes
are not captured; move the entire block that sets ROOTFS_ARCHIVE_PATH and the
ROOTFS_EXPORT_DIR rsync/export logic so it runs after the final rootfs hooks
have executed but before the SD card is unmounted. Specifically, keep the
ROOTFS_COMPRESSION handling and the decision logic for
ROOTFS_ARCHIVE_PATH/ROOTFS_EXPORT_DIR, but relocate the tar+pv compression
pipeline (which writes ROOTFS_ARCHIVE_PATH) and the rsync export block (using
run_host_command_logged rsync ... "$SDCARD/" "${ROOTFS_EXPORT_DIR}/") to the
last point in the flow where "${SDCARD}" is still mounted and the hooks like
pre_update_initramfs and pre_umount_final_image have completed, ensuring those
hooks (e.g., pre_umount_final_image__100_netboot_clean_fstab) run before
snapshot/export.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb001f64-bdfa-4e81-bcd0-0da839216a2b

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 2ab3495.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/functions/configuration/main-config.sh

Comment thread config/templates/nfs-boot.cmd.template Outdated
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
extensions/netboot/netboot.sh (1)

131-141: Implementation is correct, but note the timing dependency.

The awk-based fstab cleanup is well-implemented — preserving comments while stripping non-comment /boot entries. However, this hook runs at hook priority 100 within pre_umount_final_image, which occurs after the rootfs archive/export in rootfs-to-image.sh (lines 55-102). The exported NFS root will still contain the /boot fstab entry unless the archive/export is moved later in the pipeline.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@extensions/netboot/netboot.sh` around lines 131 - 141, The fstab cleanup in
pre_umount_final_image__100_netboot_clean_fstab runs too late (after rootfs
export), so the exported NFS root still contains the /boot entry; move or run
this cleanup earlier (e.g., hook into the rootfs export stage or before the
rootfs archive/export in rootfs-to-image.sh) by changing the hook point or
priority so pre_umount_final_image__100_netboot_clean_fstab (or an equivalent
function) executes before the archive/export step that creates the NFS root
image.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@extensions/netboot/netboot.sh`:
- Around line 131-141: The fstab cleanup in
pre_umount_final_image__100_netboot_clean_fstab runs too late (after rootfs
export), so the exported NFS root still contains the /boot entry; move or run
this cleanup earlier (e.g., hook into the rootfs export stage or before the
rootfs archive/export in rootfs-to-image.sh) by changing the hook point or
priority so pre_umount_final_image__100_netboot_clean_fstab (or an equivalent
function) executes before the archive/export step that creates the NFS root
image.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f90feb58-8d96-4fa0-a2ad-ac09f76e5d6f

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 2ab3495.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
✅ Files skipped from review due to trivial changes (1)
  • config/templates/nfs-boot.cmd.template
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/functions/image/partitioning.sh
  • lib/functions/configuration/main-config.sh

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
config/templates/nfs-boot.cmd.template (1)

27-28: ⚠️ Potential issue | 🟡 Minor

Add error handling for DTB load to match ramdisk and kernel handling.

Line 27 loads the DTB unconditionally without checking for success. If ${fdtfile} is incorrect or the DTB file is missing, the script continues and boots with an invalid ${fdt_addr_r}, causing a confusing boot failure. This is inconsistent with line 28 (ramdisk fallback) and lines 31-36 (kernel if/else).

Consider wrapping the DTB load similarly:

if load ${boot_dev} ${fdt_addr_r} dtb/${fdtfile}; then
    # proceed
else
    echo "DTB load failed: dtb/${fdtfile}"
    # abort or fallback
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/templates/nfs-boot.cmd.template` around lines 27 - 28, The DTB is
being loaded unconditionally via the load ${boot_dev} ${fdt_addr_r}
dtb/${fdtfile} call which can leave ${fdt_addr_r} invalid if dtb/${fdtfile} is
missing; modify the template to check the load exit status similar to the
ramdisk and kernel handling: wrap the load ${boot_dev} ${fdt_addr_r}
dtb/${fdtfile} invocation in an if/then/else that echoes a clear error (e.g.,
"DTB load failed: dtb/${fdtfile}") and either aborts the boot or sets a safe
fallback for ${fdt_addr_r}; locate the DTB load line and update the surrounding
logic that references ${fdt_addr_r} and ${fdtfile} accordingly so failure is
handled consistently with the ramdisk and kernel branches.
lib/functions/image/rootfs-to-image.sh (1)

43-102: ⚠️ Potential issue | 🟠 Major

Snapshot timing: archive/export runs before final rootfs hooks.

This block executes at line 43-102, but pre_umount_final_image (line 150) runs later. The netboot extension's pre_umount_final_image__100_netboot_clean_fstab() removes the stale /boot fstab entry to prevent the 90-second dev-disk-by\x2duuid-...device wait on NFS boot — but that cleanup happens after this archive/export.

The exported rootfs will still contain the /boot fstab entry, potentially causing emergency-mode boots on NFS clients.

Consider moving the archive/export logic to after pre_umount_final_image but before umount_chroot_recursive (around line 161), or have the netboot extension perform its own export in pre_umount_final_image.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/functions/image/rootfs-to-image.sh` around lines 43 - 102, The
archive/export of the rootfs currently runs before the final rootfs hooks, so
the netboot hook pre_umount_final_image__100_netboot_clean_fstab() (which
removes the stale /boot fstab entry) runs too late; either move the ROOTFS
archive/export block (the logic that sets ROOTFS_ARCHIVE_PATH and the
ROOTFS_EXPORT_DIR rsync) to execute after the pre_umount_final_image hook but
before umount_chroot_recursive, or alternatively have the netboot extension
perform its own export inside pre_umount_final_image (so exports see the cleaned
fstab); update references to ROOTFS_ARCHIVE_PATH, ROOTFS_EXPORT_DIR, the
tar/rsync steps, and ensure pipefail/rsync flags remain intact when relocating
the block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@config/templates/nfs-boot.cmd.template`:
- Around line 27-28: The DTB is being loaded unconditionally via the load
${boot_dev} ${fdt_addr_r} dtb/${fdtfile} call which can leave ${fdt_addr_r}
invalid if dtb/${fdtfile} is missing; modify the template to check the load exit
status similar to the ramdisk and kernel handling: wrap the load ${boot_dev}
${fdt_addr_r} dtb/${fdtfile} invocation in an if/then/else that echoes a clear
error (e.g., "DTB load failed: dtb/${fdtfile}") and either aborts the boot or
sets a safe fallback for ${fdt_addr_r}; locate the DTB load line and update the
surrounding logic that references ${fdt_addr_r} and ${fdtfile} accordingly so
failure is handled consistently with the ramdisk and kernel branches.

In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 43-102: The archive/export of the rootfs currently runs before the
final rootfs hooks, so the netboot hook
pre_umount_final_image__100_netboot_clean_fstab() (which removes the stale /boot
fstab entry) runs too late; either move the ROOTFS archive/export block (the
logic that sets ROOTFS_ARCHIVE_PATH and the ROOTFS_EXPORT_DIR rsync) to execute
after the pre_umount_final_image hook but before umount_chroot_recursive, or
alternatively have the netboot extension perform its own export inside
pre_umount_final_image (so exports see the cleaned fstab); update references to
ROOTFS_ARCHIVE_PATH, ROOTFS_EXPORT_DIR, the tar/rsync steps, and ensure
pipefail/rsync flags remain intact when relocating the block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0a7f4755-8c5b-4e21-9ae9-1c6a9574bb2e

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 2ab3495.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/functions/configuration/main-config.sh
  • extensions/netboot/netboot.sh

@iav iav force-pushed the enh/netboot-extension branch from 2ab3495 to 29e7423 Compare April 16, 2026 18:27
…YPE=nfs

ROOTFS_TYPE=nfs produces a rootfs tarball via `tar cp ... | gzip` in
rootfs-to-image.sh and never mounts NFS on the build host. The NFS
client runs on the target's kernel at boot time, so host-side NFS
filesystem support is irrelevant. Additionally, the check runs inside
the Armbian docker launcher where /lib/modules is empty, causing
`modprobe nfs` to fail even when the host kernel has nfs.ko available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iav iav force-pushed the enh/netboot-extension branch from 29e7423 to b0550f6 Compare April 16, 2026 18:35
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/functions/image/rootfs-to-image.sh (1)

101-155: ⚠️ Potential issue | 🟠 Major

netboot_artifacts_ready still fires before the rootfs archive exists.

pre_umount_final_image runs before this archive/export block, but extensions/netboot/netboot.sh invokes netboot_artifacts_ready from that earlier hook and forwards NETBOOT_ROOTFS_ARCHIVE="${ROOTFS_ARCHIVE_PATH:-}". As a result, deploy hooks never get the archive path even when ${FINALDEST}/${version}-rootfs.* is produced here. Please add a post-archive hook point after this block and move the netboot deploy callback there.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/functions/image/rootfs-to-image.sh` around lines 101 - 155, The netboot
deploy callback fires too early because call_extension_method
"pre_umount_final_image" runs before the rootfs archive/export block, so
ROOTFS_ARCHIVE_PATH isn't set when extensions/netboot/netboot.sh emits
netboot_artifacts_ready; add a new hook call (e.g. call_extension_method
"post_create_rootfs_archive" "config_post_create_rootfs_archive") immediately
after the archive/export block (after ROOTFS_ARCHIVE_PATH is set and after the
ROOTFS_EXPORT_DIR rsync) and update extensions/netboot/netboot.sh to subscribe
to netboot_artifacts_ready from that new hook (or move the
netboot_artifacts_ready invocation into the new post_create_rootfs_archive
handler) so NETBOOT_ROOTFS_ARCHIVE="${ROOTFS_ARCHIVE_PATH:-}" is populated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/templates/nfs-boot.cmd.template`:
- Around line 35-41: The fallback path currently runs "load ${boot_dev}
${kernel_addr_r} zImage" without checking its return value, which can leave
${kernel_addr_r} stale before calling bootz; modify the fallback to mirror the
booti branch by wrapping the zImage load in an if-check (i.e., if load
${boot_dev} ${kernel_addr_r} zImage; then setenv fdt_high ffffffff; bootz
${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}; else abort/print error and
exit), ensuring the zImage load failure is logged/handled and bootz is not
invoked with an invalid kernel address.

In `@extensions/netboot/netboot.sh`:
- Around line 38-45: The function
extension_prepare_config__netboot_defaults_and_validate currently forces
BOOTSIZE=0 unconditionally which breaks non-nfs-root setups; update it so
BOOTSIZE is set to 0 only when ROOTFS_TYPE == "nfs-root" (e.g., wrap the declare
-g BOOTSIZE=0 assignment in a conditional test of ROOTFS_TYPE) or alternatively
detect manual enabling on unsupported ROOTFS_TYPE and exit with a clear error;
reference extension_prepare_config__netboot_defaults_and_validate, BOOTSIZE and
ROOTFS_TYPE when making the change.

In `@extensions/netboot/README.md`:
- Around line 378-385: Update the paragraph to reflect that the extension now
prevents a /boot fstab entry by forcing BOOTSIZE=0 during config preparation (so
no boot partition or /boot entry is created) instead of stripping /boot from
/etc/fstab at unmount; remove references to the removed fstab-cleanup hook and
clarify that because BOOTSIZE=0 is applied in the config prep step there is no
generated /boot line and therefore no systemd dev-disk-by...device delay or
emergency mode risk.

In `@lib/functions/image/rootfs-to-image.sh`:
- Line 22: The current conditional appends the same suffix for both ROOTFS_TYPE
values, causing artifacts to collide; update the logic that sets
calculated_image_version so that ROOTFS_TYPE==nfs and ROOTFS_TYPE==nfs-root
append distinct suffixes (e.g. use _nfsboot for nfs and _nfsroot for nfs-root)
by checking the exact value of ROOTFS_TYPE and setting calculated_image_version
accordingly (refer to the calculated_image_version variable and the ROOTFS_TYPE
comparison in rootfs-to-image.sh).

---

Outside diff comments:
In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 101-155: The netboot deploy callback fires too early because
call_extension_method "pre_umount_final_image" runs before the rootfs
archive/export block, so ROOTFS_ARCHIVE_PATH isn't set when
extensions/netboot/netboot.sh emits netboot_artifacts_ready; add a new hook call
(e.g. call_extension_method "post_create_rootfs_archive"
"config_post_create_rootfs_archive") immediately after the archive/export block
(after ROOTFS_ARCHIVE_PATH is set and after the ROOTFS_EXPORT_DIR rsync) and
update extensions/netboot/netboot.sh to subscribe to netboot_artifacts_ready
from that new hook (or move the netboot_artifacts_ready invocation into the new
post_create_rootfs_archive handler) so
NETBOOT_ROOTFS_ARCHIVE="${ROOTFS_ARCHIVE_PATH:-}" is populated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 447fa688-7495-4468-bae1-35735f057eda

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6016 and 29e7423.

📒 Files selected for processing (6)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
✅ Files skipped from review due to trivial changes (1)
  • lib/functions/image/partitioning.sh

Comment thread config/templates/nfs-boot.cmd.template
Comment thread extensions/netboot/netboot.sh
Comment thread extensions/netboot/README.md Outdated
Comment thread lib/functions/image/rootfs-to-image.sh Outdated
iav and others added 6 commits April 16, 2026 21:54
The previous template was hardcoded for sunxi arm32 — `zImage`/`bootz`,
`console=tty1 console=ttyS0,115200`, `disp.screen0_output_mode=...`,
`ext4load/fatload mmc 0`. It did not work on arm64 boards (e.g.
rockchip64/helios64) and baked in a 115200 baud that breaks non-standard
UART speeds (helios64 runs at 1500000).

Rewrites the U-Boot hush script to:
- Prefer `Image` + `booti` (arm64), fall back to `zImage` + `bootz` (arm32).
- Load via `${devtype} ${devnum}:${distro_bootpart}` from U-Boot's distro
  bootflow scanner instead of hardcoded `mmc 0`.
- Drop the `console=` overrides — let the kernel resolve the console from
  DTB `/chosen/stdout-path`, keeping `earlycon` for early output.
- Drop sunxi-specific `disp.screen0_output_mode` and legacy `.next`/
  `script.bin` probe paths.

For the full TFTP+NFS netboot flow see the new `netboot` extension; this
template remains the hybrid path where the kernel + DTB live on a local
boot partition and only the rootfs is NFS-mounted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…the tree

The archive was created inside the if/else block at the top of
create_image_from_sdcard_rootfs(), BEFORE update_initramfs and
pre_umount_final_image hooks run.  Any rootfs changes made by those
hooks (initramfs regeneration, fstab fixups, extension tweaks) were
missing from the archive.

Move archive creation to after pre_umount_final_image so the tarball
captures the fully finalized rootfs tree.
…TFS_COMPRESSION

Split the rootfs pipeline so it can produce either (or both) of:
  * a tarball — via ROOTFS_COMPRESSION=gzip (default, .tar.gz) / zstd
    (.tar.zst); matches existing behaviour, with zstd now available for
    faster creation and decompression on modern hardware.
  * an exported tree — via ROOTFS_EXPORT_DIR=<abs path>, which rsyncs
    the built rootfs to a host-side directory (e.g. an NFS export)
    without an intermediate archive.

Set ROOTFS_COMPRESSION=none when only the exported tree is wanted;
this skips archive creation entirely. If both ROOTFS_COMPRESSION=none
and -z ROOTFS_EXPORT_DIR are set the run is aborted — otherwise the
rootfs stage would produce nothing.

This is infrastructure; no existing callers need to change. The
netboot extension (added in a following commit) consumes
ROOTFS_EXPORT_DIR to populate the NFS export tree.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hooks:
- extension_prepare_config: validate variables, compute defaults for
  NETBOOT_TFTP_PREFIX / NETBOOT_NFS_PATH (shared by
  LINUXFAMILY/BOARD/BRANCH/RELEASE, or per-host when NETBOOT_HOSTNAME
  is set), normalize NETBOOT_CLIENT_MAC to PXELINUX 01-<mac> form,
  fail fast on bad ROOTFS_COMPRESSION/ROOTFS_EXPORT_DIR combinations.
- custom_kernel_config: enable ROOT_NFS, NFS_FS, NFS_V3, IP_PNP,
  IP_PNP_DHCP so root=/dev/nfs ip=dhcp works without an initrd.
- post_customize_image: drop armbian-resize-filesystem.service
  (meaningless on NFS root) and /root/.not_logged_in_yet (the
  armbian-firstlogin interactive wizard blocks bring-up when there is
  no interactive console). armbian-firstrun.service stays — it only
  regenerates SSH host keys.
- host_pre_docker_launch: append a bind-mount for ROOTFS_EXPORT_DIR to
  DOCKER_EXTRA_ARGS when the directory lives outside ${SRC}, using the
  hook's documented mechanism.
- pre_umount_final_image: assemble the TFTP tree (Image/zImage, dtb/,
  uInitrd), write pxelinux.cfg/{default.example | 01-<mac>} with the
  right FDT/FDTDIR line and explicit INITRD directive when uInitrd is
  present, expose a netboot_artifacts_ready hook for userpatches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New rootfs type for full network boot: the only thing on the device's
local storage is U-Boot itself. Kernel, DTB, optional uInitrd and PXE
config come from TFTP; rootfs is mounted over NFS.

A new case branch in do_main_configuration auto-enables the netboot
extension, symmetric with existing fs-f2fs-support / fs-btrfs wiring.
The legacy ROOTFS_TYPE=nfs (hybrid: kernel on local storage, only /
over NFS) is untouched — both paths coexist.

- nfs-root case branch in ROOTFS_TYPE dispatch calls
  enable_extension "netboot"
- prepare_partitions skips root partition creation and SD-size sanity
  check
- check_filesystem_compatibility_on_host skipped for nfs-root
- create_image_from_sdcard_rootfs early-returns for nfs-root after the
  pre_umount hook has grabbed TFTP artifacts from /boot: SDCARD.raw is
  dropped, the .img pipeline (mv to DESTIMG, write-to-SD, fingerprint,
  compress) is skipped. For nfs-root the only deliverables are the
  rootfs archive / ROOTFS_EXPORT_DIR tree and the TFTP staging dir —
  producing a boot-partition .img would be misleading (nothing on the
  device reads it).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the netboot extension: artifact server setup (tftpd-hpa +
nfs-kernel-server), TFTP tree layout, DHCP options 66/67 on the
network DHCP server, userpatches.conf knobs, the
netboot_artifacts_ready hook, a full end-to-end helios64 walkthrough,
and a troubleshooting section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iav iav force-pushed the enh/netboot-extension branch from b0550f6 to 3b1129e Compare April 16, 2026 18:57
@iav iav marked this pull request as ready for review April 16, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

05 Milestone: Second quarter release Documentation Documentation changes or additions Framework Framework components Hardware Hardware related like kernel, U-Boot, ... Needs review Seeking for review size/large PR with 250 lines or more Work in progress Unfinished / work in progress

Development

Successfully merging this pull request may close these issues.

2 participants