# How network boot deployment works

This describes the full flow from power-on to eMMC deploy/backup when using **network boot** with the provisioning LXC.

---

## Overview

1. **reTerminal** is set to try **eMMC first, then network** (EEPROM `BOOT_ORDER=0xf21`) via the dashboard **Update EEPROM** when the device is connected over USB boot, or set manually.
2. It is connected to the **same LAN as the LXC’s eth1** (e.g. 10.20.50.0/24).
3. On power-on it gets an IP via **DHCP** and loads **boot files via TFTP** from the LXC.
4. The **netboot environment** (kernel + rootfs) runs **provisioning-client.sh**, which registers with the **dashboard** and polls for an action.
5. In the **dashboard** you see the device under “Device detected (Network)” and choose **Deploy** or **Backup**.
6. The device performs the action (download image → write eMMC, or read eMMC → upload), then you can reboot to run from eMMC.

---

## Step-by-step

### 1. LXC (provisioning server)

- **eth0** = WAN (e.g. 10.130.60.141), internet for the LXC.
- **eth1** = LAN (e.g. 10.20.50.1/24):
  - **dnsmasq**: DHCP on eth1 (e.g. 10.20.50.100–200) and **TFTP** with next-server = 10.20.50.1, boot file = `start4cd.elf`.
  - **TFTP root** `/srv/tftpboot`: Raspberry Pi 4/CM4 boot files (from GitHub: start4cd.elf, fixup4cd.dat, kernel8.img, etc.).
  - **NAT**: traffic from 10.20.50.0/24 is masqueraded out eth0 so netbooted devices have internet if needed.

The **dashboard** (Flask) runs in the LXC and is reachable at e.g. `http://10.20.50.1:5000` from the LAN. The **golden image** for Deploy lives at `/var/lib/cm4-provisioning/golden.img` (same LXC or bind-mounted from host).

### 2. reTerminal (device)

- **EEPROM**: `BOOT_ORDER=0xf21` (eMMC first, then network). Set via dashboard **Update EEPROM** (USB boot) or manually (usbboot recovery / `rpi-eeprom-config` on device). Not set by first-boot.
- **Network**: Ethernet connected to the same segment as the LXC’s **eth1** (e.g. same switch/VLAN as 10.20.50.0/24).
- On **power-on**:
  1. Pi 4/CM4 firmware does **DHCP** on the wired interface.
  2. DHCP reply gives: IP (e.g. 10.20.50.100), **next-server (TFTP)** = 10.20.50.1, **boot filename** = start4cd.elf.
  3. Device **TFTP**s boot files from the LXC (start4cd.elf, fixup4cd.dat, kernel, DTB, etc.).
  4. It boots the **kernel** (and optionally an initramfs or NFS root). That environment must have **network**, **curl**, and **provisioning-client.sh**.

### 3. Netboot root / environment

The **TFTP**-loaded kernel (and optional initramfs/NFS root) must end up in an environment where:

- The device has an IP on the same LAN as the LXC (already from DHCP).
- **provisioning-client.sh** is present and run (e.g. from init, a login script, or a systemd service).
- **PROVISIONING_SERVER** is set to the dashboard URL on the LXC’s LAN IP, e.g.  
  `PROVISIONING_SERVER=http://10.20.50.1:5000`

So the “netboot environment” is either:

- A **custom initramfs** (recommended): build with **network-boot-initramfs/build.sh**, copy **initrd.img** to the TFTP root, and add `initramfs initrd.img followkernel` to **config.txt**. The initramfs brings up the network and runs the provisioning client. See **network-boot-initramfs/README.md**.
- A **minimal rootfs** (e.g. NFS) that runs the client script at boot, or  
- Any other setup that gets the client running with network and the right `PROVISIONING_SERVER`.

### 4. Provisioning client (on the device)

- **provisioning-client.sh**:
  1. **Registers**: `POST /api/register-device` with MAC and IP.
  2. **Polls**: `GET /api/device-action-poll?mac=...` every few seconds.
  3. When the dashboard returns **action = deploy** (with **url**):  
     downloads the image from **url** and runs `dd of=/dev/mmcblk0`.
  4. When the dashboard returns **action = backup** (with **upload_url**):  
     runs `dd if=/dev/mmcblk0` and POSTs the stream to **upload_url**.
  5. Then exits (and you can reboot to eMMC after deploy).

### 5. Dashboard (your actions)

- You open the dashboard at `http://10.20.50.1:5000` (or the LXC’s WAN IP if you’re not on the provisioning LAN).
- Under **“Device detected (Network)”** you see the device (identified by MAC).
- You click **Deploy**, **Backup**, or **Disable network boot**.
- **Deploy** / **Backup**: the dashboard sets the action and URL; the client runs dd + curl, then calls **/api/action-done**, which **disables DHCP network-boot options** on the LXC so the device will boot from eMMC on the next reboot. No need to unplug ethernet.
- **Disable network boot**: turns off DHCP options 66/67 (next-server, boot file) on the LXC. The DHCP server keeps running; devices just stop receiving netboot and will boot from local storage (eMMC) next time. Use this when you don't want to deploy or backup; the netbooted device can then reboot and boot from eMMC.

---

## Data flow summary

| Stage        | Where        | What happens |
|-------------|--------------|--------------|
| Boot        | reTerminal   | DHCP (get IP + next-server + boot file), then TFTP (load start4cd.elf, kernel, etc.). |
| Boot        | reTerminal   | Kernel (and netboot root) start; run **provisioning-client.sh** with `PROVISIONING_SERVER=http://10.20.50.1:5000`. |
| Register    | Device → LXC | POST /api/register-device (MAC, IP). |
| Poll        | Device → LXC | GET /api/device-action-poll?mac=... every 5 s. |
| Your choice | You → LXC   | In dashboard: click Deploy or Backup for that device. |
| Deploy      | LXC → device | Client GETs image URL, streams to `dd of=/dev/mmcblk0`. |
| Backup      | Device → LXC | Client `dd if=/dev/mmcblk0` and POSTs to upload_url. |
| After       | Device → LXC | Client calls **POST /api/action-done**; server disables DHCP netboot options. |
| After       | reTerminal   | Reboot; device boots from eMMC (no netboot advertised). |

---

## What you need in place

- **LXC**: eth1 = 10.20.50.1/24, dnsmasq (DHCP + TFTP on eth1; netboot options 66/67 in a separate snippet so they can be toggled), `/srv/tftpboot` with RPi 4 boot files, NAT for 10.20.50.0/24 via eth0. Toggle script **/opt/cm4-provisioning/toggle-network-boot-dhcp.sh** (enable/disable/status). Dashboard running, `golden.img` present for Deploy.  
  See **NETWORK-BOOT-LXC.md** and **setup-network-boot-on-lxc.sh**.
- **reTerminal**: EEPROM boot order = eMMC first, then network; Ethernet on 10.20.50.0/24; netboot environment that runs **provisioning-client.sh** with `PROVISIONING_SERVER=http://10.20.50.1:5000`.
- **Netboot root**: Must provide network, curl, and the client script (NFS, initramfs, or custom root).

The **TFTP** setup only gets the Pi to boot a kernel (and optional root). The **provisioning** (Deploy/Backup) is done by that kernel’s environment running the **network-client** against the dashboard on the LXC.
