Skip to content

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

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

feat(extensions): add netboot extension for TFTP+NFS diskless boot#9656
iav wants to merge 20 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 (NETBOOT_CLIENT_MAC MAC normalization to the 01-<mac> PXELINUX form, ROOTFS_COMPRESSION / ROOTFS_EXPORT_DIR rejection of bad combinations before debootstrap), set the build-flavor _NETBOOT_FLAVOR suffix (-min / -desktop / empty) for default paths.
    • _netboot_compute_runtime_defaults — lazy helper that materializes NETBOOT_TFTP_PREFIX / NETBOOT_NFS_PATH defaults (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 in extension_prepare_config would capture an empty ${LINUXFAMILY} on flows where family-config sourcing happens later (e.g. kernel-only compile.sh kernel ...). Called from each consuming hook (pre_umount_final_image, post_create_rootfs_archive, artifact_ready in netboot-deploy.sh).
    • 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/artifacts/artifacts-obtain.sh — new generic artifact_ready extension hook, fired at the end of obtain_complete_artifact after artifact_reversion_for_deployment (on the local-build path; skipped when deploy_to_remote=yes since that path tears down artifact_base_dir without leaving usable .deb files on disk). Extension-side handlers see reversioned .deb filenames in artifact_map_debs_reversioned_* under ${DEB_STORAGE} and the standard WHAT / artifact_name / artifact_version / artifact_final_file context. 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 (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/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 by compile.sh kernel BOARD=... ENABLE_EXTENSIONS=netboot,netboot-deploy NETBOOT_DEPLOY_SSH=.... Unpacks the reversioned linux-image-${BRANCH}-${LINUXFAMILY}_*_${ARCH}*.deb into ${SRC}/.tmp/; rsyncs vmlinuz-${kver}${TFTP_PREFIX}/Image|zImage|vmlinuz-${kver} (renamed by ${ARCH}, mirrors what pre_umount_final_image__900_collect_netboot_artifacts produces in a full image build), usr/lib/linux-image-${kver}/${TFTP_PREFIX}/dtb/, and lib/modules/${kver}/${NFS_PATH}/lib/modules/${kver}/ with --delete scoped 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 .ko set out-of-sync with the freshly-deployed vmlinuz, producing BPF: Invalid name_offset:N and failed to validate module BTF: -22 spam at boot. Initramfs is intentionally skipped — regenerating it requires a chroot into the NFS rootfs (cross-arch needs qemu-user-static + binfmt_misc registered 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 the artifact_ready handler workflow with the update-initramfs follow-up step.

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).
  • Kernel-only deploy on helios64 (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 new artifact_ready__netboot_kernel_deploy handler fired, unpacked the reversioned linux-image-*.deb under ${SRC}/.tmp/, rsynced vmlinuz → ${TFTP_PREFIX}/Image, dtbs → ${TFTP_PREFIX}/dtb/, modules → ${NFS_PATH}/lib/modules/${kver}/ with --delete. Runtime 17 sec.
  • Full image build + PXE boot, bookworm on helios64: 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 (Image 45.8 MB, uInitrd 26.4 MB, dtb/rockchip/rk3399-kobol-helios64.dtb) → kernel boot → NFS rootfs mount → systemd PID1 → Welcome to Armbian-unofficial 26.05.0-trunk bookwormhelios64 login: root. dmesg | grep -c BPF = 1 line (only -BPF_FRAMEWORK in systemd's version banner; no Invalid name_offset / failed to validate module BTF — empirical confirmation that vmlinuz and /lib/modules/${kver}/ are coherent under the lazy default expansion).
  • 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.

Post-review update (round 5): also includes a small core-fix in lib/functions/host/host-utils.shreset_uid_owner now uses chown -h to tolerate dangling symlinks in the unpacked rootfs tree this extension exports (see the commit for the full rationale).

Post-review update (round 6): adds a generic artifact_ready extension hook to lib/functions/artifacts/artifacts-obtain.sh and a kernel-only deploy handler in netboot-deploy.sh (artifact_ready__netboot_kernel_deploy). Closes the kernel-only coherence gap — compile.sh kernel ... ENABLE_EXTENSIONS=netboot,netboot-deploy now refreshes vmlinuz + dtbs + /lib/modules/${kver}/ in one shot instead of needing a full image rebuild. Default-path computation in netboot.sh moved from extension_prepare_config into a lazy _netboot_compute_runtime_defaults helper called at hook time — fixes a latent bug where ${LINUXFAMILY} could be empty when the default was first materialized on flows that source the family config later in the dispatch.

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

    • Netboot: full nfs-root mode with per-host/MAC PXE/TFTP artifacts, staged kernel/DTB/initrd, builder-as-NFS-server support, and optional remote deploy over SSH/rsync.
  • Documentation

    • Comprehensive netboot guide covering build/deploy workflows, variables, Helios64 walkthrough, and troubleshooting.
  • Initramfs

    • DHCP-derived root-path propagation, NFS watchdog and cancel scripts, and initramfs dhcpcd hook.
  • Bug Fixes / Reliability

    • Safer export validation, atomic rootfs archive writes, preserved numeric owners/xattrs/ACLs/SELinux, symlink-aware ownership resets.
  • Behavior

    • NFS boot flow revised: derive console from DTB, probe active boot partition/mainline marker, clearer fallbacks and fatal/reset handling.

@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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c6a506c-7583-4e11-a6ca-c935109042e3

📥 Commits

Reviewing files that changed from the base of the PR and between 9d57350 and 39a1c92.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/functions/rootfs/rootfs-create.sh
🚧 Files skipped from review as they are similar to previous changes (13)
  • lib/functions/rootfs/create-cache.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/rootfs/rootfs-create.sh
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • config/templates/nfs-boot.cmd.template
  • lib/functions/image/rootfs-to-image.sh
  • extensions/netboot/netboot.sh
  • extensions/netboot/netboot-deploy.sh

📝 Walkthrough

Walkthrough

Adds a new netboot mode (ROOTFS_TYPE=nfs-root) and a comprehensive netboot extension (validation, staging, deploy hooks, initramfs/dhcpcd hooks, watchdog scripts), updates the U‑Boot NFS boot template for distro-boot and mainline kernels, adjusts image/partition flows for NFS-root, and broadens tar/extract metadata preservation.

Changes

Netboot feature & deployment

Layer / File(s) Summary
Feature flag & config
lib/functions/configuration/main-config.sh
Introduce ROOTFS_TYPE=nfs-root, set FIXED_IMAGE_SIZE=256, enable netboot extension, and skip host FS compatibility checks for nfs-root.
Extension entry & validation
extensions/netboot/netboot.sh
New netboot extension: defaults, NETBOOT_* runtime computation, client MAC normalization, ROOTFS_EXPORT_DIR normalization/validation, export-marker semantics, host pre-docker bind-mount hooks, propagate ${SRC} into container, and kernel NFS config enablement.
Artifact staging & hooks
extensions/netboot/netboot.sh, lib/functions/artifacts/artifacts-obtain.sh
Stage deterministic TFTP tree (kernel/DTB/uInitrd), validate BOOT_FDT_FILE, generate PXE/extlinux config, set NETBOOT_* outputs, and call netboot_artifacts_ready after rootfs archive/export; add artifact_ready hook point in obtain flow.
Rootfs archive/export integration
lib/functions/image/rootfs-to-image.sh, lib/functions/image/partitioning.sh
Treat nfs-root like nfs: compute image version suffix, atomic rootfs archive creation (gzip/zstd/none), rsync export path handling with safety realpath checks, add pre_create_rootfs_archive/post_create_rootfs_archive hooks, and skip creating local SD image for nfs-root; avoid allocating root partition for nfs/nfs-root.
Deploy automation
extensions/netboot/netboot-deploy.sh
New deploy hook: require NETBOOT_DEPLOY_SSH, optional remote TFTP probe, host pre-docker SSH key / known_hosts bind-mount support, secure scratch key handling, two-phase rsync (TFTP + pxelinux.cfg), optional upload+untar of ROOTFS_ARCHIVE preserving numeric IDs/xattrs/ACLs, and kernel-only deploy helper.
DHCP & initramfs integration
extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath, extensions/netboot/files/initramfs-hooks/netboot-rootpath
Add dhcpcd hook that records bootserver into per-interface /run/net-<if>.conf and an initramfs hook that installs that dhcpcd hook into generated initramfs.
Initramfs watchdog scripts
extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog, .../nfs-bottom/zz-netboot-watchdog-cancel
Add watchdog that reboots after 600s if booted with NFS root, and a cancel script that validates PID before signalling and removes pidfile.
U‑Boot NFS boot template
config/templates/nfs-boot.cmd.template
Rebuild bootargs (derive console from DTB /chosen/stdout-path, add rootwait earlycon, quote nfs_root), switch to distro-boot boot_dev, probe .next marker to prefer mainline flow: normalize .dts.dtb, load DTB from dtb/${dtb_name}, load uInitrd with ramdisk_addr_r="-" fallback, boot Image with booti or zImage with bootz (set fdt_high), otherwise fallback legacy script.bin/zImage legacy flow; print FATAL+reset on failures.
Customization & housekeeping
extensions/netboot/netboot.sh (post_customize hooks)
Stamp .netboot_export_marker, disable armbian-resize-filesystem.service, remove empty first-login trigger, install initramfs hooks and rebuild uInitrd.
PXE naming/activation
extensions/netboot/netboot.sh, extensions/netboot/README.md
Generate per-board/branch/release ± MAC/hostname PXE filenames and manage symlink activation rules documented in README.
Documentation
extensions/netboot/README.md
Comprehensive guide covering build-time/runtime variables, server vs DHCP-derived NFS behavior, PXE/TFTP/NFS layout, deploy hook usage, proxyDHCP caveat, Helios64 walkthrough, and troubleshooting.

Archive & metadata preservation + host ownership semantics

Layer / File(s) Summary
Tar archive creation
lib/functions/rootfs/rootfs-create.sh
Create rootfs cache/archive with --numeric-owner, configurable xattr include pattern, and include ACLs, SELinux labels, and sparse extents in tar command.
Tar extraction pipeline
lib/functions/rootfs/create-cache.sh
Restore numeric ownership and preserve xattrs/ACLs/SELinux on streamed extraction (--numeric-owner --xattrs --xattrs-include=... --acls --selinux --sparse).
Host ownership reset semantics
lib/functions/host/host-utils.sh
reset_uid_owner and reset_uid_owner_non_recursive now use chown -h to avoid following symlinks when resetting ownership.

Sequence Diagram

sequenceDiagram
    participant Builder as Builder Host
    participant Ext as Netboot Extension
    participant Staging as TFTP/NFS Staging
    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)
    Ext->>Builder: emit netboot_artifacts_ready (TFTP tree, PXE config, ROOTFS_ARCHIVE)
    Builder->>Remote: rsync TFTP payload + pxelinux configs
    Builder->>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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped through TFTP with bootfiles bright,
DTBs and kernels snug and tight.
PXE menus sing, the NFS fields hum,
Targets wake, their netboots come.
Hooray — I danced; the network’s fun!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding a netboot extension for TFTP+NFS diskless boot. It accurately reflects the primary objective of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and 03a0e14.

📒 Files selected for processing (13)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/README.md 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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and 5690997.

📒 Files selected for processing (14)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/README.md 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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and c822221.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog 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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and f5d9055.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

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: 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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and 8471b94.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/netboot.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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and 36dc9ae.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/netboot-deploy.sh
Comment thread extensions/netboot/netboot-deploy.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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and f5306ef.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread lib/functions/rootfs/rootfs-create.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.

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 win

Make watchdog cancellation tolerant to stale/already-exited PIDs.

kill can legitimately fail (race, stale pidfile). Mask the exit status to avoid unintended script abort in errexit contexts.

Suggested patch
-            [ "${watchdog_pid}" -gt 1 ] && kill "${watchdog_pid}" 2> /dev/null
+            [ "${watchdog_pid}" -gt 1 ] && kill "${watchdog_pid}" 2> /dev/null || true
Based on learnings, Armbian shell execution generally assumes `set -e`, so unhandled non-zero statuses can terminate flow unexpectedly.
🤖 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

📥 Commits

Reviewing files that changed from the base of the PR and between 165f8b1 and 7bcded6.

📒 Files selected for processing (15)
  • config/templates/nfs-boot.cmd.template
  • extensions/netboot/README.md
  • extensions/netboot/files/dhcpcd-hooks/71-netboot-rootpath
  • extensions/netboot/files/initramfs-hooks/netboot-rootpath
  • extensions/netboot/files/initramfs-scripts/init-premount/zz-netboot-watchdog
  • extensions/netboot/files/initramfs-scripts/nfs-bottom/zz-netboot-watchdog-cancel
  • extensions/netboot/netboot-deploy.sh
  • extensions/netboot/netboot.sh
  • lib/functions/artifacts/artifacts-obtain.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/host/host-utils.sh
  • lib/functions/image/partitioning.sh
  • lib/functions/image/rootfs-to-image.sh
  • lib/functions/rootfs/create-cache.sh
  • lib/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

Comment thread extensions/netboot/netboot-deploy.sh Outdated
Comment thread extensions/netboot/netboot-deploy.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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7bcded6 and 9d57350.

📒 Files selected for processing (2)
  • extensions/netboot/README.md
  • extensions/netboot/netboot-deploy.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • extensions/netboot/netboot-deploy.sh

Comment thread extensions/netboot/README.md Outdated
iav and others added 20 commits May 8, 2026 22:44
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>
… watchdog

Replace the `nfsroot=auto` (DHCP option 17) discovery path with
`nfsroot=<path>,tcp,v3` baked into the extlinux APPEND, and let the
kernel resolve the NFS server from DHCP siaddr at boot. Per-host rootfs
paths live in per-board pxelinux.cfg files; the server is a single
network-wide value. DHCP option 17 is no longer consulted in this mode
— it doesn't scale to multi-board setups (one path for all clients).

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>
The default NETBOOT_TFTP_PREFIX and (shared-mode) NETBOOT_NFS_PATH now
include a build-flavor suffix so CLI vs minimal vs desktop builds for
the same board/branch/release coexist side by side without colliding
on the staging tree, the deployed TFTP layout, or the NFS root.

  • CLI:     armbian/<family>/<board>/<branch>-<release>
  • min:     armbian/<family>/<board>/<branch>-<release>-min
  • desktop: armbian/<family>/<board>/<branch>-<release>-desktop

Flavor is computed once in extension_prepare_config and stored as the
global ${_NETBOOT_FLAVOR}, so the post-build hook that composes pxe_tag
picks it up too — pxelinux.cfg/<board>-<branch>-<release><flavor>.example
becomes a unique tagged file per flavor, and the deploy/symlink workflow
keeps working without changes.

Per-host NFS path (NETBOOT_HOSTNAME set) is left untouched — host names
are already disambiguating.

User-supplied NETBOOT_TFTP_PREFIX / NETBOOT_NFS_PATH are honored verbatim,
flavor is only added to the defaults.

README updated to document the new <flavor> segment in both default
patterns.

Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
NFS-side writes (rootfs archive untar with --numeric-owner/xattrs and
/lib/modules/<ver>/ rsync) preserve ownership only when the remote shell
runs as uid 0. With NETBOOT_DEPLOY_SUDO=no and a non-root SSH login the
write succeeds but the export gets rewritten under the login uid; the
next netboot then panics on broken permissions in /etc, /usr, modules.

Add _netboot_deploy_require_remote_root helper that probes 'id -u' over
the same SSH path the deploy will use and aborts with a precise error
when uid != 0 and SUDO=no. NETBOOT_DEPLOY_SUDO=yes (sudo -n) is the
documented elevation escape hatch and skips the probe.

Call it before:
  - rootfs archive untar in netboot_artifacts_ready (full-image deploy)
  - /lib/modules/<ver>/ rsync in artifact_ready__netboot_kernel_deploy

Doc on NETBOOT_DEPLOY_SUDO updated to spell out the constraint.

Reported-by: coderabbitai (review on PR armbian#9656)
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
The kernel-only deploy hook (artifact_ready__netboot_kernel_deploy) was
copying new DTBs but never removing ones that disappeared from the
linux-image package. A board pointing at a renamed or removed
BOOT_FDT_FILE would keep loading the old DTB against the fresh kernel —
exactly the kernel/DTB coherence gap this hook is meant to close.

Mirror the full-image deploy by adding --delete to the dtb/ rsync.
Safe scope: dtb/ lives entirely under the board+branch+release-scoped
NETBOOT_TFTP_PREFIX, so the prune only touches DTBs from this kernel's
package and never neighbours from other deployments under the shared
TFTP root.

Reported-by: coderabbitai (review on PR armbian#9656)
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
The earlier 'preserve xattrs/ACLs/sparse' commit added --sparse to tar
creation in rootfs-create.sh but missed the symmetric flag on the tar
extraction in create-cache.sh. Without --sparse on extract, sparse-extent
information stored in the tarball is silently discarded — files restore
as fully-allocated, negating the storage optimization the creation flag
was meant to enable.

Add --sparse to the 'tar xp' invocation that restores the rootfs cache
into ${SDCARD}.

Reported-by: coderabbitai (review on PR armbian#9656)
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
…amfs is build-side only

Initramfs cannot be regenerated correctly outside a full image build:
its content depends on the configured rootfs (customize_image hooks,
/etc/initramfs-tools tweaks, board-specific extensions, userpatches
overlay), and that context survives only during the build itself.
After deploy the configured rootfs lives only on the NFS server, which
may be OpenWRT/embedded/etc. and cannot run chroot+update-initramfs;
regenerating from the generic post-debootstrap rootfs cache would
produce a *different* initramfs than the one the full build would have
made — fake, not just incomplete.

Therefore artifact_ready__netboot_kernel_deploy now:

  - drops any pre-existing uInitrd from TFTP after the kernel rsync,
    so U-Boot does not pair the new kernel with a stale initramfs whose
    modules have a wrong vermagic
  - replaces the previous 'run update-initramfs on the server' guidance
    (which was wrong — server-side regen is impossible on most servers
    and produces a wrong initramfs even where it is) with a clear
    contract: 'for a fresh initramfs do a full image rebuild'
  - documents the boot-time consequence in the function header: boards
    with built-in boot networking (mvneta, etc.) come up cleanly
    without initramfs; modular-NIC boards fail fast at networking and
    the operator knows to do a full rebuild

README 'Kernel-only deploy' section reframed as a narrow optimization
for built-in-NIC boards rather than a general kernel refresh path,
with explicit guidance on when to use it vs the full image rebuild.

Closes the long-standing P2 (NETBOOT_DEPLOY_REGENERATE_INITRD) by
contract clarification, not deferred TODO: standalone initramfs
regeneration is an architecturally wrong frame, removed from scope.

Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
… failure

The remote shell ran with `set -e`, so a tar failure (disk full on the
NFS export, archive corruption, etc.) exited the shell before the
`rm -f` and left a 200-800 MB rootfs archive in /tmp. Repeated failed
deploys accumulate.

Restructure to: mkdir && tar; capture rc; rm -f unconditionally; exit
with the captured rc so Armbian's set -e still aborts on the real
failure.

Reported by coderabbitai (armbian#9656 review, line 438).

Assisted-by: Claude:claude-opus-4.7
…target

The deploy hook untars the rootfs archive with --xattrs/--acls/--selinux,
which are GNU-tar extensions. Busybox tar (Alpine, OpenWRT) silently
drops xattrs on extract — file capabilities like security.capability on
ping/mtr are lost and they fail at runtime, regardless of the host
filesystem's xattr support. Capability-probe with fallback was
considered and rejected: there is no Busybox-tar code path that
preserves xattrs, so the only honest fallback would be silently broken
caps. Document the requirement instead.

Reported by coderabbitai (armbian#9656 review, line 437).

Assisted-by: Claude:claude-opus-4.7
…ernel build

A full image build (`compile.sh build ...`) obtains a kernel artifact
internally and triggers `artifact_ready` with WHAT=kernel. The kernel-
only deploy handler treated that as a standalone kernel deploy and
rsynced `/lib/modules/<ver>/` into the NFS export. The subsequent full-
image rootfs archive deploy then fails on tar extract:

    tar: ./lib: Cannot create symlink to 'usr/lib': File exists

— the rsync materialized `lib/` as a directory, but the rootfs tarball
contains `./lib -> usr/lib` (Ubuntu/Debian usrmerge), and tar refuses
to overwrite a directory with a symlink.

Add a `${ARMBIAN_COMMAND}` gate so the kernel-only path only fires for
standalone `compile.sh kernel ...` runs. Full image builds keep using
the full rootfs archive deploy in
`netboot_artifacts_ready__deploy_to_remote_server`.

Reproducer: clean NFS export at `${NETBOOT_NFS_PATH}`, then run
`compile.sh build BOARD=helios4 BRANCH=edge BUILD_MINIMAL=yes
RELEASE=resolute ROOTFS_TYPE=nfs-root ENABLE_EXTENSIONS=netboot,netboot-deploy
NETBOOT_DEPLOY_SSH=root@${nfs_server} NETBOOT_NFS_PATH=...`. Without
this fix the deploy hook fails on the lib-symlink collision; with it,
the rootfs archive lands cleanly.

Assisted-by: Claude:claude-opus-4.7
Line 77 uses British 'normalises'; line 95 used American 'Normalize'.
Match the British form already established earlier in the file.

Reported by coderabbitai (armbian#9656 review, README.md:95).

Assisted-by: Claude:claude-opus-4.7
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