Обновления
Как агенты нод обновляют себя из подписанных вами пакетов, как раскатка проверяет и откатывает ноды и как вручную обновить саму панель.
На этой странице
- Как устроено доверие
- Выпуск релиза
- 1. Сделайте ключ релиза (один раз)
- 2. Соберите с открытым ключом
- 3. Подпишите бинарники нод
- 4. Положите пакет на панель
- Страница «Обновления»
- Раскатка
- Запуск
- Обновление одной ноды
- Собственная страховка агента
- Пауза, продолжение, отмена
- Откат вручную
- Старые агенты: один раз вручную
- Обновление панели
- Обновления через API и MCP
Агенты нод обновляют себя сами, но только до сборки, подписанной вашим ключом релиза. Панель доставляет подписанный пакет на ноды, а каждый агент перед заменой себя проверяет подпись ключом, вшитым в его собственный бинарник. Саму панель обновляют вручную (самообновление панели в планах).
Как устроено доверие#
- Есть одна пара ключей ed25519 — ключ релиза. Закрытая половина остаётся у вас, офлайн. Открытая вшивается в оба бинарника при сборке (
RELEASE_KEY). - На каждый релиз вы подписываете манифест: версию, время сборки, срок действия и для каждого бинарника — имя, ОС, архитектуру, размер и SHA-256.
- Агент проверяет по порядку: подпись — вшитым ключом, формат манифеста, срок действия, что релиз новее его самого и что в пакете есть файл под его ОС и архитектуру. Затем скачивает файл с панели по своему соединению с взаимным TLS и сверяет размер и SHA-256. При любой ошибке установленный бинарник не трогается.
- Панель — только курьер: взломанная панель не заставит ноду запустить код, который вы не подписывали.
- Релизы упорядочены по времени сборки (Unix-время коммита исходников), а не по строке версии. Релиз с тем же временем сборки, что у ноды, считается «уже актуальным»; более старый отклоняется как откат версии.
- Бинарник, собранный без
RELEASE_KEY, никогда не обновляется сам.mistgate versionиmistgate-node versionпечатают отпечаток ключа, которому доверяет бинарник, или пишут, что ключа нет.
Выпуск релиза#
1. Сделайте ключ релиза (один раз)#
mistgate release keygen --out ~/mistgate-release.keyКоманда пишет закрытый ключ в файл (режим 0600; существующий файл никогда не перезаписывается) и печатает открытый ключ и его отпечаток (первые 16 шестнадцатеричных символов его SHA-256).
храните файл ключа офлайн и сделайте резервную копию. Без него ни одну ноду нельзя обновить из панели: придётся сделать новый ключ, собрать с ним новые бинарники и один раз обновить вручную каждую ноду и панель.
2. Соберите с открытым ключом#
RELEASE_KEY=<открытый ключ> make buildСобираются bin/mistgate-linux-{amd64,arm64} и bin/mistgate-node-linux-{amd64,arm64}, и в оба вшиваются ключ релиза, версия (git describe --tags --always --dirty) и время сборки (git log -1 --format=%ct). Панель тоже собирайте с ключом: без него она не может проверить пакет и не запустит раскатку.
3. Подпишите бинарники нод#
mistgate release sign --key ~/mistgate-release.key \
--version "$(git describe --tags --always)" \
--built "$(git log -1 --format=%ct)" --expires 30d \
bin/mistgate-node-linux-amd64 bin/mistgate-node-linux-arm64 --out dist/- Бинарники должны называться
<имя>-<ос>-<архитектура>, как их называетmake build. --builtдолжно совпадать со временем сборки, вшитым в бинарники: собирайте и подписывайте из одного коммита. Новая сборка, у которой собственное время сборки отличается от манифеста, после обновления откатывает себя сама (built_mismatch).--expires— число дней (30d) или длительность в формате Go (720h); по умолчанию30d. После этого панель и ноды отклоняют манифест, так что перехваченный старый манифест долго не проживёт.- Команда пишет
dist/manifest.jsonиdist/manifest.sig, кладёт рядом копии бинарников, перечитывает результат и проверяет его, затем печатает версию, срок действия, каждый файл с размером и отпечаток ключа.
4. Положите пакет на панель#
scp dist/* panel.example.com:/var/lib/mistgate/dist/Панель читает <data-dir>/dist и замечает изменения в течение минуты; Перечитать папку на странице «Обновления» читает её сразу. Учитываются только обычные файлы (символьные ссылки не открываются). Меняйте пакет целиком; замена пакета во время раскатки ставит раскатку на паузу.
Карточка Пакет релиза показывает результат:
| Статус | Значение |
|---|---|
| Подпись проверена | Подпись сходится с ключом релиза этой панели, манифест в порядке, все файлы на месте с нужным размером и контрольной суммой. Раскатывать можно только такой пакет. |
| Не прошёл проверку | Что-то не так; карточка пишет что (см. ниже). |
| Не проверен | Панель собрана без ключа релиза и оценить пакет не может. Ноды всё равно проверяют его сами. |
| Нет пакета | В <data-dir>/dist нет manifest.json. |
| Причина | Что делать |
|---|---|
| В каталоге данных панели нет пакета релиза | Скопируйте пакет в <data-dir>/dist. |
| Нет файла подписи (manifest.sig) | Скопируйте и manifest.sig. |
| manifest.json — не манифест релиза | Подпишите заново; не правьте манифест. |
| Манифест в более новом формате, чем понимает эта панель | Сначала обновите панель. |
| Подпись не сходится с ключом релиза этой панели | Пакет подписан другим ключом или панель собрана с другим ключом. |
| Срок манифеста истёк: подпиши новый | Подпишите заново с более поздним --expires. |
| Файла из манифеста нет | Скопируйте все файлы пакета. |
| Файл не совпадает с манифестом (размер или контрольная сумма) | Копия неполная или файл изменён: скопируйте его снова. |
Файлы пакета панель отдаёт только агентам с действующим сертификатом ноды, через точку подключения агентов, не больше четырёх загрузок одновременно, кусками, с докачкой.
Страница «Обновления»#
Смотреть страницу могут все. Запуск, пауза, продолжение и отмена раскатки, откат ноды и Перечитать папку доступны только владельцу и требуют свежего повторного подтверждения входа (см. «Безопасность»).
- Эта панель: версия, дата сборки и отпечаток ключа релиза (или «нет: эта сборка не проверяет пакеты»), с шагами обновления самой панели.
- Пакет релиза: пакет в
<data-dir>/dist. - Ноды: каждая нода с версией агента и датой сборки, состоянием и последним обновлением. Владельцу в строке доступны Обновить и Откатить.
| Состояние ноды | Значение |
|---|---|
| Актуальна | Её сборка не старее сборки проверенного пакета (без проверенного пакета — сборки самой панели). |
| Есть обновление | Она умеет обновляться сама и работает на более старой сборке. |
| Обновляется… | Идёт шаг раскатки этой ноды. |
| Откатилась | Последнее обновление закончилось откатом; работает прежняя сборка. |
| Обновление не удалось | Последнее обновление не удалось на ноде. |
| Обновить вручную | Её агент не умеет обновляться сам (см. «Старые агенты» ниже). |
| Не в сети | Нода не на связи; показана последняя известная сборка. |
«Нет защиты от повторных падений» под нодой значит, что в её служебном файле нет защиты от цикла падений: обновление там страхует только самооткат агента через 5 минут. Один раз запустите на ней mistgate-node install с новым бинарником, чтобы добавить защиту.
Раскатка#
Запуск#
Обновить все (сначала канарейка) обновляет все ноды в состоянии «Есть обновление»; Обновить в строке ноды обновляет одну ноду. Диалог говорит, какая нода пойдёт первой и какого размера будут пачки.
- Канарейка. Первой идёт нода, где меньше всего людей онлайн, затем — меньше всего профилей, затем по имени. Её обновляют одну.
- Пачки. После канарейки остальные идут пачками: по одной ноде, пока обновить нужно меньше 5 нод, иначе по 2. Следующая пачка начинается, только когда по всем нодам предыдущих есть итог.
- Одновременно идёт одна раскатка.
- Раскатка везёт пакет в том виде, в каком он был при запуске. Нода, которая к своей очереди не на связи, не умеет обновляться или уже актуальна, пропускается.
Обновление одной ноды#
- Панель отправляет подписанный манифест. Агент проверяет его, скачивает свой файл, сохраняет текущий бинарник как
<бинарник>.prev, ставит новый на его место и перезапускает себя на месте (systemd ничего не замечает). Нода пропадает на несколько секунд; админка показывает это как обновление, а не как сбой. - Панель ждёт ответа агента до 10 минут (вместе со скачиванием), затем до 3 минут — возвращения ноды с новой сборкой.
- Проверка после обновления идёт до 5 минут после возвращения ноды. Она пройдена, когда выполнено всё сразу:
- новая сборка закрепилась: подключилась и применила конфигурацию без упавшего профиля;
- нода применила ту же конфигурацию, что у панели;
- не упал ни один профиль, который работал до обновления (профиль, который не работает 30 секунд, сразу проваливает проверку);
- каждый профиль, который панель умеет проверять, прошёл проверку глазами клиента после возвращения ноды (панель сразу запускает круг).
- Если проверка пройдена, шаг завершён. Если нет, панель отправляет ноде откат (возвращается прежний бинарник), шаг заканчивается как «откачена», раскатка встаёт на паузу.
Собственная страховка агента#
Агент не полагается на панель, чтобы отменить плохое обновление:
- Новая сборка, которая за 5 минут после запуска не подключилась и не применила конфигурацию, возвращает прежний бинарник и перезапускается (
not_committed). - Новая сборка, у которой собственное время сборки отличается от манифеста, откатывается сразу (
built_mismatch). - Служебный файл считает запуски, пока обновление не закреплено; на третьем запуске подряд он возвращает прежний бинарник ещё до старта агента (
crash_loop). - Прежняя сборка сообщает итог, когда снова подключается.
Пауза, продолжение, отмена#
- Пауза: новые шаги не начинаются. Шаг, который уже идёт, доходит до конца и проходит свою проверку. Уже обновлённые ноды остаются обновлёнными.
- Продолжить: оставшиеся ждущие шаги идут дальше. Неудачные и откаченные шаги остаются как есть; обновите эти ноды новой раскаткой, когда устраните причину. Если пакет на диске сменился, продолжить нельзя: отмените раскатку и начните заново.
- Отменить раскатку: ждущие ноды пропускаются; нода, которую обновляют сейчас, заканчивает и проходит проверку; обновлённые ноды остаются на новой версии.
Раскатка встаёт на паузу и сама:
| Причина паузы | Что случилось |
|---|---|
| нода не приняла обновление | Она отклонила обновление (причина показана). |
| нода не прошла проверку после обновления | Она провалила проверку или не вернулась; где получилось, ей вернули прежнюю версию. |
| пакет релиза сменился | В <data-dir>/dist теперь другой релиз. Отмените раскатку и начните заново. |
| панель перезапустилась во время шага | Панель не знает, чем закончился шаг. Проверьте ноду, затем продолжите или отмените. |
Первая, вторая и четвёртая причины ещё и открывают алерт «Обновление ноды остановилось» — до тех пор, пока раскатку не продолжат, не отменят или не запустят новую.
Законченная раскатка получает статус Готово, Отменена или Закончилась с проблемами (хотя бы одна нода не обновилась или откатилась). Страница показывает идущую раскатку или последнюю. Законченные раскатки хранятся: последние 20 — всегда, более старые — 90 дней.
Частые ошибки шагов:
| Ошибка | Значение |
|---|---|
| Нода отвергла подпись | Агент ноды доверяет другому ключу релиза. |
| Агент этой ноды собран без ключа релиза | Обновите его вручную. |
| Релиз старее того, что уже работает на ноде | Подпишите более новую сборку. |
| В пакете нет файла для системы и архитектуры этой ноды | Добавьте бинарник под её архитектуру (например, arm64). |
| Нода не смогла скачать файл с панели | Проверьте связь ноды с панелью. |
| Нода не может писать рядом со своей программой | Проверьте диск ноды; один запуск mistgate-node install запишет актуальный служебный файл. |
| Нода не ответила на команду обновления за 10 минут | Посмотрите на ноду. |
| Нода не вернулась за 3 минуты | Посмотрите на ноду и её логи. |
| Проверка глазами клиента после обновления не прошла | См. «Здоровье»; нода уже на прежней версии. |
Откат вручную#
Откатить в строке ноды возвращает прежний бинарник ноды (<бинарник>.prev) и перезапускает агента. Работает и вне раскатки. У ноды, которую ни разу не обновляли, прежней версии нет, и она откажет. Если нода участвует в идущей раскатке, её шаг помечается как «откачена», и раскатка встаёт на паузу.
Столбец Последнее обновление показывает, кто откатил ноду: «Откачено тобой», «Панель вернула прошлую версию: …» (проверка после обновления) или «Прошлую версию вернули командой панели».
Старые агенты: один раз вручную#
Нода показывает Обновить вручную, когда её агент не умеет обновляться сам: он появился раньше самообновления, собран без ключа релиза или работает под первой версией служебного файла (где каталог программы только для чтения). Как обновить в её строке даёт две команды, например:
scp /var/lib/mistgate/dist/mistgate-node-linux-amd64 root@de1.example.com:/root/mistgate-node
ssh root@de1.example.com 'chmod +x /root/mistgate-node && /root/mistgate-node install'install копирует бинарник в /usr/local/bin/mistgate-node, пишет актуальный защищённый служебный файл (с защитой от цикла падений) и перезапускает агента. После этого нода обновляется со страницы «Обновления». Если пакета на панели нет, возьмите mistgate-node из того же релиза, что и панель.
Старые агенты продолжают работать с более новой панелью: изменения протокола агента только добавляют новое. Если старому агенту чего-то не хватает, там, где это нужно, админка пишет «агент слишком старый».
Обновление панели#
Сама себя панель пока не обновляет. Обновите её вручную:
- Соберите новую версию с тем же
RELEASE_KEY(см. выше). Панель без него больше не сможет проверять пакеты и запускать раскатки. - Не обновляйте панель во время раскатки: поставьте её на паузу или дождитесь конца. Перезапуск посреди шага ставит раскатку на паузу («панель перезапустилась во время шага»).
- Скопируйте новый бинарник рядом с установленным, затем остановите панель, сделайте копию каталога данных, замените бинарник и запустите панель снова. Здесь бинарник —
/usr/local/bin/mistgate, а unit systemd —mistgate.service, как в «Установке панели»; подставьте свои имена:
scp bin/mistgate-linux-amd64 panel.example.com:/usr/local/bin/mistgate.new
# на сервере панели, от root
systemctl stop mistgate
tar czf /root/mistgate-backup-$(date +%F).tgz -C /var/lib mistgate
mv /usr/local/bin/mistgate.new /usr/local/bin/mistgate
systemctl start mistgate
journalctl -u mistgate -n 50- База данных мигрирует при запуске панели, больше ничего не нужно. Новую версию покажут строка журнала
mistgate starting, карточка Эта панель на странице «Обновления» иmistgate version.
Что происходит вокруг перезапуска:
- Агенты нод переподключаются сами (повторяют попытки с растущей паузой от 1 до 60 секунд). Пока панели нет, их профили продолжают работать.
- Первые 90 секунд после запуска панель не открывает алерт «Нода недоступна».
- Сессии админки переживают перезапуск.
миграции идут только вперёд. Старый бинарник панели не обязан работать с базой, которую уже обновил новый. Чтобы вернуться, остановите панель, восстановите каталог данных из копии, сделанной перед обновлением, верните старый бинарник и запустите. Всё, что изменилось после копии, будет потеряно.
Обновления через API и MCP#
Любой профиль API-токена может читать страницу обновлений (GetUpdates). Запуск, пауза, продолжение и отмена раскатки и откат ноды через обычный API запрещены; MCP-агент с профилем admin может их только запланировать, а каждый план одобряет владелец в админке. См. API и MCP.