# Управление сервером из веб-интерфейса В меню админки доступны **Обновления** (`/admin/updates`) и **Конфигурация** (`/admin/config`). Клиентские APK и desktop-сборки по-прежнему раздаются через существующий механизм `appupdate`; источники обновления сервера от него независимы. ## Установка на существующий сервер Обычное обновление на Linux-хосте автоматически настраивает агент после переключения на выбранную версию и до пересоздания контейнеров: ```bash cd /opt/pipu-music/deploy ./update.sh main # либо тег версии, содержащей эту возможность ``` Если прав не хватает, установщик запросит sudo только для настройки системного сервиса. Повторный запуск проверяет установку и запускает остановленный агент; исправный агент с тем же кодом и unit-файлом не перезапускается. Ошибка установки останавливает обновление до пересоздания контейнеров. При обновлении из админки собственный агент остаётся запущенным и заменяет свою копию после успеха. В версии **v1.9.0** вызов установщика из `update.sh` был пропущен. Если сервер уже обновлён до неё, агент можно включить сразу без новой сборки: ```bash cd /opt/pipu-music/deploy && sudo bash ./install-management.sh ``` Чтобы получить исправленный updater на checkout ветки main, один раз выполните `git pull --ff-only` перед `./update.sh main`: старая временная копия updater, запущенная до checkout, ещё не содержит нового шага настройки. Новая установка через `sudo ./install.sh` также устанавливает агент автоматически. Нужны systemd, Python **3.10+**, Git, Bash, `flock` (util-linux) и Docker Compose **2.24+**. Compose должен поддерживать несколько `--env-file` и тег `!reset` из существующего TLS-overlay. Агент выполняется от root, чтобы запускать Compose и обращаться к данным развёртывания; API продолжает работать без root и без Docker socket. Скрипт создаёт `pipu-management.service`, копирует агент вне Git-checkout в `/usr/local/lib/pipu/server-agent.py`, создаёт `deploy/config.local` и общий каталог `${PIPU_DATA}/management` с владельцем UID 65532. Последний монтируется только в API. Приватные настройки источников, состояние, аудит и журналы лежат в `/var/lib/pipu-management`, доступном только root. Нужен доступ этого пользователя к origin; SSH-ключи и known_hosts для приватных репозиториев настройте на хосте. Пароли и токены в URL источников не принимаются. После успешного обновления агент автоматически заменяет свою установленную копию из нового checkout и перезапускается, сохранив итоговый статус. Для ручной установки нового кода можно повторно запустить `install-management.sh`. Во время выполняющейся операции не перезапускайте его: systemd остановит дочерние процессы. После прерывания/перезагрузки задача помечается ошибкой, а не успехом. ## Права Администратор всегда может управлять обновлениями. В меню действий пользователя на странице **Пользователи** он может выдать и забрать право **Управление обновлениями** (`manages_updates`). Право действует независимо от роли и проверяется на сервере при каждом запросе. Оно позволяет изменять источники, видеть журнал и запускать обновление. Пользователь с этим правом получает ссылку на обновления, но не получает доступ к пользователям, конфигурации или остальным действиям админа. Выдавайте это право доверенным операторам: обновление запускает код выбранного совместимого репозитория на хосте. Только администраторы могут просматривать, сохранять и применять конфигурацию. Выдача/отзыв права записываются в `audit_log`; операции агента с UUID инициатора — в его приватный `audit.jsonl` без значений секретов. ## Обновления При первом обращении автоматически добавляется текущий `git remote origin`. Можно создавать, редактировать и удалять источники; хотя бы один должен остаться. Поддерживаются совместимые Git-репозитории Pipu через HTTP(S) и SSH. * **Последний релиз** — значение по умолчанию: максимальный стабильный тег SemVer `vMAJOR.MINOR.PATCH` (также допускается без `v`), без `-rc.N`. * **Выбрать версию** — конкретный релизный тег, включая release candidate. * **main** — текущий commit ветки main. Обновления устанавливаются только по нажатию кнопки и после подтверждения. Перед запуском агент повторно читает refs и фиксирует SHA; update.sh проверяет, что полученный commit совпадает. Выбранный источник не перезаписывает origin и не смешивает его теги с тегами другого репозитория. Git checkout с локальными изменениями отклоняется. Защита update.sh от downgrade сохраняется: откат выполняется вручную с `PIPU_ALLOW_DOWNGRADE=1` после проверки совместимости БД. Выполнение, ограниченный хвост журнала и итоговый статус доступны на странице. Можно закрыть браузер или переждать перезапуск API: работа продолжается на хосте. Полные логи остаются приватными; для интерфейса известные секреты маскируются. Одновременно агент допускает только одну операцию обновления/применения. Резервная копия и откат схемы БД автоматически не выполняются. ## Конфигурация Реестр поддерживаемых параметров находится в `deploy/config.schema.json`: API, общие параметры сервисов, рекомендатель и развёртывание. Добавляя параметр в конфигурацию сервиса, обновите реестр; для рекомендателя/агента хранилища также проверьте передачу через Compose. Пути томов, сгенерированный DATABASE_URL и некоторые служебные параметры показаны для просмотра и меняются на хосте. Страница не является произвольным редактором nginx/Caddy/YAML-файлов. Приоритет при запуске через скрипты: 1. Явные переменные окружения Compose и значения из `deploy/.env`. 2. `deploy/config.local`. 3. Встроенные значения по умолчанию. Для интерполяции Compose скрипты передают `--env-file config.local --env-file .env`. У API порядок `env_file: [config.local, .env]`; рекомендатель и storage-agent получают только необходимые им переменные через `environment`. При ручном запуске Compose сохраняйте эти флаги, иначе параметры интерполяции из config.local не подхватятся. Страница показывает ожидаемое значение после применения, а не утверждает, что работающий процесс уже перечитал сохранённый файл. Окружение shell запуска Compose тоже может перекрывать интерполяцию; для агента используется окружение systemd. В интерфейсе видны локальное значение, значение из `.env` и источник приоритета. Если ключ уже есть в `.env`, изменение его в config.local сохраняется, но не перекрывает `.env` — интерфейс прямо сообщает об этом. Чтобы управлять таким ключом через страницу, удалите его строку из `.env` на хосте. Секреты не возвращаются в API открытым текстом: поле без изменений сохраняет прежний секрет, ввод заменяет, **Сбросить локальное** удаляет только значение из config.local. Сохранение атомарно, с правами 0600 и проверкой ревизии: устаревшая форма не затрёт правки другого администратора. Перед сохранением проверяются типы и Compose; при ошибке прежний файл восстанавливается. Произвольные ключи, переводы строк и изменение служебных параметров отклоняются. Сохраняемые значения трактуются буквально: подстановки shell не выполняются. Кнопка **Применить и перезапустить** отдельно подтверждает пересоздание контейнеров. Агент запускает `apply-config.sh`, ждёт `/readyz` и сохраняет результат. Если сервисы не стали готовы, состояние — ошибка; исправьте config.local или восстановите его на хосте. Автоматического отката конфигурации после неудачного применения нет. Диагностика: ```bash sudo systemctl status pipu-management.service sudo journalctl -u pipu-management.service -n 100 cd /opt/pipu-music/deploy docker compose --env-file config.local --env-file .env logs api ``` Проверки разработки: `python3 -m unittest discover -s deploy -p 'test_*.py'`, `go test ./internal/auth ./internal/management` из `services/api`, а также `pnpm --filter @pipu/web test:e2e e2e/server-management.spec.ts`.