mistgate Документация

Обновления

Как агенты нод обновляют себя из подписанных вами пакетов, как раскатка проверяет и откатывает ноды и как вручную обновить саму панель.

На этой странице

Агенты нод обновляют себя сами, но только до сборки, подписанной вашим ключом релиза. Панель доставляет подписанный пакет на ноды, а каждый агент перед заменой себя проверяет подпись ключом, вшитым в его собственный бинарник. Саму панель обновляют вручную (самообновление панели в планах).

Как устроено доверие#

  • Есть одна пара ключей ed25519 — ключ релиза. Закрытая половина остаётся у вас, офлайн. Открытая вшивается в оба бинарника при сборке (RELEASE_KEY).
  • На каждый релиз вы подписываете манифест: версию, время сборки, срок действия и для каждого бинарника — имя, ОС, архитектуру, размер и SHA-256.
  • Агент проверяет по порядку: подпись — вшитым ключом, формат манифеста, срок действия, что релиз новее его самого и что в пакете есть файл под его ОС и архитектуру. Затем скачивает файл с панели по своему соединению с взаимным TLS и сверяет размер и SHA-256. При любой ошибке установленный бинарник не трогается.
  • Панель — только курьер: взломанная панель не заставит ноду запустить код, который вы не подписывали.
  • Релизы упорядочены по времени сборки (Unix-время коммита исходников), а не по строке версии. Релиз с тем же временем сборки, что у ноды, считается «уже актуальным»; более старый отклоняется как откат версии.
  • Бинарник, собранный без RELEASE_KEY, никогда не обновляется сам. mistgate version и mistgate-node version печатают отпечаток ключа, которому доверяет бинарник, или пишут, что ключа нет.

Выпуск релиза#

1. Сделайте ключ релиза (один раз)#

sh
mistgate release keygen --out ~/mistgate-release.key

Команда пишет закрытый ключ в файл (режим 0600; существующий файл никогда не перезаписывается) и печатает открытый ключ и его отпечаток (первые 16 шестнадцатеричных символов его SHA-256).

Внимание

храните файл ключа офлайн и сделайте резервную копию. Без него ни одну ноду нельзя обновить из панели: придётся сделать новый ключ, собрать с ним новые бинарники и один раз обновить вручную каждую ноду и панель.

2. Соберите с открытым ключом#

sh
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. Подпишите бинарники нод#

sh
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. Положите пакет на панель#

sh
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. Следующая пачка начинается, только когда по всем нодам предыдущих есть итог.
  • Одновременно идёт одна раскатка.
  • Раскатка везёт пакет в том виде, в каком он был при запуске. Нода, которая к своей очереди не на связи, не умеет обновляться или уже актуальна, пропускается.

Обновление одной ноды#

  1. Панель отправляет подписанный манифест. Агент проверяет его, скачивает свой файл, сохраняет текущий бинарник как <бинарник>.prev, ставит новый на его место и перезапускает себя на месте (systemd ничего не замечает). Нода пропадает на несколько секунд; админка показывает это как обновление, а не как сбой.
  2. Панель ждёт ответа агента до 10 минут (вместе со скачиванием), затем до 3 минут — возвращения ноды с новой сборкой.
  3. Проверка после обновления идёт до 5 минут после возвращения ноды. Она пройдена, когда выполнено всё сразу:
    • новая сборка закрепилась: подключилась и применила конфигурацию без упавшего профиля;
    • нода применила ту же конфигурацию, что у панели;
    • не упал ни один профиль, который работал до обновления (профиль, который не работает 30 секунд, сразу проваливает проверку);
    • каждый профиль, который панель умеет проверять, прошёл проверку глазами клиента после возвращения ноды (панель сразу запускает круг).
  4. Если проверка пройдена, шаг завершён. Если нет, панель отправляет ноде откат (возвращается прежний бинарник), шаг заканчивается как «откачена», раскатка встаёт на паузу.

Собственная страховка агента#

Агент не полагается на панель, чтобы отменить плохое обновление:

  • Новая сборка, которая за 5 минут после запуска не подключилась и не применила конфигурацию, возвращает прежний бинарник и перезапускается (not_committed).
  • Новая сборка, у которой собственное время сборки отличается от манифеста, откатывается сразу (built_mismatch).
  • Служебный файл считает запуски, пока обновление не закреплено; на третьем запуске подряд он возвращает прежний бинарник ещё до старта агента (crash_loop).
  • Прежняя сборка сообщает итог, когда снова подключается.

Пауза, продолжение, отмена#

  • Пауза: новые шаги не начинаются. Шаг, который уже идёт, доходит до конца и проходит свою проверку. Уже обновлённые ноды остаются обновлёнными.
  • Продолжить: оставшиеся ждущие шаги идут дальше. Неудачные и откаченные шаги остаются как есть; обновите эти ноды новой раскаткой, когда устраните причину. Если пакет на диске сменился, продолжить нельзя: отмените раскатку и начните заново.
  • Отменить раскатку: ждущие ноды пропускаются; нода, которую обновляют сейчас, заканчивает и проходит проверку; обновлённые ноды остаются на новой версии.

Раскатка встаёт на паузу и сама:

Причина паузы Что случилось
нода не приняла обновление Она отклонила обновление (причина показана).
нода не прошла проверку после обновления Она провалила проверку или не вернулась; где получилось, ей вернули прежнюю версию.
пакет релиза сменился В <data-dir>/dist теперь другой релиз. Отмените раскатку и начните заново.
панель перезапустилась во время шага Панель не знает, чем закончился шаг. Проверьте ноду, затем продолжите или отмените.

Первая, вторая и четвёртая причины ещё и открывают алерт «Обновление ноды остановилось» — до тех пор, пока раскатку не продолжат, не отменят или не запустят новую.

Законченная раскатка получает статус Готово, Отменена или Закончилась с проблемами (хотя бы одна нода не обновилась или откатилась). Страница показывает идущую раскатку или последнюю. Законченные раскатки хранятся: последние 20 — всегда, более старые — 90 дней.

Частые ошибки шагов:

Ошибка Значение
Нода отвергла подпись Агент ноды доверяет другому ключу релиза.
Агент этой ноды собран без ключа релиза Обновите его вручную.
Релиз старее того, что уже работает на ноде Подпишите более новую сборку.
В пакете нет файла для системы и архитектуры этой ноды Добавьте бинарник под её архитектуру (например, arm64).
Нода не смогла скачать файл с панели Проверьте связь ноды с панелью.
Нода не может писать рядом со своей программой Проверьте диск ноды; один запуск mistgate-node install запишет актуальный служебный файл.
Нода не ответила на команду обновления за 10 минут Посмотрите на ноду.
Нода не вернулась за 3 минуты Посмотрите на ноду и её логи.
Проверка глазами клиента после обновления не прошла См. «Здоровье»; нода уже на прежней версии.

Откат вручную#

Откатить в строке ноды возвращает прежний бинарник ноды (<бинарник>.prev) и перезапускает агента. Работает и вне раскатки. У ноды, которую ни разу не обновляли, прежней версии нет, и она откажет. Если нода участвует в идущей раскатке, её шаг помечается как «откачена», и раскатка встаёт на паузу.

Столбец Последнее обновление показывает, кто откатил ноду: «Откачено тобой», «Панель вернула прошлую версию: …» (проверка после обновления) или «Прошлую версию вернули командой панели».

Старые агенты: один раз вручную#

Нода показывает Обновить вручную, когда её агент не умеет обновляться сам: он появился раньше самообновления, собран без ключа релиза или работает под первой версией служебного файла (где каталог программы только для чтения). Как обновить в её строке даёт две команды, например:

sh
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 из того же релиза, что и панель.

Старые агенты продолжают работать с более новой панелью: изменения протокола агента только добавляют новое. Если старому агенту чего-то не хватает, там, где это нужно, админка пишет «агент слишком старый».

Обновление панели#

Сама себя панель пока не обновляет. Обновите её вручную:

  1. Соберите новую версию с тем же RELEASE_KEY (см. выше). Панель без него больше не сможет проверять пакеты и запускать раскатки.
  2. Не обновляйте панель во время раскатки: поставьте её на паузу или дождитесь конца. Перезапуск посреди шага ставит раскатку на паузу («панель перезапустилась во время шага»).
  3. Скопируйте новый бинарник рядом с установленным, затем остановите панель, сделайте копию каталога данных, замените бинарник и запустите панель снова. Здесь бинарник — /usr/local/bin/mistgate, а unit systemd — mistgate.service, как в «Установке панели»; подставьте свои имена:
sh
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
  1. База данных мигрирует при запуске панели, больше ничего не нужно. Новую версию покажут строка журнала mistgate starting, карточка Эта панель на странице «Обновления» и mistgate version.

Что происходит вокруг перезапуска:

  • Агенты нод переподключаются сами (повторяют попытки с растущей паузой от 1 до 60 секунд). Пока панели нет, их профили продолжают работать.
  • Первые 90 секунд после запуска панель не открывает алерт «Нода недоступна».
  • Сессии админки переживают перезапуск.
Внимание

миграции идут только вперёд. Старый бинарник панели не обязан работать с базой, которую уже обновил новый. Чтобы вернуться, остановите панель, восстановите каталог данных из копии, сделанной перед обновлением, верните старый бинарник и запустите. Всё, что изменилось после копии, будет потеряно.

Обновления через API и MCP#

Любой профиль API-токена может читать страницу обновлений (GetUpdates). Запуск, пауза, продолжение и отмена раскатки и откат ноды через обычный API запрещены; MCP-агент с профилем admin может их только запланировать, а каждый план одобряет владелец в админке. См. API и MCP.

Править страницу на GitHub