Files
Button/docs/ota.md
T
GrigoandClaude Opus 5.5 56d635f051 docs: what OTA changes in the system (docs/ota.md)
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>
2026-11-10 10:58:05 +00:00

7.0 KiB
Raw Blame History

OTA: что обновление может менять в системе

Изначально OTA задумывалась как замена только приложения (бинарник, веб, коллектор). На практике bt-update выполняется от root и уже меняет системные файлы: хелперы, sudoers, юниты systemd, конфиги systemd. Здесь описано, что именно он делает, в каком порядке и как добавить новую системную правку.

Как запускается

  1. Веб (пользователь buttontask) принимает пакет и вызывает sudo -n /opt/buttontask/scripts/bt-update stage <pkg>. Это разрешено правилом в /etc/sudoers.d/buttontask.
  2. bt-update перезапускает сам себя через systemd-run в отдельном временном юните buttontask-update-<ts>. Поэтому он переживает перезапуск buttontask-web посреди обновления.
  3. Прогресс пишется в 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 руками (см. ниже).
  • Перезагрузку после установки. Если она нужна, это ручной шаг.

Как добавить новую системную правку

  1. Положите файл в пакет, в webconfig/… (всё из webconfig/ попадает в OTA через make-package.sh).
  2. В bt-update в sync_system добавьте install_if_changed <src> <dst> и нужный reload/reexec/enable. Не добавляйте новый шаг прямо в cmd_stage: тогда правка не применится при первой OTA (пункт 1).
  3. Проверьте, что правка совместима со старыми версиями приложения (пункт 2).
  4. Повторите то же в winDeployScripts/device-install.sh для чистой установки. Если добавили новый хелпер bt-*, впишите его в списки в device-install.sh и make-adb-bundle.ps1.
  5. Новые типы файлов (*.conf и т.п.) пропишите в .gitattributes с eol=lf.

Безопасность

Пакет OTA фактически исполняется от root: хелперы, sudoers и юниты из него ставятся без подписи. От подмены защищают только пароль веб-конфигуратора и (необязательная) сверка sha256 при загрузке. Доступ к вкладке «Обновление» равен root-доступу к устройству.