In #776, we added the `--allow-releaseinfo-change-suite` to avoid erroring out if the Raspbian apt repo changed suite names. In #1604, we deleted the `apt update` command entirely, as it seemed unnecessary after deleting Ansible. In #1623, we brought back the `apt update` command, but we left off the flag we were previously using. In recent installs, I'm seeing this warning: ```bash 4 packages can be upgraded. Run 'apt list --upgradable' to see them. N: Repository 'http://raspbian.raspberrypi.org/raspbian bullseye InRelease' changed its 'Suite' value from 'stable' to 'oldstable' Reading package lists... Done ``` For the sake of preserving longstanging behavior, I think we should bring back the `--allow-releaseinfo-change-suite` flag. <a data-ca-tag href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1630"><img src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review on CodeApprove" /></a>
Bundler
The bundler is responsible for creating a single-file distributable called “TinyPilot bundle”.
Components
Bundle
The TinyPilot bundle contains all the TinyPilot-owned code required to install TinyPilot on a device.
The create-bundle script generates the bundle from the bundle/ folder. That folder contains a few “static” configuration files. At build time, the create-bundle script adds the following dependencies:
- The TinyPilot web service
- The root
Dockerfilepacks the TinyPilot web service as a Debian package from the source files.
- The root
- Metadata
- E.g., version/build information
The entrypoint for installing the bundle is the bundle/install script. It contains the installation logic that installs TinyPilot and all of its dependencies.
Gatekeeper Web Service
Gatekeeper is TinyPilot’s web service for hosting and distributing bundles. See the Gatekeeper README for more info.
Our CircleCI pipeline automatically builds and uploads new bundles to Gatekeeper:
- For Community, it releases every commit to the
masterbranch - For Pro, it only releases tags with a particular format (e.g.,
2.4.1)
get-tinypilot.sh
get-tinypilot.sh (get-tinypilot-pro.sh for Pro) facilitates the installation process.
For installing TinyPilot on the device, get-tinypilot.sh unpacks the bundle to /mnt/tinypilot-installer and invokes the install script.
To avoid excessive writes to the filesystem, the bundle is downloaded and unpacked on a volatile RAMdisk mounted at /mnt/tinypilot-installer.
On a fresh device, the user runs get-tinypilot.sh manually. On a device with an existing TinyPilot installation, TinyPilot’s update process invokes get-tinypilot.sh “under the hood”.
get-tinypilot.sh is idempotent, so it’s safe to run repeatedly.
Installation Process
The installation procedure consists of the following steps. The procedure is slightly different between TinyPilot Community and Pro.
TinyPilot Community
get-tinypilot.shretrieves latest bundle from Gatekeeper.get-tinypilot.shunpacks bundle and invokesinstallscript.
TinyPilot Pro
get-tinypilot-pro.shchecks whether the caller supplied a version flag.- If the version flag is absent,
get-tinypilot-pro.shasks Gatekeeper what the latest available version is.
- If the version flag is absent,
get-tinypilot-pro.shrequests the bundle with the desired version from Gatekeeper.get-tinypilot-pro.shunpacks bundle and invokesinstallscript.
Update Process
When performing a version-to-version update, TinyPilot carries out the above installation procedure automatically after the user requests an update via the web UI.
- From the TinyPilot web UI, the user clicks “System” > “Update”.
- TinyPilot’s web service backend returns two versions:
- The one that is currently installed on the device.
- The latest available version, which the TinyPilot web service retrieves from Gatekeeper.
- If the versions are different, the frontend shows an “Update” button.
- When the user clicks on “Update”, TinyPilot’s web service backend runs the update launcher asynchronously.
- On TinyPilot Pro, the update launcher stores the desired target version in a file.
- The update launcher starts the
tinypilot-updatersystemd service. - The
tinypilot-updatersystemd service executes theupdate-servicePython script. - The
update-serviceinvokes the privileged/opt/tinypilot-privileged/scripts/updatescript. - The privileged
updatescript downloadsget-tinypilot.sh/get-tinypilot-pro.sh(see above) and executes that script in the privileged context.- On TinyPilot Pro, the privileged
updatescript reads and passes on the target version from the file that the update launcher had populated previously.
- On TinyPilot Pro, the privileged
The indirection in the update flow has the following reasons:
- The system update is a long-running process, so we use systemd to run it asynchronously.
- To avoid an elevation of privilege vulnerability, the
update-service(owned by thetinypilotuser) delegates to the privilegedupdatescript (owned by therootuser).
There is one main difference between the Community and Pro edition:
- On TinyPilot Community, the update process always installs the latest available version (i.e., built from the latest commit to the
masterbranch). - On TinyPilot Pro, the update process installs the particular version that was returned from Gatekeeper and shown in the UI.
History
Until August/September 2022, the installation and update flows used to look differently. You can read up on the rationale behind the overhaul in detail in the “update overhaul document”. We broke down the overhaul into individual tasks, which you can find in this mega ticket.
From a high level, the differences were:
- The previous update flow relied on git repositories. So instead of shipping a self-contained bundle, the deployment of new code happened via
git pull. However,gitis not the right tool for software distribution, so over time we ran into several issues and limitations with this setup. - There were no license checks for TinyPilot Pro. Instead, the only protection mechanism of the Pro source code was by keeping the URL of the git mirror secret.
- Because the legacy update flow depended on commodity Git hosting, it prevented us from controlling important parts of the update experience such as ensuring valid version transitions, phasing rollouts into stages, and performing license checks.