feat(extensions): add netboot extension for TFTP+NFS diskless boot#9656
feat(extensions): add netboot extension for TFTP+NFS diskless boot#9656iav wants to merge 14 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds ROOTFS_TYPE=nfs-root with a netboot extension (validation, staging, deploy hooks, initramfs/dhcpcd hooks, watchdogs), updates the U‑Boot NFS boot template for distro-boot/mainline kernels, integrates rootfs archive/export with metadata preservation, and adjusts image/partition and host/artifact utilities. ChangesNetboot feature & deployment
Archive & metadata preservation + host ownership semantics
Sequence Diagram(s)sequenceDiagram
participant Builder as Builder Host
participant Ext as Netboot Extension
participant Staging as TFTP/NFS Staging
participant Deploy as Deploy Hook
participant Remote as Remote Server
participant Target as Target U‑Boot
Builder->>Ext: build with ROOTFS_TYPE=nfs-root
Ext->>Staging: validate NETBOOT_*, normalize paths, stage kernel/DTB/uInitrd, generate PXE configs
Ext->>Staging: create rootfs archive or rsync export (preserve owners/xattrs/ACLs/SELinux)
Ext->>Builder: emit netboot_artifacts_ready (TFTP tree, PXE config, ROOTFS_ARCHIVE)
Builder->>Deploy: artifact_ready -> deploy to Remote
Deploy->>Remote: rsync TFTP payload + pxelinux configs
Deploy->>Remote: upload & extract ROOTFS_ARCHIVE (optional, preserve metadata)
Target->>Remote: DHCP/PXE -> download kernel/DTB/initrd via TFTP
Target->>Target: initramfs dhcpcd hook may set ROOTSERVER -> mount NFS root
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (5)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/netboot.shlib/functions/configuration/main-config.shlib/functions/image/rootfs-to-image.sh
`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>
|
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 |
|
Thanks for the pointer! Let's get this merged first — iterating on something that works is the easy part. |
a76e4b2 to
fec99ac
Compare
a10feb4 to
4ff6016
Compare
|
@coderabbitai review |
|
Pull my Helios64 to v2026.04 in #9675 |
a61ff64 to
dac19c8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
extensions/netboot/README.md (2)
77-77: 💤 Low valueDe-emphasize the overused “exactly”.
You use “that’s exactly what U-Boot’s … resolution requests” in the
NETBOOT_CLIENT_MACrow. It’s correct, but the word is called out by static analysis as overused; removing “exactly” improves readability without changing meaning.Suggested doc wording
-... that’s exactly what U-Boot's PXELINUX per-MAC fallback resolution requests. +... that’s what U-Boot's PXELINUX per-MAC fallback resolution requests.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@extensions/netboot/README.md` at line 77, In the NETBOOT_CLIENT_MAC README row update the wording to remove the overused adverb "exactly" — change the phrase "that's exactly what U-Boot's PXELINUX per-MAC fallback resolution requests" to a simpler "that's what U-Boot's PXELINUX per-MAC fallback resolution requests" (preserve the surrounding explanation about lowercase + dashes and the NETBOOT_PXE_FILE exposure).
79-80: ⚡ Quick winClarify when
ROOTFS_EXPORT_DIRmust pre-exist on the host.The
ROOTFS_EXPORT_DIRtable row says: “The directory must exist on the host before the build…”. For external absolute paths, that’s correct; but for relative values confined under${SRC}/output/netboot-export/<value>, the build is typically able to create/populate paths under the build output.Consider qualifying the sentence so users don’t create unnecessary directories for the relative (confined) case.
Suggested doc fix
-| Relative** value (e.g. `shared/rockchip64/helios64/edge-trixie`) is confined under `${SRC}/output/netboot-export/<value>` so `rsync --delete` cannot escape that subtree. **Absolute path outside the build tree** (e.g. `/srv/netboot/rootfs/shared/<board>/<branch>-<release>` or `/nfsroot`) is kept as-is and bind-mounted into the container at the same path; rsync writes straight into the host export tree. The directory must exist on the host before the build (typically `sudo mkdir -p` for root-owned NFS roots). Primary use: builder host is also the NFS server — single-step `build → boot` loop, no tar/unpack/rsync hop. System roots (`/`, `/etc`, `/usr`, ...) and `..` segments are rejected. The build stamps a `.netboot_export_marker` at the root of every export tree it writes; a non-empty target without that marker is refused (so `rsync --delete` cannot wipe an unrelated Linux tree at the same path) unless `NETBOOT_EXPORT_FORCE=yes`. +| Relative** value (e.g. `shared/rockchip64/helios64/edge-trixie`) is confined under `${SRC}/output/netboot-export/<value>` so `rsync --delete` cannot escape that subtree. **Absolute path outside the build tree** (e.g. `/srv/netboot/rootfs/shared/<board>/<branch>-<release>` or `/nfsroot`) is kept as-is and bind-mounted into the container at the same path; rsync writes straight into the host export tree. For absolute/external paths, the directory must exist on the host before the build (typically `sudo mkdir -p` for root-owned NFS roots). Primary use: builder host is also the NFS server — single-step `build → boot` loop, no tar/unpack/rsync hop. System roots (`/`, `/etc`, `/usr`, ...) and `..` segments are rejected. The build stamps a `.netboot_export_marker` at the root of every export tree it writes; a non-empty target without that marker is refused (so `rsync --delete` cannot wipe an unrelated Linux tree at the same path) unless `NETBOOT_EXPORT_FORCE=yes`.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@extensions/netboot/README.md` around lines 79 - 80, The README text for ROOTFS_EXPORT_DIR is ambiguous about when the directory must pre-exist; update the table row for ROOTFS_EXPORT_DIR to clearly state that only absolute external paths (e.g. /srv/netboot/... or /nfsroot) must exist on the host before the build and will be bind-mounted as-is, whereas relative values confined under ${SRC}/output/netboot-export/<value> are created/populated by the build process and do not require pre-creation; keep the note about the .netboot_export_marker and NETBOOT_EXPORT_FORCE behavior unchanged.
🤖 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/README.md`:
- Around line 703-713: The sample boot log is inconsistent: the APPEND/kernel
cmdline example contains "rw" (the line starting with "append: root=/dev/nfs ...
rw") while the following kernel output shows "VFS: Mounted root (nfs filesystem)
readonly on device 0:17."; update the README so these two lines match—either
change the APPEND example to use "ro" (if the root was actually mounted
read-only) or change the VFS line in the sample to "rw"/remove "readonly" to
reflect a read-write mount; ensure the two literal strings ("append:
root=/dev/nfs ... rw" and "VFS: Mounted root (nfs filesystem) readonly on device
0:17.") are consistent.
---
Nitpick comments:
In `@extensions/netboot/README.md`:
- Line 77: In the NETBOOT_CLIENT_MAC README row update the wording to remove the
overused adverb "exactly" — change the phrase "that's exactly what U-Boot's
PXELINUX per-MAC fallback resolution requests" to a simpler "that's what
U-Boot's PXELINUX per-MAC fallback resolution requests" (preserve the
surrounding explanation about lowercase + dashes and the NETBOOT_PXE_FILE
exposure).
- Around line 79-80: The README text for ROOTFS_EXPORT_DIR is ambiguous about
when the directory must pre-exist; update the table row for ROOTFS_EXPORT_DIR to
clearly state that only absolute external paths (e.g. /srv/netboot/... or
/nfsroot) must exist on the host before the build and will be bind-mounted
as-is, whereas relative values confined under
${SRC}/output/netboot-export/<value> are created/populated by the build process
and do not require pre-creation; keep the note about the .netboot_export_marker
and NETBOOT_EXPORT_FORCE behavior unchanged.
🪄 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: 2afa6525-7b8b-4e73-8c55-cb66d068cc49
📒 Files selected for processing (3)
extensions/netboot/README.mdextensions/netboot/netboot-deploy.shextensions/netboot/netboot.sh
🚧 Files skipped from review as they are similar to previous changes (2)
- extensions/netboot/netboot-deploy.sh
- extensions/netboot/netboot.sh
There was a problem hiding this comment.
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 `@extensions/netboot/netboot.sh`:
- Around line 386-405: The install logic for dhcpcd_hook and initramfs_hook
should unconditionally overwrite the target hooks and force the initramfs
rebuild instead of only installing when the file is missing; remove the [[ ! -f
"${dhcpcd_hook}" ]] and [[ ! -f "${initramfs_hook}" ]] guards so
run_host_command_logged install -D -m 0755
"${EXTENSION_DIR}/files/dhcpcd-hooks/71-netboot-rootpath" "${dhcpcd_hook}" and
run_host_command_logged install -D -m 0755
"${EXTENSION_DIR}/files/initramfs-hooks/netboot-rootpath" "${initramfs_hook}"
always execute, ensure changed is set to "yes" after each install, and keep the
chroot_sdcard update-initramfs -u call guarded by if [[ "${changed}" == "yes" ]]
so the new hooks are always included in the uInitrd.
In `@extensions/netboot/README.md`:
- Around line 611-655: The Helios64 example block is inconsistent with the
captured log; update the sample so all values match (or clearly mark the log as
an older capture). Ensure NETBOOT_SERVER, ROOTFS_EXPORT_DIR, ROOTFS_TYPE,
BUILD_MINIMAL and the BUILD BRANCH/RELEASE (e.g., edge/trixie) in the compile.sh
invocation match the values shown in the log (remove mismatched "edge-noble",
path-only "nfsroot=", and bootserver/rootserver=192.168.1.65), or add a short
note before the log stating it is from a different run with its exact settings;
keep the compile.sh invocation and the log consistent and self-contained.
🪄 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: 577ff317-7d1a-4d1d-ac15-f148feca461e
📒 Files selected for processing (12)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/configuration/main-config.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
✅ Files skipped from review due to trivial changes (3)
- lib/functions/configuration/main-config.sh
- lib/functions/rootfs/rootfs-create.sh
- lib/functions/image/partitioning.sh
🚧 Files skipped from review as they are similar to previous changes (4)
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- lib/functions/rootfs/create-cache.sh
- extensions/netboot/netboot-deploy.sh
- lib/functions/image/rootfs-to-image.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 438-440: The script currently silently skips copying DTB from
"${MOUNT}/boot/dtb" to "${tftp_prefix_dir}/dtb/" but still emits a PXE FDTDIR
pointing at "${NETBOOT_TFTP_PREFIX}/dtb", causing broken PXE configs; modify the
logic around the DTB staging (check existence of "${MOUNT}/boot/dtb" and/or
"${tftp_prefix_dir}/dtb") to fail fast or omit the FDTDIR fallback: either (A)
if no DTB tree is staged, log an error and exit non-zero so the build fails
early, or (B) when producing the PXE config, only emit the FDTDIR
${NETBOOT_TFTP_PREFIX}/dtb line if the destination dtb directory actually exists
and contains files; update the blocks that reference MOUNT, tftp_prefix_dir,
NETBOOT_TFTP_PREFIX and the FDTDIR emission to implement one of these two
behaviors.
🪄 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: 7c2a396a-6903-4c51-b156-2826d8b7ff24
📒 Files selected for processing (13)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/configuration/main-config.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
✅ Files skipped from review due to trivial changes (2)
- lib/functions/rootfs/rootfs-create.sh
- config/templates/nfs-boot.cmd.template
🚧 Files skipped from review as they are similar to previous changes (3)
- lib/functions/rootfs/create-cache.sh
- lib/functions/image/rootfs-to-image.sh
- extensions/netboot/netboot-deploy.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/README.md`:
- Around line 437-444: The README incorrectly states that rsync performs kernel
reflinks on btrfs/xfs; update the text near ROOTFS_EXPORT_DIR to remove or
reword the claim that "the kernel reflinks the rootfs tree" and instead explain
that while bind-mounting and rsync preserve ownership, rsync will copy data
unless explicit reflink tooling or filesystem-level copy-on-write (e.g., cp
--reflink or filesystem snapshot mechanisms) is used; reference
ROOTFS_EXPORT_DIR and the rsync-in-container behavior so readers understand the
export remains fast only when reflink/cow mechanisms are explicitly employed,
not automatically by rsync.
🪄 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: 1e89d51b-0cb5-41e2-936a-6b5ab8d6bd19
📒 Files selected for processing (13)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/configuration/main-config.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
✅ Files skipped from review due to trivial changes (3)
- extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
- lib/functions/image/partitioning.sh
- config/templates/nfs-boot.cmd.template
🚧 Files skipped from review as they are similar to previous changes (4)
- lib/functions/rootfs/rootfs-create.sh
- extensions/netboot/netboot-deploy.sh
- extensions/netboot/netboot.sh
- lib/functions/image/rootfs-to-image.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/netboot/README.md`:
- Around line 659-660: The example uses a glob "output/images/*-netboot-tftp/"
which can accidentally merge multiple build outputs into "/srv/netboot/tftp/";
update the README example to point at a specific build directory instead of the
wildcard (e.g., replace "output/images/*-netboot-tftp/" with the specific build
directory name for the target board/release) and keep the destination
"/srv/netboot/tftp/"; update the example text so readers must substitute their
exact build directory (referencing the string "output/images/*-netboot-tftp/"
and the destination "/srv/netboot/tftp/").
🪄 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: 7bdbb458-1561-4a19-9941-b926c8ce368d
📒 Files selected for processing (14)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (4)
- lib/functions/rootfs/rootfs-create.sh
- config/templates/nfs-boot.cmd.template
- lib/functions/image/rootfs-to-image.sh
- extensions/netboot/netboot-deploy.sh
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog`:
- Around line 14-16: The watchdog currently writes "b" to /proc/sysrq-trigger
which is a no-op if kernel sysrq is disabled; modify the script around the sleep
600 block so it first attempts to enable sysrq by writing "1" to
/proc/sys/kernel/sysrq (check the write/result), then trigger the sysrq reboot
via echo b > /proc/sysrq-trigger only if enabling succeeded, and if enabling or
triggering fails fallback to a forced reboot command (e.g., busybox reboot -f or
echo c to /proc/sysrq-trigger / invoking kexec/reboot alternative) so the
watchdog cannot silently hang.
- Line 11: Update the inaccurate comment in zz-netboot-watchdog: replace "Force
kernel panic + PSCI reset after 10 min if NFS root mount hangs." with text that
correctly describes the action performed by the script (e.g. "Trigger immediate
reboot via SysRq 'b' (not a kernel panic) + PSCI reset after 10 min if NFS root
mount hangs.") so the comment accurately reflects that echo b >
/proc/sysrq-trigger issues an immediate reboot rather than causing a kernel
panic.
🪄 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: 6ff8f58e-7371-4aee-b74b-ab78af14a2f0
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
✅ Files skipped from review due to trivial changes (1)
- extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
🚧 Files skipped from review as they are similar to previous changes (7)
- lib/functions/rootfs/create-cache.sh
- lib/functions/image/partitioning.sh
- lib/functions/rootfs/rootfs-create.sh
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- config/templates/nfs-boot.cmd.template
- extensions/netboot/netboot-deploy.sh
- extensions/netboot/netboot.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel`:
- Around line 9-11: In zz-netboot-watchdog-cancel, don't pass raw pidfile
contents to kill; read /run/netboot-watchdog.pid, trim whitespace, validate it
matches a numeric regex and is within a safe range (e.g. >1), verify the PID
refers to a live process (kill -0 or /proc/$pid exists) and only then call kill;
if validation fails, log/ignore and remove the stale pidfile rather than sending
a signal to an unintended process.
🪄 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: e1c86711-3099-4f4e-a87d-3dca25f2de02
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (6)
- lib/functions/image/partitioning.sh
- lib/functions/configuration/main-config.sh
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- lib/functions/rootfs/rootfs-create.sh
- config/templates/nfs-boot.cmd.template
- lib/functions/image/rootfs-to-image.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/netboot/netboot.sh`:
- Around line 446-480: The TFTP staging subtree (${tftp_prefix_dir}) is never
cleared so stale files (old DTBs, uInitrd) can persist across incremental
builds; before copying artifacts (kernel via kernel_src, dtbs, uInitrd) remove
or clean the contents of ${tftp_prefix_dir} (but keep the directory itself) and
recreate any required subdirs (e.g. dtb and pxe_dir) so subsequent
run_host_command_logged cp -v / cp -a operations only copy current ${MOUNT}/boot
artifacts; ensure this cleaning happens just after declaring
tftp_prefix_dir/pxe_dir and before copying kernel, dtb, and initrd so
dtb_payload and INITRD checks reflect the fresh tree.
🪄 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: cd4ac0fe-9415-4f52-b343-21e8d9d1347a
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (9)
- lib/functions/rootfs/create-cache.sh
- extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
- lib/functions/image/partitioning.sh
- lib/functions/configuration/main-config.sh
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- lib/functions/rootfs/rootfs-create.sh
- config/templates/nfs-boot.cmd.template
- lib/functions/image/rootfs-to-image.sh
- extensions/netboot/netboot-deploy.sh
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/netboot/netboot-deploy.sh`:
- Around line 44-48: The script must fail fast if the remote side is not
effectively root for NFS updates: update the logic around NETBOOT_DEPLOY_SUDO,
the archive untar routine (where tar --numeric-owner is used) and the
kernel-only sync to require either NETBOOT_DEPLOY_SUDO=yes or an effective
remote UID of 0; implement a remote check (ssh "$host" 'id -u' or similar)
before running tar/rsync/mkdir/tar that preserve numeric owners and if neither
condition is true exit with a clear error; tighten the NETBOOT_DEPLOY_SUDO
help/contract text to state it is required when the SSH account cannot act as
root for rsync/mkdir/tar on TFTP_ROOT and NETBOOT_NFS_PATH; apply the same
check/exit logic to the other similar blocks mentioned (archive untar and
/lib/modules sync locations).
- Around line 545-550: The rsync that syncs
"${scratch_dir}/usr/lib/linux-image-${kver}/" to
"${NETBOOT_DEPLOY_SSH}:${NETBOOT_DEPLOY_TFTP_ROOT}/${NETBOOT_TFTP_PREFIX}/dtb/"
copies new DTBs but does not remove DTBs removed or renamed in the package, so
add the delete option to the rsync invocation (i.e. include --delete among the
"${rsync_base[@]}" options passed to run_host_command_logged_raw) for the dtb
sync to mirror the full-image deploy behavior and ensure removed DTBs are pruned
from the target.
🪄 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: adade000-f830-4a0c-832c-83fad6ccc028
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (6)
- lib/functions/rootfs/create-cache.sh
- lib/functions/image/partitioning.sh
- lib/functions/configuration/main-config.sh
- lib/functions/rootfs/rootfs-create.sh
- extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
- lib/functions/image/rootfs-to-image.sh
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/functions/rootfs/rootfs-create.sh`:
- Around line 26-27: The tar extraction in the rootfs cache restore (the tar xp
invocation in create-cache.sh) is missing the --sparse flag so sparse-file
extents recorded during creation are lost; update the extraction command (the
tar xp --numeric-owner --xattrs
--xattrs-include="${ROOTFS_TAR_XATTR_INCLUDE:-security.*}" --acls --selinux ...
-C "${SDCARD}"/ invocation) to include --sparse so restored files preserve
sparse metadata and match the creation command used in rootfs-create.sh.
🪄 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: 6c34a51f-bbf3-489f-bca4-e0f135b4485d
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
✅ Files skipped from review due to trivial changes (1)
- extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
🚧 Files skipped from review as they are similar to previous changes (8)
- lib/functions/image/partitioning.sh
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
- lib/functions/configuration/main-config.sh
- config/templates/nfs-boot.cmd.template
- lib/functions/rootfs/create-cache.sh
- lib/functions/image/rootfs-to-image.sh
- extensions/netboot/netboot-deploy.sh
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel (1)
17-17:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMake watchdog cancellation tolerant to stale/already-exited PIDs.
killcan legitimately fail (race, stale pidfile). Mask the exit status to avoid unintended script abort in errexit contexts.Based on learnings, Armbian shell execution generally assumes `set -e`, so unhandled non-zero statuses can terminate flow unexpectedly.Suggested patch
- [ "${watchdog_pid}" -gt 1 ] && kill "${watchdog_pid}" 2> /dev/null + [ "${watchdog_pid}" -gt 1 ] && kill "${watchdog_pid}" 2> /dev/null || true🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel` at line 17, In zz-netboot-watchdog-cancel make the watchdog PID kill tolerant to stale/exited PIDs by masking kill's exit status; locate the line using the watchdog_pid variable and the kill "${watchdog_pid}" 2> /dev/null invocation and change it so failures don't propagate (for example by appending a no-op OR to swallow non-zero exit codes like "|| true" or using ":"), ensuring the script won't abort under set -e when the PID is already gone.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/netboot/netboot-deploy.sh`:
- Around line 435-438: The remote command passed to run_host_command_logged_raw
can exit early under set -e and leave the large q_remote_archive in /tmp if tar
fails; change the remote shell sequence invoked over ssh (the string currently
building with mkdir -p ${q_nfs_path}; ${sudo_prefix}tar -xp ... -f
${q_remote_archive} -C ${q_nfs_path}; rm -f ${q_remote_archive}) so that the
mkdir→tar step short-circuits on error (use && between mkdir and tar) but the rm
-f ${q_remote_archive} is executed unconditionally and the original tar exit
status is preserved and re-exited (capture the tar/mkdir exit code into a temp
var and then run rm -f ${q_remote_archive}; exit ${ret}) to ensure cleanup
always runs while still propagating failures back to
run_host_command_logged_raw.
- Line 437: The tar invocation that uses --selinux, --acls, and --xattrs (the
line that runs "${sudo_prefix}tar -xp --numeric-owner --xattrs
--xattrs-include='*' --acls --selinux -f ${q_remote_archive} -C ${q_nfs_path}")
assumes GNU tar and will fail on BusyBox; modify the deployment script to probe
the remote tar capabilities (e.g. run "${sudo_prefix}tar --version" or check for
"GNU" in output) and conditionally set an extended-attribute flags variable
(like EXT_TAR_FLAGS="--numeric-owner --xattrs --xattrs-include='*' --acls
--selinux" for GNU tar, fallback to "-x --numeric-owner" or "-xp" for non-GNU),
then use "${sudo_prefix}tar ${EXT_TAR_FLAGS} -f ${q_remote_archive} -C
${q_nfs_path}" in place of the hardcoded flags; alternatively, if you prefer
docs-only, add a README note stating GNU tar is required on the NFS server.
---
Duplicate comments:
In
`@extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel`:
- Line 17: In zz-netboot-watchdog-cancel make the watchdog PID kill tolerant to
stale/exited PIDs by masking kill's exit status; locate the line using the
watchdog_pid variable and the kill "${watchdog_pid}" 2> /dev/null invocation and
change it so failures don't propagate (for example by appending a no-op OR to
swallow non-zero exit codes like "|| true" or using ":"), ensuring the script
won't abort under set -e when the PID is already gone.
🪄 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: 0a996b13-5b68-49c0-80c0-39489b849af8
📒 Files selected for processing (15)
config/templates/nfs-boot.cmd.templateextensions/netboot/README.mdextensions/netboot/files/dhcpcd-hooks/71-netboot-rootpathextensions/netboot/files/initramfs-hooks/netboot-rootpathextensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdogextensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancelextensions/netboot/netboot-deploy.shextensions/netboot/netboot.shlib/functions/artifacts/artifacts-obtain.shlib/functions/configuration/main-config.shlib/functions/host/host-utils.shlib/functions/image/partitioning.shlib/functions/image/rootfs-to-image.shlib/functions/rootfs/create-cache.shlib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (5)
- lib/functions/rootfs/create-cache.sh
- lib/functions/configuration/main-config.sh
- extensions/netboot/files/initramfs-hooks/netboot-rootpath
- lib/functions/image/rootfs-to-image.sh
- config/templates/nfs-boot.cmd.template
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/netboot/README.md`:
- Line 95: The README uses two spellings ("Normalize" and "normalises") for the
same concept; pick one dialect and make it consistent across the file by
updating all occurrences (e.g., the NETBOOT_CLIENT_MAC description and earlier
uses) to the chosen spelling; search for instances of "normalize", "normalise",
"normalizes", "normalises" and update them to one variant so the README is
consistent.
🪄 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: f83b57d6-01c8-4e1a-95e5-eb619ce2d934
📒 Files selected for processing (2)
extensions/netboot/README.mdextensions/netboot/netboot-deploy.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- extensions/netboot/netboot-deploy.sh
There was a problem hiding this comment.
🧹 Nitpick comments (1)
lib/functions/image/rootfs-to-image.sh (1)
47-50: ⚡ Quick winSerialize
exclude_homeforrun_host_command_logged.
run_host_command_loggedrebuilds the command withbash -c "$*", so forwarding"${exclude_home[@]}"here loses the array’s quoting guarantees again. Please pass the array through${exclude_home[*]@Q}(or keep a helper-safe quoted string) at both rsync call sites.Suggested change
- "${exclude_home[@]}" \ + ${exclude_home[*]@Q} \ @@ - "${exclude_home[@]}" \ + ${exclude_home[*]@Q} \Based on learnings, in Armbian shell scripts arrays passed through
run_host_command_loggedshould use${array[*]@Q}because the helper re-parses arguments viabash -c "$*".Also applies to: 57-65, 199-207
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/functions/image/rootfs-to-image.sh` around lines 47 - 50, The array exclude_home is declared to avoid embedded quote characters but is being forwarded through run_host_command_logged which rebuilds commands with bash -c "$*", so you must serialize the array to preserve quoting: replace any use of "${exclude_home[@]}" passed into run_host_command_logged/rsync with "${exclude_home[*]@Q}" (or construct a helper-safe quoted string variable) at both rsync call sites and the other occurrences that forward this array through run_host_command_logged (e.g., the blocks invoking rsync where exclude_home is appended); ensure the serialized form is used in the command arguments passed to run_host_command_logged so rsync receives the correct --exclude pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@lib/functions/image/rootfs-to-image.sh`:
- Around line 47-50: The array exclude_home is declared to avoid embedded quote
characters but is being forwarded through run_host_command_logged which rebuilds
commands with bash -c "$*", so you must serialize the array to preserve quoting:
replace any use of "${exclude_home[@]}" passed into
run_host_command_logged/rsync with "${exclude_home[*]@Q}" (or construct a
helper-safe quoted string variable) at both rsync call sites and the other
occurrences that forward this array through run_host_command_logged (e.g., the
blocks invoking rsync where exclude_home is appended); ensure the serialized
form is used in the command arguments passed to run_host_command_logged so rsync
receives the correct --exclude pattern.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8076f47c-c2be-4d26-ad6e-1a8288f63493
📒 Files selected for processing (2)
extensions/netboot/netboot-deploy.shlib/functions/image/rootfs-to-image.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- extensions/netboot/netboot-deploy.sh
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Make the network-boot u-boot template work for both arm64 (Image/booti) and armv7 (zImage/bootz). Load kernel/initrd/dtb from the local boot partition; mount root over NFS. Take console settings from DTB `/chosen/stdout-path` instead of hardcoded baud — boards like helios64 (1500000) and others (115200) work without per-board overrides. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Allow the rootfs stage to produce a compressed archive, an exported directory tree, or both. Compression is configurable. When `ROOTFS_COMPRESSION=none` is set without `ROOTFS_EXPORT_DIR`, fail fast — there would be no rootfs artifact otherwise. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Add opt-in netboot extension for diskless U-Boot PXE/NFS boot. Generates a TFTP tree (kernel + DTB + uInitrd + per-board pxelinux.cfg with extlinux APPEND for NFS root) alongside or instead of a flashable image. Supports per-host MAC-tagged configs, builder-as-NFS-server via ROOTFS_EXPORT_DIR, ROOTSERVER discovery from DHCP siaddr in initramfs, and a `netboot_artifacts_ready` post-hook for deploy automation. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.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> Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.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> Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
In the rootfs cache and image pipelines, switch tar/rsync calls to:
rsync -aHWh -XAXS --numeric-ids ...
tar cp --xattrs --xattrs-include='security.*' --acls --selinux --sparse ...
Without this, xattrs (notably `security.capability` for setcap'd binaries
like /usr/bin/ping) and POSIX ACLs were stripped during the rootfs →
tarball → image (or → NFS export) round-trip.
The tar xattr include pattern defaults to `security.*` (file capabilities
and SELinux contexts) — broader patterns also pick up source-fs internals
(`bcachefs_*`, `btrfs.*`, `zfs.*` from the build host) that have no
meaning on the target and produce extract-time errors. Tunable via:
- `ROOTFS_TAR_XATTR_INCLUDE` (env, replaces default include pattern)
- `ROOTFS_TAR_EXTRA_FLAGS` (bash array, appended to tar args)
- `ROOTFS_RSYNC_XATTR_FLAGS` (env, replaces rsync xattr/ACL flags)
- `pre_create_rootfs_archive` extension hook (set the above lazily,
e.g. depending on ARCH/RELEASE)
Drive-by: scope the `post_create_rootfs_archive` hook dispatch to
`ROOTFS_TYPE=nfs|nfs-root` (the only types that produce an archive)
and add `zst` to the `expected:` list in the unknown-compression
error message.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Reference implementation of the `netboot_artifacts_ready` post-hook:
rsyncs the TFTP tree and unpacks the rootfs archive into an NFS export
on a remote server over SSH.
- Setting `NETBOOT_DEPLOY_SSH=user@host` implies `ROOTFS_TYPE=nfs-root`
so the operator does not have to repeat it on the command line.
- An early probe hook (`extension_prepare_config__060_…`) tries
`touch && rm` on the target TFTP root before the long build, so a
misconfigured SSH key / sudo / known_hosts fails fast with a clear
diagnostic instead of after `./compile.sh` has run for 40 minutes.
- Host identity is explicit: `known_hosts` file by default
(`NETBOOT_DEPLOY_SSH_KNOWN_HOSTS`), optional TOFU
(`NETBOOT_DEPLOY_SSH_TOFU=yes`) for first-time deployments.
- SSH key passed via `NETBOOT_DEPLOY_SSH_KEY`; `sudo` on the
target is opt-in via `NETBOOT_DEPLOY_SUDO=yes`.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Add troubleshooting entries for the most common netboot failure modes: 'NFS over TCP not available from <gateway>' (DHCP boot-server / siaddr unset or wrong) and the corresponding dnsmasq/OpenWRT 'dhcp-boot' fix. Show how to verify with /proc/net/pnp on a booted client. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Add a 10-minute mount-stall safety net via two initramfs hooks:
- init-premount/zz-netboot-watchdog forks a background shell that
sleeps 600 s and then triggers an immediate reboot via
`echo b > /proc/sysrq-trigger` if the NFS root mount has not
completed by then.
- nfs-bottom/zz-netboot-watchdog-cancel kills that background
shell after a successful mount.
Active only for ROOTFS_TYPE=nfs-root. Without the watchdog, a
misconfigured server or transient network failure would hang the target
in initramfs forever; with it, the board self-recovers and tries again.
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
…uid_owner netboot extension exports an unpacked rootfs tree under output/netboot-export/<suffix>/ and reset_uid_owner runs over it. Debian/Ubuntu rootfs trees routinely contain dangling symlinks (e.g. /etc/systemd/system/multi-user.target.wants/ entries referring to services from packages that aren't installed). GNU chown without -h follows the symlink and fails on a missing target with 'cannot dereference', so post-docker cleanup returns exit 2 even though the build itself succeeded. chown -h sets the owner of the symlink inode itself rather than its target; it is a no-op for regular files and directories. This is the semantically correct choice when walking a filesystem tree, regardless of the netboot use case. Surfaced by armbian#9656 (netboot extension); applies to any extension that performs reset_uid_owner over a real rootfs tree on host. Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Add NETBOOT_ROOTDELAY build-time variable that controls the initramfs
NFS-mount retry interval via the `rootdelay=N` kernel cmdline arg
(consumed by /usr/share/initramfs-tools/scripts/nfs:89 as
`delay=${ROOTDELAY:-180}`). Empty default leaves the upstream 180s.
Lowering to 30-60 in trusted labs surfaces a dead NFS server quickly
while still leaving headroom for the 10-minute initramfs watchdog to
trigger a reboot.
Numeric form is validated at extension_prepare_config time so a bad
value aborts the build instead of producing a kernel cmdline the
NFS init script silently ignores.
Note: this does not affect the "Waiting up to 180 secs for end0"
netdev wait. That one is hardcoded in
initramfs-tools/scripts/functions:395 as \`local netdevwait=180\`,
without env/cmdline override. README calls out the distinction so
users don't expect NETBOOT_ROOTDELAY to shorten netdev probing.
README: new row in Build-time variables table, new section "Tuning
the NFS-mount retry delay" with example invocation and value
guidance, ToC entry.
Assisted-by: Claude:claude-opus-4.7
…verride
Replace the hardcoded `tcp,v3` NFS mount option tail with a user-tunable
NETBOOT_NFS_OPTIONS variable (default `tcp,v3`, same as before).
Validation: comma list of alnum / = / _ / - / . tokens — rejects
whitespace, quotes, shell metacharacters so a bad override fails at
extension_prepare_config time instead of producing a garbage kernel
cmdline. Per Documentation/admin-guide/nfs/nfsroot.rst the kernel
itself parses the individual options.
Both the path-only (no server) and the literal-server variants of the
nfsroot= line now use ${NETBOOT_NFS_OPTIONS}.
README: new row in the variables table, new section "Tuning NFS mount
options" with three concrete examples (LAN default, unreliable link
tuning, NFSv4.2), ToC entry.
Assisted-by: Claude:claude-opus-4.7
…RNEL Codex on #135 flagged that the kernel-only deploy hook hardcoded `arm64 -> Image, everything-else -> zImage`. That is wrong for non-arm64 architectures that also use Image — config/sources/ riscv64.conf sets NAME_KERNEL=Image, loong64.conf sets it to vmlinux, and family includes can override (e.g. meson uses uImage). On those targets the deploy hook wrote `vmlinuz-<kver>` to the wrong TFTP filename, so the next PXE boot fetched the previous kernel binary while modules had already been refreshed — exactly the split-kernel/ modules state this hook exists to prevent. Replace the case-on-ARCH with `kernel_name="${NAME_KERNEL:-}"` and abort with an actionable error if unset (which means arch/family sourcing didn't complete). Apply the same fix to the matching fallback in netboot.sh's full-image flow (the vmlinuz branch), which carried the identical arm64-only logic; full-image arm64 builds still hit the explicit Image/zImage branches above it first, so this only affects the rare path where neither file is materialised. Assisted-by: Claude:claude-opus-4.7
Summary
Adds an opt-in
netbootextension that produces a full network-boot payload — kernel, DTB, optionaluInitrd,pxelinux.cfgand 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=nfsalone 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 newROOTFS_TYPE=nfs-root.What changes
lib/functions/configuration/main-config.sh— newROOTFS_TYPE=nfs-rootcase branch, symmetric with the existingfs-f2fs-support/fs-btrfswiring: the branch auto-enables thenetbootextension soROOTFS_TYPE=nfs-rootis the single switch that selects the full netboot flow.check_filesystem_compatibility_on_hostis skipped for bothnfsandnfs-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 singleextensions/netboot.shfile) exists so the long-form usage guide can live next to the code asREADME.md; inlining documentation of that size into the script body would be unwieldy. Hooks:extension_prepare_config— validate variables (NETBOOT_CLIENT_MACMAC normalization to the01-<mac>PXELINUX form,ROOTFS_COMPRESSION/ROOTFS_EXPORT_DIRrejection of bad combinations before debootstrap), set the build-flavor_NETBOOT_FLAVORsuffix (-min/-desktop/ empty) for default paths._netboot_compute_runtime_defaults— lazy helper that materializesNETBOOT_TFTP_PREFIX/NETBOOT_NFS_PATHdefaults (armbian/${LINUXFAMILY}/${BOARD}/${BRANCH}-${RELEASE}${_NETBOOT_FLAVOR}shared, or/srv/netboot/rootfs/hosts/<hostname>per-host) at hook time, when${LINUXFAMILY}is guaranteed populated. Computing inextension_prepare_configwould capture an empty${LINUXFAMILY}on flows where family-config sourcing happens later (e.g. kernel-onlycompile.sh kernel ...). Called from each consuming hook (pre_umount_final_image,post_create_rootfs_archive,artifact_readyinnetboot-deploy.sh).custom_kernel_config— enableROOT_NFS,NFS_FS,NFS_V3,IP_PNP,IP_PNP_DHCPsoroot=/dev/nfs ip=dhcpworks without an initrd.post_customize_image— droparmbian-resize-filesystem.service(meaningless on NFS root) and/root/.not_logged_in_yet(thearmbian-firstlogininteractive wizard blocks bring-up when there is no interactive console).armbian-firstrun.servicestays — it only regenerates SSH host keys.host_pre_docker_launch— bind-mountROOTFS_EXPORT_DIRinto 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), writepxelinux.cfg/{default.example | 01-<mac>}with the rightFDT/FDTDIRline and an explicitINITRDdirective whenuInitrdis present (U-Boot's PXE parser only loads an initramfs when the stanza names it), expose anetboot_artifacts_readyhook for userpatches that deploy to a real server.lib/functions/artifacts/artifacts-obtain.sh— new genericartifact_readyextension hook, fired at the end ofobtain_complete_artifactafterartifact_reversion_for_deployment(on the local-build path; skipped whendeploy_to_remote=yessince that path tears downartifact_base_dirwithout leaving usable.debfiles on disk). Extension-side handlers see reversioned.debfilenames inartifact_map_debs_reversioned_*under${DEB_STORAGE}and the standardWHAT/artifact_name/artifact_version/artifact_final_filecontext. Generic — netboot-deploy below is the first consumer; any extension can use it for deploy / notification / cache-warming actions.lib/functions/image/rootfs-to-image.sh— two new controls for NFS-rootfs builds (bothROOTFS_TYPE=nfsandnfs-root):ROOTFS_COMPRESSION=zstd|gzip|none(defaultzstd).zstd→.tar.zst,gzip→.tar.gz,none→ no archive at all. Rejected early ifnoneis set withoutROOTFS_EXPORT_DIR. Thetar | pv | compressorpipeline now runs in aset -o pipefailsubshell 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--deleteso a re-used export dir stays in sync with the new build instead of accumulating stale files from previous runs. Combined withROOTFS_COMPRESSION=nonethis turns deploy-to-NFS-server into a single build step.ROOTFS_ARCHIVE_PATHis exported so downstream hooks (the newnetboot_artifacts_ready) can reference the produced archive.lib/functions/image/partitioning.sh—prepare_partitionsskips the root partition entry fornfs-rootthe same way it does fornfs, 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 hybridROOTFS_TYPE=nfspath builds for arm64 boards too.extensions/netboot/netboot-deploy.sh— reference deploy hook with two trigger points:netboot_artifacts_ready__deploy_to_remote_server— full-image flow (existing). Rsyncs the staged TFTP tree and uploads + untars the rootfs archive via SSH.artifact_ready__netboot_kernel_deploy— new kernel-only flow. Triggered bycompile.sh kernel BOARD=... ENABLE_EXTENSIONS=netboot,netboot-deploy NETBOOT_DEPLOY_SSH=.... Unpacks the reversionedlinux-image-${BRANCH}-${LINUXFAMILY}_*_${ARCH}*.debinto${SRC}/.tmp/; rsyncsvmlinuz-${kver}→${TFTP_PREFIX}/Image|zImage|vmlinuz-${kver}(renamed by${ARCH}, mirrors whatpre_umount_final_image__900_collect_netboot_artifactsproduces in a full image build),usr/lib/linux-image-${kver}/→${TFTP_PREFIX}/dtb/, andlib/modules/${kver}/→${NFS_PATH}/lib/modules/${kver}/with--deletescoped to that single kernel version. Closes a coherence gap: a kernel-only refresh (changed driver, recompiled with a config tweak) used to leave the on-NFS.koset out-of-sync with the freshly-deployed vmlinuz, producingBPF: Invalid name_offset:Nandfailed to validate module BTF: -22spam at boot. Initramfs is intentionally skipped — regenerating it requires a chroot into the NFS rootfs (cross-arch needsqemu-user-static+binfmt_miscregistered on the server, not the build host); operator runs it manually or rebuilds the full image when ABI moves.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. Includes a "Kernel-only deploy" subsection covering theartifact_readyhandler workflow with theupdate-initramfsfollow-up step.Variables (quick reference)
All optional.
ROOTFS_TYPE=nfs-rootalone gives you a shared-rootfs build with apxelinux.cfg/default.examplefile.NETBOOT_SERVERnfsroot=keeps${serverip}literal for U-Boot to fill from DHCP siaddr.NETBOOT_TFTP_PREFIXarmbian/${LINUXFAMILY}/${BOARD}/${BRANCH}-${RELEASE}NETBOOT_NFS_PATH/srv/netboot/rootfs/shared/...or/srv/netboot/rootfs/hosts/<hostname>nfsroot=.NETBOOT_HOSTNAMEhosts/<hostname>/— each machine owns its own writable copy.NETBOOT_CLIENT_MAC01-<mac>(per-MAC PXELINUX override). Accepts:or-, normalized to lowercase.ROOTFS_COMPRESSIONzstdzstd/gzip/none.ROOTFS_EXPORT_DIRTest plan
Validated end-to-end on helios64 (
rockchip64,edge/resolute,ttyS2 @ 1500000), Armbian 26.05:ROOTFS_TYPE=nfs-root NETBOOT_SERVER=192.168.1.125, shared NFS path, FDTDIR fallback for boards withoutBOOT_FDT_FILE, no hardcodedconsole=). 6:57 min, all artifacts correct.NETBOOT_HOSTNAME=helios64-a NETBOOT_CLIENT_MAC=aa:bb:cc:dd:ee:ff).pxelinux.cfg/01-aa-bb-cc-dd-ee-ffcontainsnfsroot=.../hosts/helios64-a. 7:44 min.ROOTFS_COMPRESSION=gzip— produces.tar.gz(defaultzstd→.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=nonewithoutROOTFS_EXPORT_DIR— fails fast inextension_prepare_configbefore debootstrap, not hours later.tftpd-hpa+ NFS rootfs via rsync tonfs-kernel-server. DHCP options 66/67 on OpenWRT. Helios64 cold boot → U-Bootbootflow scan -lb→ TFTP →booti→ kernel →ip_auto_config→ NFS mount → systemdgraphical.target→ login prompt onttyS2@1500000. Noarmbian-firstloginwizard, noresize2fserrors,armbian-firstrun.serviceregenerates SSH host keys normally. Verified twice: once with archive workflow + manual unpack, once with tree workflow + rsync deploy.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).compile.sh iav kernel BOARD=helios64 BRANCH=edge BUILD_MINIMAL=yes RELEASE=trixie ENABLE_EXTENSIONS=netboot,netboot-deploy NETBOOT_DEPLOY_SSH=root@m1). On a cache-hit kernel artifact the newartifact_ready__netboot_kernel_deployhandler fired, unpacked the reversionedlinux-image-*.debunder${SRC}/.tmp/, rsynced vmlinuz →${TFTP_PREFIX}/Image, dtbs →${TFTP_PREFIX}/dtb/, modules →${NFS_PATH}/lib/modules/${kver}/with--delete. Runtime 17 sec.compile.sh iav build BOARD=helios64 BRANCH=edge BUILD_MINIMAL=no RELEASE=bookworm ROOTFS_TYPE=nfs-root ENABLE_EXTENSIONS=netboot,netboot-deploy. 16:15 min. Cold boot helios64 → U-Boot SPL/BL31/proper → DHCP from m1 → TFTP fetch (Image45.8 MB,uInitrd26.4 MB,dtb/rockchip/rk3399-kobol-helios64.dtb) → kernel boot → NFS rootfs mount → systemd PID1 →Welcome to Armbian-unofficial 26.05.0-trunk bookworm→helios64 login: root.dmesg | grep -c BPF= 1 line (only-BPF_FRAMEWORKin systemd's version banner; noInvalid name_offset/failed to validate module BTF— empirical confirmation that vmlinuz and/lib/modules/${kver}/are coherent under the lazy default expansion).BOOT_FDT_FILEset (the FDTDIR vs FDT code path is exercised by helios64's missingBOOT_FDT_FILE, but a board with it set should also work).Known issues found during helios4 testing (not blockers for this PR):
ramdisk_addr_r(0x2880000) is only 8 MB abovekernel_addr_r(0x2080000), but zImage 6.12 is 8.1 MB → U-Boot refuses to boot with initrd. Workaround: omitINITRDfrom PXE config — kernel withCONFIG_ROOT_NFS=ymounts NFS root directly without initrd.ip=dhcpwrites DNS to/proc/net/pnpbutsystemd-resolveddoesn't read it → "No DNS servers known". Workaround:resolvectl dns <iface> <gateway>. Needs a networkd.networkfile or oneshot service inpost_customize_image(future improvement).Related work
A companion PR to armbian/documentation will add
Developer-Guide_Netboot.mdwith the short overview + variable reference; this extension'sREADME.mdis the long-form guide and is linked from that page.Summary by CodeRabbit
New Features
Documentation
Initramfs
Reliability
Behavior