The mod replaces FlashForge's application outright, so the reasoning that still framed the web stack as coexisting with it was wrong on its own terms. * nginx and moonraker are documented as the only web stack on the printer. MOD_WEB=0 is a debugging switch that leaves ssh and the touchscreen, not a way back to stock -- that is a stock FlashForge package. The own-prefix rule stays, for the reason that is actually true: /usr/prog is the firmware partition and every FlashForge package reinstalls it, so a config written there is undone by the next stock flash. * Configs the mod ships now update when you have not edited them. A live file still byte-identical to the one the last package wrote is replaced; one you changed is kept and the new version lands beside it as .mod-new. $MODDIR/config-installed holds that last-written copy. Without this a config we own could only ever be written once: it exists on the second flash, so it would land as .mod-new forever and updates would never reach the printer. * Dropped the three dead /server/files/ alias blocks from nginx.conf. The regex location above them matches /server/ too and nginx gives regex locations precedence, so they never fired -- and had they fired, serving those paths from disk would 405 the DELETE and POST that Mainsail sends to the very same URLs. * Recorded what dies with firmwareExe, in docs/notes/25 and in the README: the :8898 REST API (FlashPrint, Orca's FlashForge profile, the mobile app) and the :8080 camera stream. The camera is the one that looks restorable and is not -- the MJPEG server is compiled into firmwareExe (its own accept loop, `GET /?action=stream`, boundarydonotcross) rather than being mjpg-streamer, so there is no daemon left to point a [webcam] at. assets/moonraker.conf carries the block, commented, for when a streamer is built for this board. Also in this change: the MOD_UI switch and the stock-UI path are gone, the chamber-heater model gate arrives with ff-model.cfg/ff-chamber.cfg, and the tests follow. make test: 32 passed, 1 failed. The failure is the probe end-to-end, which dies at "mount: failed to setup loop device for /stick.img" -- leaked loop devices on this build host, not the package. Probe installs nothing, and the default profile's install -> re-install -> boot passes in the same run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.4 KiB
Hardware testing
CI installs the package into a replica of the printer -- the real
rootfs.squashfs running under qemu-mipsel, on the printer's own busybox and
unTar (see printer-replica.md) -- and proves the
machine would still boot. What it cannot do is drive the screen, the MCUs, the
toolchanger or a print. This is the on-hardware procedure.
There are two flashes: probe, which changes nothing and proves the update
chain works on your machine, and default, which is the firmware.
Rule: do the probe first, and have the stock package on a spare stick before you flash the firmware. The probe costs five minutes and rules out a bad stick, the wrong model or a truncated download — the three failures that are annoying on a probe and frightening on a real flash.
Step zero: check the model gate
Every package carries a gate. Its runFirmwareExe.sh has MACHINE= / PID=
baked in, and compares them against the values app_startup.sh passes from
the firmware already on the printer. A mismatch is refused with
"Firmware does not match machine type" — it will not install, and it is not a
valid recovery image either.
| Model | MACHINE | PID |
|---|---|---|
| Creator 5 | Creator5 |
0028 |
| Creator 5 Pro | Creator5Pro |
0029 |
The gate is not cosmetic: the two models ship different firmwareExe
binaries, so a package must be built from the stock package for its own
model. make release builds both.
Find yours in Settings → About, or in
/usr/data/firmwareRes/config/general.json (machineName), and set
TARGET_MACHINE in config.env. Then:
make default && make verify # one model
make release PROFILE=default # both, into dist/
verify.sh fails loudly on a mismatch. You must start from a stock package
built for your own model — the mod inherits the gate from whatever package
you unpack.
Before the first flash
- Put a copy of the stock FlashForge package for your model on a spare
USB stick and keep it physically separate. That is your recovery image:
flashing it restores every file the mod touches (proven by
make test-recovery). Check it is the right model first — see above. - Note your printer's serial number (Settings → About). The factory image restores a placeholder serial and you may need to put yours back.
- Confirm you can reach the printer's IP.
make testpasses.make rootfs && make test-ashpasses — this parses every script that will run on the printer using the printer's own busybox ash.
Two USB sticks, FAT32, both packages at the root of the stick (not in a
folder). Ship both filenames (Creator5-* and Creator5Pro-*): the Pro's
boot script globs Creator5Pro-*.tgz, the non-Pro globs Creator5-*.tgz.
Stage 0 — probe (make probe)
Changes nothing. Reinstalls the stock software component byte-for-byte and writes a diagnostic report to the USB stick.
Flash it, wait for the reboot, pull the stick and read:
| File on the stick | What it tells you |
|---|---|
anvil-report.txt |
free space, partitions, installed versions, init layout, whether nginx/moonraker really exist |
anvil-stock-etc.tar |
the whole /etc, so the init chain can be studied offline |
anvil-stock-nginx.conf |
the stock nginx config (not shipped in any update package) |
anvil-stock-bootscripts.tar |
app_startup.sh, start.sh, passwd, shadow as they exist on YOUR unit |
Go/no-go: the report exists and the printer boots normally. If the stick comes back empty, the package never installed — nothing was changed, and you have learned that before risking anything.
Check in the report:
- free space on
/usr/datais comfortably above the size of your full package moonrakerDmn: yesandnginx binary: yes- the
INIT SYSTEMblock matches expectations (busybox init,/etc/init.d/rcS,S50dropbearpresent)
Stage 1 — the firmware (make default)
One flash brings up everything: a root password you know, Mainsail and moonraker, the forked Klipper with the toolchanger extras, and HelixScreen on the touchscreen in place of FlashForge's UI.
The root password is generated on the printer. Nothing is baked into the
package: the installer picks a random one, sets it, and writes it to
anvil-password.txt on the USB stick you flashed from. Pull the stick after
the flash and read it — then save the password somewhere safe and delete the
file. If the stick is not writable no password is set at all, and the install
log says so.
To choose your own instead, set it before you build:
openssl passwd -6 'your-password' # paste into ROOT_PW_HASH in config.env
ssh works because the stock rootfs already ships /usr/sbin/dropbear and an
enabled /etc/init.d/S50dropbear — port 22 is already open on a stock
printer, there is simply no published password. That shell is your recovery
channel, so confirm it before you touch anything else.
Before flashing, re-read the warnings about Z offsets in docs/toolchange.md. A wrong offset drives the nozzle into the plate.
Understand the safety net first, because FlashForge's UI is gone from the screen and there is nothing to fall back to:
- ssh and Mainsail do not depend on the screen.
/etc/init.d/S50dropbearis stock and runs long before the UI, andinit.d/S60webstarts nginx and moonraker independently. They are your way in when the screen is dark. init.d/S70klipperowns Klipper startup, because on stock firmware it wasfirmwareExe— not any init script — that ran/usr/prog/klipper/start.sh. Without this the printer would boot to a working screen and be unable to move.- If the UI dies repeatedly,
SAFE-MODElatches after 3 boots and the printer boots headless — no UI started at all — rather than crash-looping. ssh and Mainsail stay up. Delete/usr/data/anvil/SAFE-MODEto try again.
Go/no-go, in this order — with the emergency stop within reach:
Access first, so that everything below is diagnosable:
ssh root@PRINTERgets you a shell (password fromanvil-password.txton the stick)http://PRINTER/loads Mainsail- Mainsail shows the printer as ready, not "Klipper reports: ERROR"
If Mainsail loads but Klipper errors, stop here and read
/usr/data/logs/printer.log over ssh. Do not go on to motion.
Then the screen:
- HelixScreen appears on the touchscreen
- Klipper is still running — this is the one people miss
- heaters and motion respond from the touchscreen
Then motion, which is the part that can damage the machine:
ssh root@PRINTER 'grep -i error /usr/data/logs/printer.log | tail'is cleanTOOLCHANGE_STATUSresponds in the Mainsail console- home all axes — watch the first Z move
- one tool change, by hand, at temperature
- a single-tool test print
- a multi-tool test print
The .cfg includes are not wired up automatically — a tuned printer.cfg
is never modified. New files arrive as *.mod-new. Add the includes by hand
in the order given in the toolchanger README, then run
FF_IMPORT_FIRMWARE_CONFIG once.
Recovering from a bad UI, in increasing severity:
ssh root@PRINTER
/usr/data/anvil/init.d/S80ui status # what did it choose, and why
touch /usr/data/anvil/SAFE-MODE # boot headless next time (ssh + Mainsail only)
reboot
If ssh is gone too, flash the stock FlashForge package for your model.
If something goes wrong
| Symptom | Do this |
|---|---|
| Printer boots, screen blank | ssh in; /usr/data/anvil/init.d/S80ui status; touch /usr/data/anvil/SAFE-MODE; reboot |
| No ssh, no screen | flash the stock package for your model |
| Recovery stick does not help | try a newer stock FlashForge package for your model |
| Still broken | factory package (Creator5Pro-factory-*.tgz plus the separate Creator5Pro-factory.tar.xz on the same stick; needs 800 MB free) |
The mod never creates a mount point named like a mod, specifically so that FlashForge's factory-restore package — which greps the mount table for a known community mod's name and refuses to run when it matches — remains usable as a last resort.
Logs worth reading, all on the data partition and all surviving a reboot:
/usr/data/anvil-install.log what the installer did
/usr/data/logs/anvil-boot.log services + UI choice at each boot
/usr/data/logs/printer.log klipper
/usr/data/logs/helixscreen.log helixscreen