- Add CLAUDE.md with project architecture and build documentation - Add verify-image.sh script to validate generated netboot images - Fix boot.ipxe kernel parameters: - Add boot=netboot to invoke custom initramfs script - Add console=tty0 for VGA output alongside serial console - Fix earlyprintk serial specification - Remove dead symlink creation in build-image.sh (http/latest pointed to non-existent directory) The boot=netboot parameter is critical - without it, initramfs falls back to local boot and fails with /dev/root errors. The console changes enable viewing boot messages on monitor instead of only serial port.
146 lines
6.3 KiB
Markdown
146 lines
6.3 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This is a netboot system for diskless Ubuntu Noble (24.04) nodes designed for K3s clusters. It builds bootable images (kernel, initramfs, squashfs) that are served via HTTP and loaded using iPXE for network booting.
|
|
|
|
**Boot Flow:**
|
|
1. Machine PXE boots and loads iPXE from network
|
|
2. iPXE fetches and executes `boot.ipxe` configuration
|
|
3. iPXE downloads kernel (`vmlinuz`) and custom initramfs (`initrd-netboot.img`) over HTTP
|
|
4. Kernel boots with custom initramfs that downloads the squashfs root filesystem over HTTP
|
|
5. Root filesystem is mounted as read-only squashfs with writable overlay (tmpfs)
|
|
|
|
## Build Commands
|
|
|
|
```bash
|
|
# Build netboot image (15-30 minutes, requires sudo)
|
|
make build
|
|
# Builds: http/vmlinuz, http/initrd-netboot.img, http/filesystem.squashfs
|
|
|
|
# Deploy to NAS server
|
|
make deploy
|
|
# Syncs http/ directory to phoenix:/srv/netboot/http/
|
|
|
|
# Build and deploy in one step
|
|
make all
|
|
|
|
# Clean build artifacts (unmounts any stray filesystem mounts first)
|
|
make clean
|
|
|
|
# Check NAS connectivity
|
|
make check-nas
|
|
```
|
|
|
|
**Configuration:**
|
|
- `NAS_HOST=phoenix` - target server for deployment
|
|
- `NAS_PATH=/srv/netboot` - deployment path on NAS
|
|
- Edit these in `Makefile` if deployment target changes
|
|
|
|
## Architecture
|
|
|
|
### Build System
|
|
|
|
**build-image.sh** - Main build script that:
|
|
1. Creates Ubuntu Noble base system using `debootstrap`
|
|
2. Chroots into rootfs and installs packages (kernel, K3s prerequisites, container runtime, tools)
|
|
3. Configures system (networking via netplan, SSH keys, tmpfs mounts, services)
|
|
4. Builds custom initramfs using `mkinitramfs` with customizations from `initramfs/`
|
|
5. Creates compressed squashfs image of entire rootfs
|
|
6. Copies artifacts to `images/<VERSION>/` and `http/` directories
|
|
7. Sets proper file permissions (644) for HTTP serving
|
|
|
|
**Path handling:** All scripts use `SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"` to work from any location, not just hardcoded paths.
|
|
|
|
### Custom Initramfs
|
|
|
|
Located in `initramfs/` directory, passed to `mkinitramfs` with `-d` flag:
|
|
|
|
- **initramfs.conf** - Configuration (MODULES=most, COMPRESS=gzip, RESUME=none)
|
|
- **modules** - Extra kernel modules to include (squashfs, overlay, r8125 network driver for 2.5GbE)
|
|
- **hooks/netboot** - Copies binaries into initramfs (wget, curl, unsquashfs, switch_root)
|
|
- **scripts/netboot** - Provides `mountroot()` function that:
|
|
- Parses kernel cmdline for `root=http://...` URL and `overlayroot=tmpfs`
|
|
- Configures networking via `configure_networking`
|
|
- Downloads squashfs over HTTP using wget (with retries)
|
|
- Validates downloaded file is squashfs
|
|
- Mounts squashfs read-only
|
|
- If `overlayroot=tmpfs`, creates overlay with tmpfs upper layer for writes
|
|
|
|
### iPXE Boot Configuration
|
|
|
|
**http/boot.ipxe** - iPXE script that:
|
|
- Loads kernel from `http://192.168.100.1:8800/vmlinuz`
|
|
- Loads initramfs from `http://192.168.100.1:8800/initrd-netboot.img`
|
|
- Sets kernel args: `root=http://192.168.100.1:8800/filesystem.squashfs rootfstype=squashfs overlayroot=tmpfs ip=dhcp console=ttyS0,115200`
|
|
- Boots the kernel
|
|
|
|
**IMPORTANT:** The HTTP server IP (192.168.100.1:8800) is hardcoded in boot.ipxe. Update this if the boot server changes.
|
|
|
|
### System Configuration
|
|
|
|
Built systems are configured with:
|
|
- Norwegian keyboard layout (nb_NO.UTF-8 + en_US.UTF-8 locales)
|
|
- Root SSH access with specific authorized keys (see build-image.sh:138-141)
|
|
- Password auth disabled, pubkey only
|
|
- Network via netplan with DHCP (systemd-networkd)
|
|
- Ephemeral tmpfs mounts: /tmp (2G), /var/tmp (1G), /var/log (1G), /run (512M)
|
|
- systemd-journald configured for volatile storage (tmpfs, 256M max)
|
|
- K3s dependencies: apparmor, iptables, conntrack, containerd, runc
|
|
- No hibernation/resume support
|
|
|
|
### Utility Scripts
|
|
|
|
**chroot-rootfs.sh** - Enter chroot for manual tweaking
|
|
- Mounts proc/sys/dev into existing rootfs
|
|
- Cleanup trap unmounts on exit
|
|
- **Hardcoded path:** `/srv/netboot/build/rootfs` - update if repo moves
|
|
|
|
**rebuild-squashfs.sh** - Rebuild squashfs after manual changes
|
|
- Creates new versioned image from existing rootfs
|
|
- Skips full debootstrap/package installation
|
|
- **Hardcoded paths:** `/srv/netboot/*` - update if repo moves
|
|
|
|
## File Structure
|
|
|
|
```
|
|
.
|
|
├── build-image.sh # Main build script
|
|
├── Makefile # Build/deploy automation
|
|
├── boot.ipxe # iPXE boot configuration (in http/)
|
|
├── initramfs/ # Custom initramfs configuration
|
|
│ ├── initramfs.conf # mkinitramfs config
|
|
│ ├── modules # Extra kernel modules
|
|
│ ├── hooks/netboot # Binary copying hook
|
|
│ └── scripts/netboot # HTTP root mounting logic
|
|
├── chroot-rootfs.sh # Chroot helper (hardcoded paths)
|
|
├── rebuild-squashfs.sh # Rebuild helper (hardcoded paths)
|
|
├── build/ # Build artifacts (gitignored)
|
|
│ └── rootfs/ # debootstrap rootfs
|
|
├── images/ # Versioned builds (gitignored)
|
|
│ ├── <YYYYMMDD-HHMM>/ # Timestamped builds
|
|
│ └── latest -> <VERSION> # Symlink to latest
|
|
└── http/ # HTTP serving directory (gitignored except boot.ipxe)
|
|
├── boot.ipxe # iPXE config (tracked)
|
|
├── vmlinuz # Kernel (generated)
|
|
├── initrd-netboot.img # Custom initramfs (generated)
|
|
├── filesystem.squashfs # Root filesystem (generated)
|
|
└── version.txt # Build metadata (generated)
|
|
```
|
|
|
|
## Development Notes
|
|
|
|
**Hardcoded paths issue:** `chroot-rootfs.sh` and `rebuild-squashfs.sh` use hardcoded `/srv/netboot/` paths instead of dynamic path detection like `build-image.sh`. They need updating if repo is cloned elsewhere.
|
|
|
|
**Build requirements:**
|
|
- Ubuntu/Debian host with debootstrap, mkinitramfs, mksquashfs
|
|
- Sudo access for chroot operations and filesystem mounting
|
|
- 15-30 minute build time
|
|
- ~1GB disk space for build artifacts
|
|
|
|
**SSH key management:** Root SSH keys are embedded in build-image.sh:138-141. Update these before building images for new environments.
|
|
|
|
**Network driver:** RTL8125 (r8125) driver is explicitly loaded in initramfs for 2.5GbE NICs. If different NICs are used, update `initramfs/modules` and `initramfs/scripts/netboot`.
|