Files
nixfiles/.claude/skills/flash-openwrt/SKILL.md
T
dev 98162ea989 openwrt: Build fergal's firmware in the flake
fergal is an 8-port SFP+ switch on a Realtek RTL9303, running OpenWrt
rather than RouterOS or UniFi. It is not part of the fabric yet, but
its firmware is now built here via astro's nix-openwrt-imagebuilder.
Packages are baked into the image: OpenWrt's package server keeps only
the current build of each feed, so installing at runtime stops working
as soon as the feed moves past the running firmware.

Those feed indexes rotate constantly, and upstream pins only the
indexes -- a mismatch drops evaluation into import-from-derivation,
putting this flake's eval on the network. The openwrt-feeds input pins
expanded per-package hashes instead, in a repository of its own
because they run to hundreds of thousands of generated lines.

Flashing gets a procedure doc and a thin skill pointing at it, the
same split as the box installation and nixpkgs upgrade procedures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 01:16:53 +01:00

38 lines
2.2 KiB
Markdown

---
name: flash-openwrt
description: >-
Flash a flake-built OpenWrt image onto one of the OpenWrt boxes (currently fergal): build the
image, pre-flight the box, back up its config, validate and stage the image, run sysupgrade, and
verify what came back. Use when the user wants to flash, reflash, upgrade or sysupgrade an OpenWrt
box, or after changing its baked-in package list.
---
# Flash an OpenWrt box
The canonical, agent-agnostic procedure lives in the repo at
[`docs/openwrt-flash.md`](../../../docs/openwrt-flash.md). Read it and follow the phases in order.
Key reminders (see the doc for the full steps):
- **Stop at the ⏸ before Phase 5.** Flashing reboots the box and cannot be interrupted partway.
Confirm with the user, and confirm a serial console is reachable, *before* writing anything.
- **Packages are baked into the image**, so a package change means a reflash. Edit the box's list in
[`openwrt/default.nix`](../../../openwrt/default.nix), rebuild, and check the built `.manifest`
a package name that doesn't exist is not a build error, it just isn't in the image.
- **`scp` does not work** on these boxes (no `sftp-server`). Move files with
`ssh <box> 'cat > /dev/…' < file` and `ssh <box> 'cat …' > file`.
- **Detach the upgrade with `setsid`**, not `nohup` (absent on busybox). `sysupgrade` kills the SSH
session mid-run, and an attached run dies with it — possibly after the firmware is erased.
- **Never reach for `sysupgrade -c`.** It needs `/overlay/upper/etc` and aborts *after* erasing the
firmware when that is missing, which is exactly the initramfs case. Plain `sysupgrade` already
keeps everything in `/lib/upgrade/keep.d/`.
- **Poll SSH to detect the reboot, never ping.** Successful pings return in milliseconds, so a
"wait for down" loop completes instantly and reports nonsense. Sleep between probes; expect about
three minutes.
- **Verify after**, don't assume: revision, management address, package count against the manifest,
and that the new packages are present and running.
The images are declared in [`openwrt/default.nix`](../../../openwrt/default.nix); background on the
outputs and the pinned package feeds is in
[`docs/deployment.md`](../../../docs/deployment.md#openwrt-images).