# Provisioning initramfs for network boot

Minimal initramfs that runs **provisioning-client.sh** after bringing up the network. Used with Raspberry Pi 4 / CM4 (reTerminal) when booting via TFTP from the provisioning LXC.

## What it does

1. Mounts `/proc`, `/sys`, `/dev`, `/dev/pts`.
2. Ensures an IP (reuses kernel DHCP or runs `udhcpc` on eth0).
3. Runs the provisioning client with `PROVISIONING_SERVER` (default `http://10.20.50.1:5000`, overridable via kernel cmdline).
4. The client registers with the dashboard and polls for **Deploy** or **Backup**; on action it performs the dd + curl and exits.

## Build

**On x86_64 (e.g. your laptop):** the script uses **Podman** or **Docker** with `--platform linux/arm64` to run an arm64 container and copy busybox + curl into the initramfs. Your host must be able to *run* arm64 containers (via QEMU emulation).

- **Fedora:** one-time setup to enable arm64 containers:
  ```bash
  sudo dnf install -y qemu-user-static
  ```
  Then run the build (Podman will use QEMU automatically):
  ```bash
  cd emmc-provisioning/network-boot-initramfs
  ./build.sh
  ```
- If you don’t install `qemu-user-static`, the script will fail with an error and print the same instructions and an alternative (build on a Pi).

**On a Raspberry Pi 4 or other aarch64 host:** no Docker. Install deps and run:

```bash
sudo apt install -y busybox curl
./build.sh
```

Optional: pass an output path:

```bash
./build.sh /path/to/initrd.img
```

## Deploy to TFTP root

1. Copy **initrd.img** to the LXC TFTP root (e.g. `/srv/tftpboot`):

   ```bash
   scp initrd.img root@10.130.60.141:/srv/tftpboot/
   ```

2. In the TFTP root, ensure **config.txt** (Raspberry Pi boot config) includes the initramfs line. If you use the stock `config.txt` from the RPi firmware repo, add:

   ```
   initramfs initrd.img followkernel
   ```

   So the firmware loads the kernel and then the initrd that “follows” it. The Pi will boot the kernel and run `/init` from the initrd.

3. If your DHCP already points the Pi to this TFTP server and `start4cd.elf`, the Pi will load kernel + initrd from the same root. No NFS or extra server needed.

## Kernel cmdline (optional)

To override the provisioning server URL (e.g. if the dashboard is on another IP), add to **cmdline.txt** in the TFTP root (or append to the kernel command line):

```
provisioning_server=http://10.20.50.1:5000
```

The init script reads `provisioning_server=` from `/proc/cmdline` and exports `PROVISIONING_SERVER` for the client.

### Rescue mode (stuck in network-only boot)

If the device has **BOOT_ORDER=0x2** (network only), it never boots from eMMC. To get a shell and change boot order using the eMMC’s **rpi-eeprom-config**, add **provisioning_rescue=1** to the kernel cmdline (e.g. in the TFTP-served `cmdline.txt` for that device). The initramfs will then start an interactive shell instead of the provisioning client. Run **/rescue-eeprom.sh** to mount eMMC and chroot to run `rpi-eeprom-config --edit`; set `BOOT_ORDER=0x1` or `0x21`, save, then `reboot`. See **docs/NETWORK-BOOT-TROUBLESHOOTING.md** (“Stuck in network-only boot”) for full steps.

## Flow summary

1. Pi does DHCP → gets IP and TFTP server (e.g. 10.20.50.1).
2. Pi loads via TFTP: start4cd.elf, fixup4cd.dat, config.txt, cmdline.txt, kernel8.img, **initrd.img**.
3. Kernel boots with initrd as root; runs `/init`.
4. Init mounts minimal fs, ensures network, runs `/provisioning-client.sh`.
5. Client registers and polls; you choose Deploy or Backup in the dashboard; client runs dd + curl and exits.
6. After deploy, power cycle the Pi so it boots from eMMC.

See **docs/NETWORK-BOOT-DEPLOYMENT-FLOW.md** for the full deployment flow.
