citadel-core/scripts/update/README.md
2022-01-21 21:37:48 +01:00

4.9 KiB

Over-The-Air (OTA) Updates

How over-the-air updates work on Citadel.

Execution Flow

  1. New developments across the any/entire fleet of Citadel's services (bitcoind, lnd, dashboard, middleware, etc) are made, which maintain their own independent version-control and release-schedule. Subsequently, their new docker images are built, tagged and pushed to Docker Hub.

  2. The newly built and tagged images are updated in the main repository's (i.e. this repo) docker-compose.yml file.

  3. Any new developments to the main repository (i.e. this repo) are made, eg. adding a new directory or a new config file.

  4. To prepare a new release of Citadel, called vX.Y.Z, a PR is opened that updates the version in README.md and info.json file to:

{
    "version": "X.Y.Z",
    "name": "Citadel vX.Y.Z",
    "notes": "This release contains a number of bug fixes and new features.",
    "requires": ">=A.B.C"
}
  1. Once the PR is merged, the main branch is immediately tagged vX.Y.Z and released on GitHub.

  2. Thus the new info.json will automatically be available at https://raw.githubusercontent.com/runcitadel/core/main/info.json. This is what triggers the OTA update.

  3. When the user opens his dashboard, it periodically polls manager to check for new updates.

  4. manager fetches the latest info.json from Citadel's main repo's main branch using GET https://raw.githubusercontent.com/runcitadel/core/main/info.json, compares it's version with the version of the local $CITADEL_ROOT/info.json file, and exits if both the versions are same.

  5. If fetched version > local version, manager checks if local version satisfies the requires condition in the fetched info.json.

  6. If not, manager computes the minimum satisfactory version, called L.M.N, required for update. Eg, for "requires": ">=1.2.2" the minimum satisfactory version would be 1.2.2. manager then makes a GET request to https://raw.githubusercontent.com/runcitadel/core/vL.M.N/info.json and repeats step 8 and 9 until local version < fetched version AND local version fulfills the fetched requires condition.

  7. manager then returns the satisfying info.json to dashboard.

  8. dashboard then alerts the user regarding the available update, and after the user consents, it makes a POST request to manager to start the update process.

  9. manager adds the updateTo key to $CITADEL_ROOT/statuses/update-status.json (a file used to continuosly update the user with the update status and progress) with the update release tag.

{
    ...
    "updateTo": "vX.Y.Z"
    ...
}
  1. manager then creates an update signal file on the mounted host OS volume ($CITADEL_ROOT/events/signals/update) and returns OK to the dashboard.

  2. karen is triggered (obviously) as soon as $CITADEL_ROOT/events/signals/update is touched/updated, and immediately runs the update trigger script $CITADEL_ROOT/events/triggers/update as root.

  3. $CITADEL_ROOT/events/triggers/update clones release vX.Y.Z from github in $CITADEL_ROOT/.citadel-vX.Y.Z.

  4. $CITADEL_ROOT/events/triggers/update then executes all of the following update scripts from the new release $CITADEL_ROOT/.citadel-vX.Y.Z one-by-one:

All of the above scripts continuously update $CITADEL_ROOT/statuses/update-status.json with the progress of update, which the dashboard periodically fetches every 2s via manager to keep the user updated.

Further improvements

  • OTA updates should not trust GitHub, they should verify signed checksums before installing
  • Catch any error during the update and restore from the backup
  • Restore from backup on power-failure