diff --git a/http/boot.ipxe b/http/boot.ipxe index 58a48b6..5ba7016 100644 --- a/http/boot.ipxe +++ b/http/boot.ipxe @@ -1,17 +1,5 @@ #!ipxe -echo Booting Ubuntu Noble K3s Node via iPXE - -# Clear any previous images -imgfree - -echo Loading kernel from http://192.168.100.1:8800/vmlinuz -kernel --name vmlinuz http://192.168.100.1:8800/vmlinuz - -echo Loading initramfs from http://192.168.100.1:8800/initrd-netboot.img -initrd --name initrd http://192.168.100.1:8800/initrd-netboot.img - -echo Setting kernel arguments for HTTP root mounting -imgargs vmlinuz initrd=initrd rdinit=/init boot=netboot root=http://192.168.100.1:8800/filesystem.squashfs rootfstype=squashfs overlayroot=tmpfs ip=dhcp console=tty0 console=ttyS0,115200 loglevel=7 panic=-1 break=mountroot - -echo Booting system... -boot vmlinuz +echo Configuring network via DHCP... +dhcp +echo Chaining to dynamic boot script... +chain http://192.168.100.1:8800/netboot.ipxe diff --git a/initramfs/scripts/netboot b/initramfs/scripts/netboot index b2d827e..37adb8d 100755 --- a/initramfs/scripts/netboot +++ b/initramfs/scripts/netboot @@ -1,207 +1,85 @@ #!/bin/sh -# Netboot HTTP root mounting - sourced by initramfs init (functions already loaded) +# Netboot HTTP root mounting - HARDCODED VALUES - no cmdline parsing export PATH=/usr/bin:/usr/sbin:/bin:/sbin + +# HARDCODED CONFIGURATION +ROOT_URL="http://192.168.100.1:8800/filesystem.squashfs" +OVERLAYROOT="tmpfs" MOUNTPOINT=/root SQUASHFS_MOUNT=/mnt/squashfs OVERLAY_TMPFS=/mnt/overlay -# Hook functions for initramfs-tools boot script integration -netboot_top() -{ - if [ "${netboot_top_used}" != "yes" ]; then - [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-top" - run_scripts /scripts/netboot-top - [ "$quiet" != "y" ] && log_end_msg - fi - netboot_top_used=yes +# Debug logging to console +log() { + echo "$@" > /dev/console 2>&1 } -netboot_premount() -{ - if [ "${netboot_premount_used}" != "yes" ]; then - [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-premount" - run_scripts /scripts/netboot-premount - [ "$quiet" != "y" ] && log_end_msg - fi - netboot_premount_used=yes -} - -netboot_bottom() -{ - if [ "${netboot_premount_used}" = "yes" ] || [ "${netboot_top_used}" = "yes" ]; then - [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/netboot-bottom" - run_scripts /scripts/netboot-bottom - [ "$quiet" != "y" ] && log_end_msg - fi - netboot_premount_used=no - netboot_top_used=no -} - -# Parse kernel command line for HTTP root -parse_cmdline() { - for x in $(cat /proc/cmdline); do - case $x in - root=http://*) - export ROOT_URL="${x#root=}" ;; - rootfstype=*) - export ROOTFSTYPE="${x#rootfstype=}" ;; - overlayroot=*) - export OVERLAYROOT="${x#overlayroot=}" ;; - ip=*) - export BOOTIP="${x#ip=}" ;; - *) - : ;; - esac - done -} +# Minimal hook functions +netboot_top() { :; } +netboot_premount() { :; } +netboot_bottom() { :; } +mount_top() { :; } +mount_premount() { :; } +mount_bottom() { :; } mountroot() { - rc=1 + log "NETBOOT: ========================================" + log "NETBOOT: mountroot() HARDCODED VERSION" + log "NETBOOT: ROOT_URL=${ROOT_URL}" + log "NETBOOT: ========================================" - # Run hook scripts - netboot_top - netboot_premount + # Load network module + /sbin/modprobe af_packet - parse_cmdline - - if test -z "${ROOT_URL}"; then - log_failure_msg "No root URL defined (root=http://... not found)" - return ${rc} - fi - - # Configure networking before attempting downloads - log_begin_msg "Configuring network" - modprobe af_packet || log_warning_msg "af_packet load failed" - - # Load RTL8125 driver (already in module list but explicit load for debugging) - modprobe r8125 || log_warning_msg "r8125 driver load failed, may use generic driver" + # Wait for udev + wait_for_udev 10 + # Configure networking via DHCP + log "NETBOOT: Calling configure_networking..." configure_networking - udevadm trigger - timeout 30 udevadm settle || log_warning_msg "udevadm settle timed out" - export DEVICE - log_end_msg - # Validate networking is up - INTERFACE_UP=0 - for iface in $(ip link show | grep "^[0-9]" | awk -F: '{print $2}' | tr -d ' '); do - if ip addr show "$iface" | grep -q "inet "; then - INTERFACE_UP=1 - log_begin_msg "Interface $iface has IP address" - ip addr show "$iface" | grep "inet " | awk '{print $2}' - break - fi - done + # Check we got an IP + log "NETBOOT: Checking for IP address..." + if ! ip addr show | grep -q "inet "; then + log "NETBOOT: FATAL - no IP address" + return 1 + fi + log "NETBOOT: Network is up" - if [ $INTERFACE_UP -eq 0 ]; then - log_failure_msg "No network interface obtained an IP address" - return ${rc} + # Download squashfs + log "NETBOOT: Downloading ${ROOT_URL}..." + if ! wget -O /filesystem.squashfs "${ROOT_URL}"; then + log "NETBOOT: FATAL - wget failed" + return 1 + fi + log "NETBOOT: Download complete" + + # Create mount points + mkdir -p "${SQUASHFS_MOUNT}" "${OVERLAY_TMPFS}" + + # Mount squashfs + log "NETBOOT: Mounting squashfs..." + if ! mount -t squashfs /filesystem.squashfs "${SQUASHFS_MOUNT}" -o ro; then + log "NETBOOT: FATAL - squashfs mount failed" + return 1 fi - # Extract filename from URL - FILE_NAME=$(basename "${ROOT_URL}") - FILE_PATH="/${FILE_NAME}" + # Mount tmpfs for overlay + log "NETBOOT: Mounting tmpfs..." + if ! mount -t tmpfs -o size=2G tmpfs "${OVERLAY_TMPFS}"; then + log "NETBOOT: FATAL - tmpfs mount failed" + return 1 + fi + mkdir -p "${OVERLAY_TMPFS}/upper" "${OVERLAY_TMPFS}/work" - # Download the root filesystem with retries and timeouts - log_begin_msg "Downloading root filesystem from ${ROOT_URL}" - if wget --timeout=30 --tries=3 --waitretry=5 \ - --progress=dot:mega \ - "${ROOT_URL}" -O "${FILE_PATH}"; then - log_end_msg - else - log_failure_msg "Failed to download from ${ROOT_URL} after retries" - rm -f "${FILE_PATH}" - return ${rc} + # Mount overlay + log "NETBOOT: Mounting overlay..." + if ! mount -t overlay -o "lowerdir=${SQUASHFS_MOUNT},upperdir=${OVERLAY_TMPFS}/upper,workdir=${OVERLAY_TMPFS}/work" overlay "${MOUNTPOINT}"; then + log "NETBOOT: FATAL - overlay mount failed" + return 1 fi - # Verify the downloaded file is a valid SquashFS - if ! file "${FILE_PATH}" | grep -q "Squash"; then - log_failure_msg "Downloaded file is not a valid SquashFS image" - rm -f "${FILE_PATH}" - return ${rc} - fi - - # Handle SquashFS images with overlay - if echo "${FILE_NAME}" | grep -q squashfs; then - log_begin_msg "Setting up SquashFS with overlay" - - # Setup overlay if requested - need separate mount points - if [ -n "${OVERLAYROOT}" ]; then - # Create mount points - mkdir -p "${SQUASHFS_MOUNT}" "${OVERLAY_TMPFS}" - - # Mount read-only SquashFS to separate location - if ! mount -t squashfs "${FILE_PATH}" "${SQUASHFS_MOUNT}" -o ro; then - log_failure_msg "Failed to mount SquashFS at ${SQUASHFS_MOUNT}" - rm -f "${FILE_PATH}" - return ${rc} - fi - log_begin_msg "SquashFS mounted at ${SQUASHFS_MOUNT}" - log_end_msg - - log_begin_msg "Mounting tmpfs for overlay upper/work" - - # Create tmpfs for upper and work directories - if ! mount -t tmpfs -o size=2G tmpfs_overlay "${OVERLAY_TMPFS}"; then - log_failure_msg "Failed to mount tmpfs for overlay" - umount "${SQUASHFS_MOUNT}" - rm -f "${FILE_PATH}" - return ${rc} - fi - - # Create overlay structure - mkdir -p "${OVERLAY_TMPFS}/upper" "${OVERLAY_TMPFS}/work" - - # Mount overlay combining read-only lower + writable upper onto /root - if ! mount -t overlay \ - -o "lowerdir=${SQUASHFS_MOUNT},upperdir=${OVERLAY_TMPFS}/upper,workdir=${OVERLAY_TMPFS}/work" \ - overlay_root "${MOUNTPOINT}"; then - log_failure_msg "Failed to mount overlay filesystem" - umount "${OVERLAY_TMPFS}" - umount "${SQUASHFS_MOUNT}" - rm -f "${FILE_PATH}" - return ${rc} - fi - - log_end_msg - log_begin_msg "Overlay mounted at ${MOUNTPOINT} (lower=${SQUASHFS_MOUNT})" - log_end_msg - - # Clean up downloaded image as it's now mounted - rm -f "${FILE_PATH}" - rc=0 - else - # Direct SquashFS mount without overlay - mount directly to /root - if ! mount -t squashfs "${FILE_PATH}" "${MOUNTPOINT}" -o ro; then - log_failure_msg "Failed to mount SquashFS at ${MOUNTPOINT}" - rm -f "${FILE_PATH}" - return ${rc} - fi - log_begin_msg "Mounted SquashFS without overlay at ${MOUNTPOINT}" - log_end_msg - rc=0 - fi - else - log_failure_msg "Unknown filesystem type: ${FILE_NAME}" - rm -f "${FILE_PATH}" - fi - - return ${rc} -} - -# Standard mount hook wrappers expected by initramfs init -mount_top() -{ - netboot_top -} - -mount_premount() -{ - netboot_premount -} - -mount_bottom() -{ - netboot_bottom + log "NETBOOT: SUCCESS - root mounted at ${MOUNTPOINT}" + return 0 } diff --git a/rebuild-initramfs.sh b/rebuild-initramfs.sh new file mode 100755 index 0000000..7a9a01d --- /dev/null +++ b/rebuild-initramfs.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Rebuild initramfs with updated netboot script +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BUILD_DIR="$SCRIPT_DIR/build" +ROOTFS="$BUILD_DIR/rootfs" +HTTP_DIR="$SCRIPT_DIR/http" + +if [ ! -d "$ROOTFS" ]; then + echo "ERROR: Rootfs not found at $ROOTFS" + echo "Run build-image.sh first" + exit 1 +fi + +echo "=== Copying updated initramfs scripts ===" +cp "$SCRIPT_DIR/initramfs/scripts/netboot" "$ROOTFS/usr/share/initramfs-tools/scripts/netboot" +cp "$SCRIPT_DIR/initramfs/hooks/netboot" "$ROOTFS/usr/share/initramfs-tools/hooks/netboot" +cp "$SCRIPT_DIR/initramfs/initramfs.conf" "$ROOTFS/etc/initramfs-tools/initramfs.conf" +cp "$SCRIPT_DIR/initramfs/modules" "$ROOTFS/etc/initramfs-tools/modules" + +echo "=== Getting kernel version ===" +KVER=$(ls "$ROOTFS/lib/modules/" | head -1) +echo "Kernel version: $KVER" + +echo "=== Mounting filesystems for chroot ===" +mount --bind /proc "$ROOTFS/proc" +mount --bind /sys "$ROOTFS/sys" +mount --bind /dev "$ROOTFS/dev" + +cleanup() { + echo "=== Cleaning up mounts ===" + umount "$ROOTFS/proc" 2>/dev/null || true + umount "$ROOTFS/sys" 2>/dev/null || true + umount "$ROOTFS/dev" 2>/dev/null || true +} +trap cleanup EXIT + +echo "=== Rebuilding initramfs ===" +chroot "$ROOTFS" mkinitramfs -v -o /boot/initrd-netboot.img "$KVER" + +echo "=== Copying to http directory ===" +cp "$ROOTFS/boot/initrd-netboot.img" "$HTTP_DIR/" +chmod 644 "$HTTP_DIR/initrd-netboot.img" + +echo "" +echo "=== Done! ===" +echo "New initramfs: $HTTP_DIR/initrd-netboot.img" +ls -lh "$HTTP_DIR/initrd-netboot.img" +echo "" +echo "Run 'make deploy' to sync to NAS"