- deploy/compose.yaml: every app service has `build:` (repo root context), local tags pipu-music-<service>:<version> - deploy/update.sh: git fetch → checkout tag (latest release by default, or vX.Y.Z / main) → docker compose build --pull → up -d → prune → /readyz; re-executes from a temp copy because checkout may replace the script - install.sh / .env.example: no REGISTRY, PIPU_VERSION set by update.sh, .env owned by the invoking user - release.yml: drop image publishing; release ships APK + sha256 only - ci.yml: new `docker` job builds all images without push - docs: install guide uses git clone, deployment/ci-cd updated, ADR-013 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
15 KiB
Установка сервера и подключение приложений
Пошаговая инструкция: от чистого Linux-сервера до работающего Pipu Music на своём домене с HTTPS, плюс подключение веб- и Android-клиента. Справочник по устройству развёртывания — deployment.md.
В примерах:
- домен —
music.example.com, замените на свой; - репозиторий —
gitea.hsrv.site/mrleo1nid/pipu-music; - каталог установки —
/opt/pipu-music.
Готовые Docker-образы не публикуются: сервер клонирует репозиторий и собирает образы сам
(docker compose build). Релизы в Gitea содержат только APK для Android.
Что умеет текущая версия. В
v0.1.0(этап M0) работают развёртывание, HTTPS и проверка связи клиентов с сервером. Вход, библиотека и плеер появятся в следующих версиях (см. roadmap.md). Шаги, которые зависят от версии, помечены.
1. Что нужно заранее
| Что | Требование |
|---|---|
| Сервер | Linux x86_64 (Debian 12 / Ubuntu 22.04+), 4+ ядра, 8+ ГБ RAM, 30+ ГБ на диске (система, образы, кэш сборки, данные) |
| Доступ | root или пользователь с sudo |
| Домен | Поддомен, которым вы управляете, например music.example.com |
| Сеть | Входящие 80/tcp и 443/tcp (+ 443/udp для HTTP/3) из интернета на сервер |
| Музыка | NFS-сервер с библиотекой (подключается позже из админки) |
| Интернет на сервере | Нужен при сборке: скачиваются базовые образы и зависимости Go / npm / Python |
| Gitea | Доступ к репозиторию на чтение (если он приватный — токен или SSH-ключ) |
2. DNS
Создайте у регистратора или в DNS-панели запись:
| Тип | Имя | Значение |
|---|---|---|
A |
music |
публичный IPv4 сервера |
AAAA |
music |
публичный IPv6 (если есть; если нет — запись не создавайте) |
Если сервер стоит дома за роутером, пробросьте на роутере порты 80 и 443 на внутренний IP сервера.
Проверка — команда должна вернуть IP вашего сервера:
dig +short music.example.com
Сертификат Let's Encrypt выдаётся, только когда домен уже указывает на сервер и порт 80 доступен из интернета. Не запускайте шаг 6, пока эта проверка не проходит.
3. Docker
curl -fsSL https://get.docker.com | sudo sh
Добавьте своего пользователя в группу docker, чтобы запускать сборку без sudo (после этого перелогиньтесь):
sudo usermod -aG docker "$USER"
И git, если его нет:
sudo apt-get install -y git
Проверьте, что есть Docker Compose v2.24 или новее (нужен для compose.tls.yaml):
docker compose version
Откройте порты в файрволе, если он включён (пример для ufw):
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw allow 443/udp
4. Клонирование репозитория
sudo mkdir -p /opt/pipu-music && sudo chown "$USER" /opt/pipu-music
git clone https://gitea.hsrv.site/mrleo1nid/pipu-music.git /opt/pipu-music && cd /opt/pipu-music/deploy
Если репозиторий приватный: клонируйте по SSH (
git@gitea.hsrv.site:mrleo1nid/pipu-music.git) с ключом, добавленным в Gitea, или по HTTPS с токеном (правоread:repository) — Git спросит логин и токен вместо пароля. Сохраните доступ (git config credential.helper storeили SSH-ключ):update.shделаетgit fetchпри каждом обновлении.
Все дальнейшие команды выполняются из /opt/pipu-music/deploy.
5. Подготовка сервера
sudo ./install.sh
Скрипт:
- создаёт каталоги данных в
/srv/pipu(БД, кэши, загрузки, сертификаты); - делает
/srv/pipu/libraryточкой монтирования с shared propagation, чтобы NFS-хранилища, которые потом подключит админ, были видны всем контейнерам, и ставит systemd-юнит, повторяющий это после перезагрузки; - создаёт
.envсо случайными паролями БД, ключом поиска и межсервисным токеном.
Заполните в /opt/pipu-music/deploy/.env:
COMPOSE_FILE=compose.yaml:compose.tls.yaml
DOMAIN=music.example.com
ACME_EMAIL=you@example.com
ACME_EMAIL — адрес, на который Let's Encrypt пишет, если с сертификатом что-то не так.
Остальные значения менять не нужно; PIPU_VERSION проставляет update.sh.
.env не хранится в git (он в .gitignore), поэтому обновления репозитория его не трогают.
6. Сборка и запуск
./update.sh
Скрипт переключает репозиторий на последний релизный тег (например, v0.1.1), собирает образы, запускает
все сервисы и ждёт готовности API (до 2 минут). Первая сборка занимает 5–15 минут, следующие — быстрее
за счёт кэша Docker. Конкретная версия: ./update.sh v0.1.1.
Локальная сборка поддерживается начиная с
v0.1.1: в тегеv0.1.0compose.yamlещё ссылается на реестр образов. Покаv0.1.1не вышел, запускайте./update.sh main. При первом запуске Caddy сам получит сертификат дляDOMAIN, обычно за 10–30 секунд.
Проверка с любого компьютера:
curl -s https://music.example.com/api/v1/server-info
Ожидаемый ответ: {"name":"pipu-music","version":"0.1.0",...}. Проверка всех зависимостей:
curl -s https://music.example.com/readyz
Должно вернуться "status":"ok" и ok для postgres и redis.
7. Веб-клиент
Откройте https://music.example.com в браузере.
-
v0.1.0: карточка «Сервер 0.1.0 на связи» и переключатель языка RU / EN.
-
С версии 0.2 (M1): экран входа. Первый вход — логин
adminи пароль, который сервер один раз выводит в лог при первом запуске:docker compose logs api | grep -i bootstrapСразу после входа приложение попросит сменить логин и пароль администратора (auth-and-roles.md). Чтобы задать пароль заранее, впишите
BOOTSTRAP_ADMIN_PASSWORDв.envдо первого запуска. -
С версии 0.3 (M2): Админка → Хранилища → «Добавить хранилище» → адрес NFS-сервера и путь экспорта → «Проверить» → шаблоны путей → «Сохранить и пересканировать» (library-and-storage.md).
8. Android-приложение
- На телефоне откройте страницу релизов
https://gitea.hsrv.site/mrleo1nid/pipu-music/releasesи скачайтеpipu-music-<версия>.apk. - Откройте файл. Android попросит разрешить установку из этого источника (браузера или файлового менеджера) — разрешите и вернитесь к установке.
- Запустите Pipu Music, на экране подключения введите адрес сервера:
music.example.com(https://подставится сам) → «Проверить». - Ожидаемый результат — «Сервер 0.1.0 на связи». Если версия приложения слишком старая для сервера, приложение попросит обновиться.
Дальше приложение обновляется само: с версии M5 оно проверяет новые релизы через ваш сервер
и предлагает обновиться (mobile.md). Для этого в .env сервера нужно заполнить
GITEA_URL, GITEA_REPO и GITEA_TOKEN (токен только на чтение).
Приложению нужен настоящий сертификат. С самоподписанным сертификатом и голым IP-адресом подключиться не получится. Поэтому нужен домен с Let's Encrypt, как в этой инструкции.
9. Вариант: свой reverse proxy вместо Caddy
Если на сервере уже есть Traefik, Nginx Proxy Manager или свой nginx с сертификатами:
-
В
.envзакомментируйтеCOMPOSE_FILEи задайте порт, на котором Pipu будет слушать только локально:#COMPOSE_FILE=compose.yaml:compose.tls.yaml HTTP_PORT=127.0.0.1:8081 -
Направьте прокси для
music.example.comнаhttp://127.0.0.1:8081с такими настройками:- передавать заголовки
Host,X-Forwarded-For,X-Forwarded-Proto; - лимит тела запроса не меньше 16 МБ (загрузка треков идёт чанками по 8 МБ);
- без буферизации ответов (стриминг аудио), длинные таймауты чтения (≥ 1 ч).
Пример для nginx:
server { listen 443 ssl http2; server_name music.example.com; # ssl_certificate / ssl_certificate_key — как у остальных ваших сайтов client_max_body_size 16m; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_read_timeout 1h; } } - передавать заголовки
-
Запуск и проверки — как в шагах 6–8.
Если прокси работает на другой машине, укажите в HTTP_PORT внутренний адрес сервера (192.168.1.10:8081) и
закройте этот порт от интернета файрволом.
10. Обновление, бэкапы, удаление
Обновление до последнего релиза:
cd /opt/pipu-music/deploy && ./update.sh
Конкретная версия или откат: ./update.sh v0.2.0. Скрипт делает git fetch, переключается на тег,
пересобирает образы и перезапускает сервисы; старые образы удаляются. Миграции БД применяются
автоматически при старте API.
Бэкап базы (всё остальное восстанавливается само — см. deployment.md):
docker compose exec -T postgres pg_dump -U pipu -Fc pipu > /srv/pipu/backups/pipu-$(date +%F).dump
Остановить сервис, сохранив данные:
cd /opt/pipu-music/deploy && docker compose down
11. Если что-то не работает
| Симптом | Что проверить |
|---|---|
| Сертификат не выдаётся, браузер ругается на HTTPS | dig +short music.example.com указывает на сервер; порт 80 открыт снаружи; docker compose logs caddy |
502 Bad Gateway |
API ещё запускается или упал: docker compose ps, docker compose logs api |
/readyz отвечает degraded |
Какая зависимость не ok — её логи: docker compose logs postgres / redis |
update.sh: ошибка git fetch |
Нет доступа к репозиторию: проверьте SSH-ключ или сохранённый токен (git fetch вручную) |
| Сборка падает на скачивании зависимостей | Нет интернета или DNS на сервере; повторите ./update.sh — уже собранные слои берутся из кэша |
| Сборка падает: «no space left on device» | Очистите кэш сборки: docker builder prune |
permission denied … docker.sock |
Пользователь не в группе docker (шаг 3) или вы не перелогинились |
storage-agent не стартует, ошибка про propagation / shared mount |
Ещё раз sudo ./install.sh; на хосте findmnt -o TARGET,PROPAGATION /srv/pipu/library должно показать shared |
| Android: «Сервер не отвечает» | Тот же адрес открывается в браузере телефона; в адресе нет опечатки; телефон в сети с доступом к серверу |
| Android: «Эта версия приложения слишком старая» | Установите APK из последнего релиза |
Логи всех сервисов сразу:
cd /opt/pipu-music/deploy && docker compose logs -f --tail=100