Files
pipu-music/docs/server-management.md
T
mrleo1nid 24707a0bfc
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 2m15s
ci / ts / ts (packages + web) (push) Successful in 2m19s
fix(admin): mask all stored configuration secrets and credential URLs
2026-10-23 00:27:20 +03:00

15 KiB
Raw Blame History

Управление сервером из веб-интерфейса

В меню админки доступны Обновления (/admin/updates) и Конфигурация (/admin/config). Клиентские APK и desktop-сборки по-прежнему раздаются через существующий механизм appupdate; источники обновления сервера от него независимы.

Установка на существующий сервер

Обычное обновление на Linux-хосте автоматически настраивает агент после переключения на выбранную версию и до пересоздания контейнеров:

cd /opt/pipu-music/deploy
./update.sh main   # либо тег версии, содержащей эту возможность

Если прав не хватает, установщик запросит sudo только для настройки системного сервиса. Повторный запуск проверяет установку и запускает остановленный агент; исправный агент с тем же кодом и unit-файлом не перезапускается. Ошибка установки останавливает обновление до пересоздания контейнеров. При обновлении из админки собственный агент остаётся запущенным и заменяет свою копию после успеха.

В версии v1.9.0 вызов установщика из update.sh был пропущен. Если сервер уже обновлён до неё, агент можно включить сразу без новой сборки:

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.

Кнопка установки появляется только если выбранный commit отличается от работающего и переход не является откатом. Для main сравнивается SHA, для релиза — SHA тега. Одинаковая версия, более новая установленная сборка, ошибка проверки и неопределённый commit не предлагают установку. «Проверить обновления» обходит кэш refs. Работающий API передаёт свою встроенную revision; для прежних сборок агент разрешает hash из git-describe или локальный релизный тег. HEAD checkout и PIPU_VERSION в .env не считаются доказательством установленного commit, поскольку сборка могла не удаться.

Обновления устанавливаются только по нажатию кнопки и после подтверждения. Перед запуском агент повторно читает 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.

Маскирование охватывает .env, config.local, итоговое значение и значение по умолчанию. URL со встроенными учётными данными, query-параметрами или фрагментом целиком считается секретом. Поля замены изначально пусты; переключатель видимости показывает только новый ввод. После сохранения поле снова очищается.

Сохранение атомарно, с правами 0600 и проверкой ревизии: устаревшая форма не затрёт правки другого администратора. Перед сохранением проверяются типы и Compose; при ошибке прежний файл восстанавливается. Произвольные ключи, переводы строк и изменение служебных параметров отклоняются. Сохраняемые значения трактуются буквально: подстановки shell не выполняются.

Панель сохранения появляется только при отличиях от исходных локальных значений. После возврата прежних значений она исчезает. Сохранённые изменения, влияющие на итоговую конфигурацию, показывают отдельное действие применения. Пустой config.local, комментарии, явное значение по умолчанию или значение, перекрытое .env, сами по себе не требуют перезапуска.

Кнопка Применить и перезапустить отдельно подтверждает пересоздание контейнеров. Агент запускает apply-config.sh, ждёт /readyz и сохраняет результат. Если сервисы не стали готовы, состояние — ошибка; исправьте config.local или восстановите его на хосте. Автоматического отката конфигурации после неудачного применения нет.

Диагностика:

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.