Upload import is not implemented yet, so nothing needs write access to LIBRARY_HOST. Write access will come back together with the import. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.2 KiB
Развёртывание
Пошаговая инструкция «с нуля до работающего сервера на домене» — install-guide.md. Здесь — справочник: требования, каталоги, сервисы, переменные.
Требования к серверу
- Linux x86_64 (нужен mount propagation для storage-agent), Docker 24+, Docker Compose v2.
- 4+ ядра, 8+ ГБ RAM (аудиоанализ при первом запуске ест CPU; TensorFlow-модели ~1–2 ГБ RAM).
- Диск: ~5 ГБ под систему и БД + кэш транскодов (по умолчанию 50 ГБ) + обложки (~1 ГБ на 10k альбомов).
- Сетевой доступ к NFS-серверам.
Каталоги на хосте
/srv/pipu/
├── library/ # точки монтирования источников (storage-agent, rshared)
├── library-host/ # папка для type=local по умолчанию; обычно вместо неё LIBRARY_HOST=/mnt/music
├── cache/
│ ├── transcode/
│ └── covers/
├── postgres/
├── meili/
├── redis/
├── models/ # модели Essentia (скачиваются при первом старте analyzer)
├── updates/ # кэш APK релизов
├── uploads/ # staging очереди на добавление (размер ≈ лимит очереди, по умолчанию 10 ГБ)
├── backups/
└── caddy/ # сертификаты Let's Encrypt (если используется compose.tls.yaml)
Музыка на локальном диске сервера подключается через LIBRARY_HOST в .env (например, /mnt/music):
каталог хоста монтируется во все сервисы, включая storage-agent, только на чтение (запись появится вместе
с импортом одобренных загрузок), внутри контейнеров он виден как /library-host.
Перед первым запуском: mkdir -p /srv/pipu/library && mount --bind /srv/pipu/library /srv/pipu/library && mount --make-rshared /srv/pipu/library
(делает deploy/install.sh, плюс systemd-unit для повторения после перезагрузки).
deploy/compose.yaml
Актуальная конфигурация — сам файл deploy/compose.yaml; здесь — как он устроен.
- Образы собираются на сервере из клонированного репозитория (
build:у каждого сервиса, контекст — корень репо), в реестр ничего не публикуется. Теги локальные:pipu-music-<сервис>:<версия>, версия —git describeтекущего тега (её проставляетupdate.shвPIPU_VERSION).
| Сервис | Собирается из | Особенности |
|---|---|---|
nginx |
apps/web/Dockerfile |
SPA + конфиг nginx; единственный открытый порт (HTTP_PORT) или за Caddy |
api |
services/api/Dockerfile, target api |
Миграции при старте |
storage-agent |
services/api/Dockerfile, target storage-agent |
CAP_SYS_ADMIN, apparmor:unconfined, библиотека с propagation: rshared |
recommender, analyzer |
services/recommender/Dockerfile (один образ) |
Команды serve и analyze --workers 4 |
postgres |
pgvector/pgvector:0.8.7-pg17 |
Healthcheck pg_isready |
redis |
redis:7.4-alpine |
AOF |
meilisearch |
getmeili/meilisearch:v1.11 |
|
caddy (из compose.tls.yaml) |
caddy:2.10-alpine |
HTTPS на DOMAIN, nginx тогда без открытых портов |
- Библиотека монтируется в
nginx,api,analyzerтолько на чтение сpropagation: rslave. - Наружу открыт только
nginx(илиcaddy). Все остальные — во внутренней сети compose.
Конфигурация (.env)
| Переменная | Пример / по умолчанию | Описание |
|---|---|---|
PIPU_VERSION |
проставляет update.sh |
Версия собранных образов (git describe) |
PUBLIC_URL |
https://music.home.lan |
Внешний адрес |
DATABASE_URL |
postgres://pipu:…@postgres:5432/pipu |
|
REDIS_URL |
redis://redis:6379/0 |
|
MEILI_URL, MEILI_MASTER_KEY |
||
JWT_PRIVATE_KEY_FILE |
/run/secrets/jwt_ed25519.pem |
Генерируется install.sh |
STREAM_SIGNING_KEY |
32 байта base64 | HMAC подписанных ссылок |
INTERNAL_TOKEN |
случайный | Межсервисная аутентификация |
BOOTSTRAP_ADMIN_USERNAME |
admin |
|
BOOTSTRAP_ADMIN_PASSWORD |
пусто → сгенерировать и вывести в лог | |
TRANSCODE_CACHE_LIMIT_GB |
50 |
|
TRANSCODE_CONCURRENCY |
2 |
|
GITEA_URL, GITEA_REPO, GITEA_TOKEN |
https://git.home.lan, owner/pipu-music, read-only токен |
Для самообновления Android |
PIPU_FILE_UID, PIPU_FILE_GID |
1000 |
Владелец файлов, которые агент записывает в принимающие хранилища |
UPLOADS_DIR |
/uploads |
Staging очереди на добавление (лимит очереди задаётся в админке) |
LOG_LEVEL |
info |
TLS
- Свой домен (рекомендуется) —
deploy/compose.tls.yamlдобавляет Caddy, который получает и продлевает сертификат Let's Encrypt дляDOMAINи проксирует на nginx; nginx тогда наружу не открыт. Включается строкойCOMPOSE_FILE=compose.yaml:compose.tls.yamlв.env. - Свой reverse proxy (Traefik, NPM, nginx) — без
compose.tls.yaml, прокси направляется наHTTP_PORT(например127.0.0.1:8081); нужныX-Forwarded-*, тело до 16 МБ, без буферизации ответов. - nginx внутри образа
webберёт схему и IP клиента изX-Forwarded-Proto/X-Forwarded-For, если запрос пришёл из частной сети (docker, LAN). - Локальная сеть без домена — свой CA; сертификат CA нужно установить на устройства или включить пиннинг в мобильном (см. mobile.md).
Пошаговая установка на домен — install-guide.md.
Бэкапы
pg_dumpежедневно (cron-контейнерbackup), хранить 14 дней + еженедельные 8 недель →/srv/pipu/backups.- Meilisearch, кэши и модели не бэкапятся — восстанавливаются (
reindex, повторный транскод / анализ). - Признаки анализа хранятся в Postgres — после восстановления из бэкапа повторный многочасовой анализ не нужен.
- Сама музыка — на NFS, вне зоны ответственности приложения.
Обновление
cd /opt/pipu-music/deploy && ./update.sh # последний релизный тег
Скрипт: git fetch → checkout тега → docker compose build --pull → up -d → удаление старых образов →
ожидание /readyz; миграции применяются при старте api.
Конкретная версия или откат: ./update.sh v1.2.4 (миграции пишутся обратно-совместимыми в пределах минорной версии: сначала добавить,
потом — в следующем релизе — удалить).