bt-update runs as root and installs helpers, sudoers, systemd units and config; none of it is rolled back. Documents the order of stage steps, the 'old bt-update runs the OTA' pitfall and how to add a system change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.0 KiB
OTA: что обновление может менять в системе
Изначально OTA задумывалась как замена только приложения (бинарник, веб, коллектор). На практике bt-update выполняется от root и уже меняет системные файлы: хелперы, sudoers, юниты systemd, конфиги systemd. Здесь описано, что именно он делает, в каком порядке и как добавить новую системную правку.
Как запускается
- Веб (пользователь
buttontask) принимает пакет и вызываетsudo -n /opt/buttontask/scripts/bt-update stage <pkg>. Это разрешено правилом в/etc/sudoers.d/buttontask. bt-updateперезапускает сам себя черезsystemd-runв отдельном временном юнитеbuttontask-update-<ts>. Поэтому он переживает перезапускbuttontask-webпосреди обновления.- Прогресс пишется в
run/update-status.json, подробный лог вrun/update.log.
Порядок stage
| Шаг | Что делается | Куда пишет |
|---|---|---|
| 1. распаковка | пакет → versions/<ver>, проверка manifest.json |
/opt/buttontask/versions/ |
2. sync_helpers |
все webconfig/scripts/bt-* → root-owned хелперы; sudoers ставится только если прошёл visudo -c |
/opt/buttontask/scripts/, /etc/sudoers.d/buttontask |
| 3. коллектор | buttontask-collector.service, enable/disable по collectorEnabled |
/etc/systemd/system/ |
| 4. bluetooth | drop-in Restart=always для bluetooth.service |
/etc/systemd/system/bluetooth.service.d/override.conf |
5. sync_system |
buttontask.service, buttontask-displaywatch.service, аппаратный вотчдог; daemon-reload или daemon-reexec, enable/restart displaywatch |
/etc/systemd/system/, /etc/systemd/system.conf.d/ |
| 6. переключение | current → новая версия, перезапуск сервисов |
|
| 7. health-check | /healthz, свежий run/qt.alive, buttontask active (30 с) |
|
| 8. откат | при провале current → предыдущая версия, перезапуск |
Подкоманды для ручного запуска:
sudo /opt/buttontask/scripts/bt-update sync-helpers # шаг 2 из текущей версии
sudo /opt/buttontask/scripts/bt-update sync-system # шаг 5 из текущей версии
Важные ограничения
1. OTA выполняет старый bt-update
Обновление запускает bt-update, который уже установлен на устройстве, а не тот, что лежит в пакете. Новый bt-update приезжает на шаге 2 и работает только со следующей OTA. Значит, системную правку, добавленную в bt-update, первая OTA не применит.
Как это обойти (сделано для вотчдога): веб при каждом старте вызывает sudo bt-update sync-system (sync_system_units() в webconfig/system_info.py). На шаге 6 веб перезапускается уже из новой версии, вызывает новый bt-update (его установил шаг 2), и правка применяется в ту же OTA. Поэтому sync-system должен быть идемпотентным: без изменений он ничего не делает (install_if_changed + cmp).
2. Системные правки не откатываются
Шаги 2–5 выполняются до health-check, и откат возвращает только симлинк current. Юниты, sudoers и конфиги остаются от новой версии. Отсюда правило: любая системная правка должна работать и со старыми версиями приложения. Пример: buttontask.service не задаёт WatchdogSec=, таймаут включает сам бинарник через WATCHDOG_USEC. Иначе старые версии без пингов убивались бы каждые 30 секунд.
3. Изменённый юнит не применяется к уже запущенному процессу
daemon-reload обновляет юнит, но переменные окружения (например, NOTIFY_SOCKET) процесс получает только при старте. Если юнит поменялся после перезапуска на шаге 6 (это случай из пункта 1), новые настройки заработают со следующего рестарта сервиса или перезагрузки.
4. Чего OTA не умеет
- apt/deb-пакеты. Для них нужен полный deploy-бандл (
winDeployScripts/,device-install.sh). - Произвольные одноразовые скрипты-миграции. Отдельного механизма нет: каждая правка вписывается в
bt-updateруками (см. ниже). - Перезагрузку после установки. Если она нужна, это ручной шаг.
Как добавить новую системную правку
- Положите файл в пакет, в
webconfig/…(всё изwebconfig/попадает в OTA черезmake-package.sh). - В
bt-updateвsync_systemдобавьтеinstall_if_changed <src> <dst>и нужныйreload/reexec/enable. Не добавляйте новый шаг прямо вcmd_stage: тогда правка не применится при первой OTA (пункт 1). - Проверьте, что правка совместима со старыми версиями приложения (пункт 2).
- Повторите то же в
winDeployScripts/device-install.shдля чистой установки. Если добавили новый хелперbt-*, впишите его в списки вdevice-install.shиmake-adb-bundle.ps1. - Новые типы файлов (
*.confи т.п.) пропишите в.gitattributesсeol=lf.
Безопасность
Пакет OTA фактически исполняется от root: хелперы, sudoers и юниты из него ставятся без подписи. От подмены защищают только пароль веб-конфигуратора и (необязательная) сверка sha256 при загрузке. Доступ к вкладке «Обновление» равен root-доступу к устройству.