Provisioning
Deploy AtomixOS to a Rock64 device by building a flashable disk image and writing it
to eMMC with dd (or mise run flash).
After Provisioning
On first boot:
- U-Boot loads
boot.scrfrom boot-a, echoes build ID, boots the kernel with initrd - The initrd mounts the selected squashfs slot at
/run/rootfs-base, thensysroot.mountassembles/as OverlayFS with a tmpfs-backed upper/work directory under/run/overlay-root - Initrd
systemd-repartcreates the/datapartition (f2fs) on first boot using the remaining eMMC space - Initrd persists a fresh-flash marker so switched-root provisioning can distinguish a new flash from a later
reprovisioned
/datawipe first-boot.servicelooks for/boot/config.tomlonly on a fresh flash, then USBconfig.toml, then starts the bootstrap web console on WAN and LAN port8080; after provisioning it narrows to the LAN gateway endpoint and waits indefinitely for operator input when no seed is present- The imported config is validated, persisted under
/data/config/, rendered into canonical Quadlet files, and synced into the active rootful and rootless Quadlet paths first-boot.serviceapplies Quadlets, LAN settings, and provisioned firewall rules, then marks the RAUC slot as good only if those runtime apply steps succeed- Network interfaces come up (eth0 via DHCP, eth1 static);
systemd-networkd-wait-onlineuses 30s timeout withanyInterface=true - Services start: dnsmasq, chrony, sshd, and the RAUC update timer when RAUC is enabled
The device is then ready to receive OTA updates and serve LAN clients.
For the canonical persisted state and runtime schemas, see Firmware Data Flow and Runtime Boundaries.
Reprovisioning
Wiping /data returns the device to the unprovisioned state without changing the A/B slot layout.
On the next boot:
- Initrd sees that
boot-balready exists, so it does not mark the boot as a fresh flash /boot/config.tomlis not replayedfirst-boot.servicesearches USBconfig.tomlsources first- If no USB seed is found, the bootstrap web console starts on WAN and LAN port
8080
Imported operator state remains bounded to /data/config/, including the imported config.toml, rendered Quadlet
files, admin SSH authorized keys, and other provisioning-derived runtime inputs.
Provisioning Service API
The bootstrap console is backed by a long-lived Litestar service. API routes are grouped by domain but still wired explicitly by the app factory:
| Route | Behavior |
|---|---|
GET /api/health | Returns service liveness. |
GET /api/nonce | Issues a single-use nonce for SSH-signature authentication. |
POST /api/validate | Validates a config.toml or config bundle without applying it. |
POST /api/config | Accepts a config source and returns 202 Accepted with a job URL. |
GET /api/jobs/{id} | Returns current provisioning job status, events, result, and rollback state. |
Mutating apply jobs are single-flight. Clients poll the returned job URL for progress and final status.
USB Recovery Mode
If the reset button is held from power-on for 5 seconds, U-Boot enters USB mass storage mode instead of booting Linux. The Rock64 OTG USB port then exposes the full eMMC as a removable disk, allowing the host to write a fresh image directly.