ADR 0007 defines the move to a native
Core. v0.131.0-beta.1 is the first published native beta. No native stable
release or guided migration for an existing box has shipped.
There are two channels:
| Channel | Tag | Use |
|---|---|---|
beta |
v0.X.Y-beta.N |
Test each candidate on real sites |
stable |
v0.X.Y |
Promote the same source commit after beta validation |
An old saved edge choice becomes beta. Native Core selects only published
0.x releases with a matching Linux package and checksum. Its launcher keeps
the current and previous releases for a same-schema rollback. A full backup
is still needed to recover older data or a failed disk.
2.x and 3.x will receive no further updates. All new releases use the new 0.x line. Switch now to follow current development. Do not install 3.x beta or use it as an intermediate upgrade. Old 0.x up to 0.130.x and 1.x are also retired. Start with Install and update FTW, which identifies the install type before giving commands.
A second SD card/host or separate Docker project lets an owner switch now with new settings and data. Guided migration preserving config, history, identity and goals has not shipped. Do not copy old databases into new Core or bypass the fresh installer's checks. If those data must move first, get help for that site and retain a verified backup off the host and a tested way back.
Old Docker's Update Center and updater still run their installed code. They may offer old releases; choosing beta does not migrate to new 0.x. Do not use those controls, moving image aliases, manual Core/updater swaps or retired migration scripts to cross lines. The scripts on master refuse the old paths.
GitHub releases/latest and old Docker :latest aliases remain on old 2.x to
avoid sending incompatible packages to old clients. They are not current
release recommendations and will not receive new 2.x updates. New releases use
exact 0.x tags. Publication never installs a release on a site by itself.
This is not the user migration path. migrate-native in the
operator CLI moves an older direct native systemd
site, one whose unit runs /opt/ftw/ftw as the ftw user, onto 0.x release
slots. The owner's home box was moved with it. It stages the release under a
separate root, /opt/ftw-native by default, and switches the unit with a
drop-in, so such a box keeps a different layout from a fresh install. Run it
on another computer, through an SSH tunnel to the box's API:
ssh -N -L 18080:127.0.0.1:8080 box.example
python3 scripts/ftwctl.py --url http://127.0.0.1:18080 status
python3 scripts/ftwctl.py --url http://127.0.0.1:18080 backup --output-dir ~/FTW-backups
python3 scripts/ftwctl.py --url http://127.0.0.1:18080 migrate-native \
--host box.example --tag v0.X.Y-beta.N \
--data-dir /srv/ftw/data --config /app/data/config.yaml \
--user-drivers /app/data/drivers --check-onlyRemove --check-only and pass --backup ~/FTW-backups/<printed-name>.ftwbak
only after checking the paths against that box. The CLI requires a backup from
the last 24 hours whose size and SHA-256 match Core's verified archive. It
checks that the same archive still exists under the service's data bind on the
box and that its site identity matches the SSH host. This avoids copying a
large archive back to /tmp or mixing up two boxes on the same version. It
then changes only the systemd start override and compares version, health,
driver names and working driver count. On failure it tries the old start
command. If old Core cannot read the data after a failed trial, it restores
the verified archive before retrying old Core. Keep the printed recovery-copy
path if automatic recovery fails. The CLI prints the active phase, elapsed time and completed/total bytes when
known; it says when a total is unknown. If LAN auth is on, set FTW_API_TOKEN
in the CLI process environment. Never paste that token into a command line.
The pilot refuses Docker and Home Assistant installations. Use the separate setup paths in the switch guide for those sites. A successful empty-data smoke test does not prove migration of a live household.
User-visible changes need a Changeset. The Version Packages PR updates
package.json and CHANGELOG.md.
After it merges, the owner dispatches
native-release.yml on master
for an exact v0.X.Y-beta.N tag. The workflow checks the source commit,
runs make verify, builds ARM64 and AMD64 packages, verifies their hashes
and publishes a prerelease. A dry_run checks the build without creating a
tag or release. A retry may keep a published asset only if its bytes match.
Before updating a test site, check that the workflow succeeded for the
chosen commit. The published ftw-native-release.json records that commit,
tag, channel, state schema and both package hashes. Match it to the release's
archives and .sha256 files. Then follow
Update a native box through SSH or a
local terminal and check the running version, health and live readings.
Publishing the release and installing it on a box are separate steps.
A native beta must run for a week on the home box and at least one other real
site with no open release-blocker. Only then can the owner dispatch the same
workflow for v0.X.Y stable, naming the tested source_beta. Stable checks
the published beta receipt and package hashes and uses the same source
commit. Beta and stable contain different embedded version strings, so each
package has its own hash and receipt. A tag, green CI run or published package
alone is not field validation.
On a native site the owner runs updates on the machine, by hand or from their
own timer or agent. Try the 0.x beta is the tester's
guide. The installer puts the ftw command on PATH:
ftw status # version, published release, last update, health
ftw update # install the next release on the saved channel
ftw update --channel stable # change the channel first
ftw rollback # return to the previous releaseftw update first checks that the disk has room: three times the current
release, for the archive, the unpacked release and some margin for the data
on the same disk. Core then downloads and verifies the 0.x package, stages
the new slot and restarts through the launcher. A native update keeps the
data in place and takes no local rollback point. On a terminal each step
shows a bar with size, rate and time left and ends as one line with its
duration; in a log or script it is one line per step. Core records every
finished step with its own timing, so a step that ends between two reads is
still shown. ftw update waits through the restart, including a history
migration, and reports the version and health that result. A trial only
becomes current after readiness;
a failed trial falls back to the previous Core, and ftw update names the
Core that runs. Already current exits 0, so a script can run the step
unattended; a failed step exits 1. The same steps are Core API calls. A
release that changes stored data (the state schema) cannot be installed
natively yet; ftw update stops before it changes anything.
ftw rollback returns to the previous release when it reads the same data.
ftw status also shows free space for releases and backups, and any local
rollback points an older Core left; native Core does not use them, so they
can be deleted.
The web UI on a native install shows the running version, a published
release and the command; it has no update controls. See
ADR 0007 and
full backup and restore.
Docker 0.x runs the same package without the launcher. Change FTW_VERSION
in .env and run docker compose up -d --build to update or go back; there
is no automatic fallback. See Docker.
Core, the compiled Energyplan worker and the Lua drivers pinned in
drivers/BUNDLED_SOURCE.json ship in one package, so ftw update and
ftw rollback move the drivers with Core. Core validates plans and keeps its
Go fallback. A newer driver installed from the signed channel runs until a
release brings a newer one, an older one chosen on purpose stays, and a
rollback runs the selection again; see
device repository. There is no optimizer sidecar in
the native install.
FTW's Core update does not update the host operating system, kernel or Docker engine. The operator handles host updates.
The old Docker workflows and receipts remain as historical and recovery material, not a path for new releases. Their current definitions refuse publication before checkout or registry writes; the Changesets version-PR job still runs on pushes for new 0.x. Do not dispatch historical workflow revisions. The native workflow cannot publish old Docker images or move old aliases. New Core code refuses cross-line update requests, but that guard cannot change an older installed binary. Do not use an old tag or script to bypass the guided migration.
Release notes keep the old state-schema markers for the remaining Docker
line. The native package carries its own state-schema receipt; the launcher
checks it before staging and refuses automatic rollback across a schema
change. Source and tests in go/internal/nativeupdate define that behavior.