Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в домашней папке, перенесены в agents/. Разложено по агентам там, где имя файла позволяло определить автора; остальное — в _salvage-2026-08-18/ и разбирается вручную. Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных рабочих копий: она существовала только на диске. Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
114 lines
13 KiB
Markdown
114 lines
13 KiB
Markdown
# Codex: единый установщик с выбором роли
|
||
|
||
## Порядок
|
||
|
||
Это задание выполняется **после** `smm-codex-task-alpha15-2026-08-15.md`. Пока не поставляется cosign, установка на чистый сервер невозможна, и переделывать интерфейс установщика поверх неработающей установки бессмысленно.
|
||
|
||
## Репозиторий
|
||
|
||
- https://github.com/ochenstarik-ui/server-monitor-manager
|
||
- База: `main` после слияния alpha.15
|
||
- Ветка: `codex/unified-installer`
|
||
|
||
## Правила репозитория
|
||
|
||
- `main` защищён: PR обязателен, обязательны статусы `build-and-test` и `build`, force-push запрещён;
|
||
- один PR — одна тема;
|
||
- описание PR заполняется **после** завершения CI, со ссылками на конкретные прогоны;
|
||
- `docs/release-policy.md` запрещает двигать опубликованные теги и заменять ассеты;
|
||
- `.github/workflows/linux-release.yml` — единственный публикатор релизов.
|
||
|
||
---
|
||
|
||
## Зачем
|
||
|
||
Живая установка на четырёх машинах показала, что оператор ошибается не в сложных местах, а в простых: путает роль, путает машину, оставляет плейсхолдер в аргументе, прерывает молчаливую загрузку. Владелец просит один файл, который спрашивает роль и делает остальное сам.
|
||
|
||
Второе изменение: код регистрации узла больше не выпускается на Hub через ssh. Его выдаёт приложение оператора — Windows-клиент или веб-консоль. Соответствующий эндпоинт делает Antigravity заданием `smm-antigravity-task-web-console-2026-08-17.md`. Установщику от этого нужно одно: принимать готовый код `SMMNODE2...`, как он делает и сейчас.
|
||
|
||
## Что сделать
|
||
|
||
Единый интерактивный режим `smm-setup.sh` без аргументов:
|
||
|
||
1. показать, что за машина: дистрибутив, версия, архитектура, публичный адрес, наличие уже установленных компонентов;
|
||
2. спросить роль — Hub или узел;
|
||
3. для Hub: спросить публичный адрес, предложив определённый автоматически как значение по умолчанию; порты предложить `7443` и `51820`;
|
||
4. для узла: попросить код `SMMNODE2...`, показать разобранный из кода адрес Hub и отпечаток CA, потребовать подтверждения;
|
||
5. проверить и доустановить зависимости, включая cosign;
|
||
6. скачать и проверить релизные файлы с видимым индикатором;
|
||
7. выполнить установку;
|
||
8. по завершении Hub напечатать **то, что нужно вставить в приложение оператора**: код регистрации устройства и отпечаток CA. Иначе получается замкнутый круг — приложение не может выдать код узла, пока само не подключено к Hub;
|
||
9. по завершении узла напечатать `SMMPEER1...` и прямо сказать, куда его вставить.
|
||
|
||
Требования к поведению:
|
||
|
||
- существующие неинтерактивные команды сохраняются полностью: они используются в `tests/acceptance/three-server-mesh.sh` и в проверке релиза. Интерактивный режим — это режим по умолчанию при запуске без аргументов, а не замена;
|
||
- при отсутствии терминала (запуск из скрипта, `stdin` не tty) интерактивный режим не включается, а выдаётся подсказка с неинтерактивными командами;
|
||
- ни один ввод не приводит к выполнению постороннего кода: код регистрации, адрес и порты проверяются до использования;
|
||
- повторный запуск на уже установленной машине распознаёт это и предлагает осмысленный выбор, а не падает и не ставит поверх.
|
||
|
||
## Состояние на 2026-08-18
|
||
|
||
**Установочная часть выполнена и слита** — PR #58, `main` @ `f7b10ac`: интерактивный режим без аргументов, выбор роли Hub/Node, показ состояния машины, доустановка зависимостей, разбор кода `SMMNODE2`, отказ без tty, тесты в `tests/bootstrap/test-unified-installer.sh`, обновлённая документация.
|
||
|
||
**Удаление не сделано.** В меню по-прежнему два пункта: `Choose role: 1) Hub 2) Node`, и `die "choose Hub (1) or Node (2)"` на всё остальное. Требование ниже появилось в задании 2026-08-18 и, судя по всему, до исполнителя не дошло. Оно остаётся в силе и выполняется **отдельным PR** поверх слитого.
|
||
|
||
Релиз с единым установщиком **не выпускать до готовности удаления**: смысл в том, чтобы владелец получил одну программу, умеющую и поставить, и снять. Выпуск половины означает второй релиз следом, а проект уже сжигал теги на такой спешке.
|
||
|
||
---
|
||
|
||
## Дополнение от владельца 2026-08-18 — полное удаление в том же файле
|
||
|
||
PR #58 закрывает установку, но не удаление. Владелец требует, чтобы единый файл умел и снимать систему целиком: третий пункт меню рядом с Hub и Node.
|
||
|
||
Сегодня `uninstall-agent` и `uninstall-control` снимают не всё. После них остаются системные пользователи и группы, конфигурация WireGuard и юнит `wg-quick@smm0`, таблица nftables `inet ochenstarik_smm`, каталоги состояния, запись в `sudoers.d`, файл в `sysctl.d`. Владелец проходил это вручную; точный список — в `smm-cleanup-and-install-2026-08-15.md`, раздел 1, проверен на живых серверах.
|
||
|
||
### Что сделать
|
||
|
||
Третий выбор роли: **удалить всё**. Поведение:
|
||
|
||
1. **Сначала показать, что будет удалено**, и только потом спрашивать подтверждение. Список строится по фактическому состоянию машины, а не печатается шаблоном: какие юниты найдены, какие пользователи существуют, есть ли таблица nftables, есть ли `smm0`, какие каталоги непусты.
|
||
2. **Подтверждение — набранным словом, не `y/N`.** Прецедент есть: `uninstall-control` требует `--confirm-destroy-control`. Случайное нажатие не должно сносить Hub вместе с его CA.
|
||
3. **Порядок: сначала остановить службы, потом удалять юниты.** Это не педантизм. Владелец однажды удалил юниты при работающем процессе, тот осиротел, продолжил держать порт 7443, и `userdel` отказал, потому что у пользователя оставался живой процесс. Правильно так: `systemctl disable --now`, затем `pkill -u` по каждому пользователю, пауза, `pkill -9 -u`, и только потом удаление файлов и учётных записей.
|
||
4. **Идемпотентность.** На машине, где ничего не стояло, режим отрабатывает молча и с нулевым кодом возврата.
|
||
5. **Ничего чужого.** На серверах владельца работает 3x-ui. Удаляются только объекты с собственными именами: юниты `ochenstarik-smm-*`, пользователи `ochenstarik-smm-control`, `ochenstarik-smm-agent`, `ochenstarik-monitor`, таблица `inet ochenstarik_smm`, интерфейс `smm0`, каталоги под своими путями. Никаких `rm -rf` по маскам, способным задеть соседа.
|
||
6. **Сохранение данных — отдельный вопрос.** Два варианта: снять программу, оставив резервные копии и базу Control, либо снести всё вместе с ними. Второй — с отдельным подтверждением: вместе с базой уходит CA, а с ним все выданные сертификаты и вся регистрация узлов.
|
||
7. **В конце — проверка**: напечатать те же четыре строки, которыми владелец проверяет чистоту вручную: свободны ли порты `7443` и `51820`, нет ли маршрутов `10.77.0.`, остались ли юниты, остались ли пользователи.
|
||
|
||
Сквозной неинтерактивный вариант тоже нужен — для скриптов и повторной приёмки: команда с обязательным флагом подтверждения, без вопросов.
|
||
|
||
### Тесты удаления
|
||
|
||
- на машине без установленной системы режим отрабатывает без ошибок и ничего не меняет;
|
||
- после полной установки и последующего удаления не остаётся ни юнитов, ни пользователей, ни таблицы nftables, ни интерфейса, ни каталогов состояния;
|
||
- посторонний юнит и посторонний пользователь, созданные до удаления, остаются нетронутыми;
|
||
- без флага подтверждения неинтерактивный вариант отказывается работать;
|
||
- удаление при работающих службах не оставляет процессов, удерживающих порты.
|
||
|
||
## Что проверить тестами
|
||
|
||
- интерактивный сценарий Hub и узла целиком, на подставном вводе;
|
||
- отказ интерактивного режима без tty;
|
||
- отклонение испорченного кода `SMMNODE2` — обрезанного, с лишним сегментом, с подменённым отпечатком;
|
||
- сохранность неинтерактивных команд: существующие тесты `tests/bootstrap/**` и проверка релиза продолжают проходить без изменений в вызовах.
|
||
|
||
## Границы
|
||
|
||
Antigravity ведёт Control и веб-консоль. **Не трогать:** `src/**`, `.github/workflows/windows-build.yml`.
|
||
|
||
Ваша область: `deploy/**`, `tests/bootstrap/**`, `docs/linux-bootstrap.md`.
|
||
|
||
Формат `SMMNODE2` и `SMMPEER1` не менять: его разбирает установленный на серверах bootstrap, а опубликованные релизы неизменяемы.
|
||
|
||
## Критерий приёмки
|
||
|
||
- `smm-setup.sh` без аргументов проводит установку Hub и узла целиком, включая cosign и зависимости;
|
||
- Hub по завершении печатает то, что вставляется в приложение оператора;
|
||
- неинтерактивные команды не изменены, приёмочный скрипт и проверка релиза проходят;
|
||
- без tty интерактивный режим не запускается;
|
||
- испорченный код отвергается;
|
||
- всё через PR, CI зелёный, PR не смержен до зелёного.
|
||
|
||
## Отчёт
|
||
|
||
Раздельно: что проверено локально, что в CI со ссылками на прогоны, что не проверялось и почему.
|