296 lines
15 KiB
Markdown
296 lines
15 KiB
Markdown
# Navidrome Music Server — LXC 203 (media)
|
||
| Контейнер | Путь | Порты| Тип|
|
||
|----------|---------|---------|---------|
|
||
| `media` (203)|`/mnt/service/navidrome` |`45136` (Web/API) | Self-hosted Subsonic-сервер + автоматическая разметка метаданных|
|
||
- [🤖 Роль Ansible](../../ansible/roles/navidrome.md)
|
||
|
||
## 📋 Описание
|
||
Лёгкий, быстрый и современный музыкальный сервер с полной поддержкой Subsonic API. Включает автоматическую нормализацию метаданных через `beets` + MusicBrainz, обход блокировок через Xray-туннель, исправление кодировки кириллицы и умные плейлисты через ListenBrainz.
|
||
Особенности:
|
||
✅ Полная локализация: интерфейс на русском языке (98%+ перевод)
|
||
✅ Автоматическая разметка: `beets` + MusicBrainz для идеальных тегов и обложек
|
||
✅ Обход блокировок: локальный SOCKS5-туннель через VPS для доступа к MusicBrainz
|
||
✅ Кириллица: автоматическая конвертация тегов из CP1251 в UTF-8
|
||
✅ Умные плейлисты: плагин ListenBrainz Daily Playlist («Моя волна»)
|
||
✅ Клиенты: полная поддержка Subsonic-клиентов (Symfonium, Substreamer, Ultrasonic)
|
||
|
||
## 🗂️ Структура файлов
|
||
|
||
```text
|
||
/mnt/service/navidrome/
|
||
├── docker-compose.yml # Конфиг запуска сервера
|
||
├── data/ # База данных, настройки, кэш Navidrome
|
||
├── plugins/ # Директория для плагинов (.ndp)
|
||
└── navidrome.tar # Архив для миграции между контейнерами
|
||
/mnt/audio/ # Точка монтирования музыкальной библиотеки
|
||
```
|
||
|
||
## ⚙️ Установка и настройка
|
||
### Шаг 1: Подготовка директорий и прав
|
||
```bash
|
||
sudo mkdir -p /mnt/service/navidrome/{data,plugins}
|
||
sudo chown -R 1000:1000 /mnt/service/navidrome/data /mnt/service/navidrome/plugins
|
||
sudo chmod -R a+rX /mnt/audio
|
||
```
|
||
|
||
### Шаг 2: Конфигурация Docker Compose
|
||
Создайте файл `/mnt/service/navidrome/docker-compose.yml`:
|
||
```yaml
|
||
services:
|
||
navidrome:
|
||
image: deluan/navidrome:latest
|
||
container_name: navidrome
|
||
user: "1000:1000"
|
||
ports:
|
||
- "45136:4533"
|
||
volumes:
|
||
- ./data:/data
|
||
- /mnt/audio:/music:ro
|
||
- ./plugins:/plugins:ro
|
||
environment:
|
||
- TZ=Asia/Yekaterinburg
|
||
- ND_MUSICFOLDER=/music
|
||
- ND_DATAFOLDER=/data
|
||
- ND_PORT=4533
|
||
- ND_LOGLEVEL=info
|
||
- ND_DEFAULTLANGUAGE=ru
|
||
- ND_PLUGINS_ENABLED=true
|
||
- ND_PLUGINS_FOLDER=/plugins
|
||
- ND_PLUGINS_AUTORELOAD=false
|
||
- ND_PLUGINS_LOGLEVEL=info
|
||
- ND_PLUGINS_CACHESIZE=200MB
|
||
restart: unless-stopped
|
||
security_opt:
|
||
- no-new-privileges:true
|
||
```
|
||
|
||
### Шаг 3: Запуск и первоначальная настройка
|
||
```bash
|
||
cd /mnt/service/navidrome
|
||
sudo docker compose up -d
|
||
sudo docker compose logs -f --tail=20
|
||
```
|
||
Ожидаемый вывод: `INFO Starting HTTP server on :4533`.
|
||
Откройте `http://<IP>:4533`, создайте учётную запись администратора. Сервер автоматически просканирует `/mnt/audio`.
|
||
|
||
## Автоматическая разметка метаданных (beets + MusicBrainz)
|
||
Серверы не исправляют теги автоматически. Для чистоты библиотеки используется `beets`.
|
||
|
||
### Шаг 1: Установка зависимостей
|
||
```bash
|
||
sudo apt update
|
||
sudo apt install beets python3-pylast python3-requests python3-unidecode python3-mutagen
|
||
mkdir -p ~/.config/beets
|
||
```
|
||
|
||
### Шаг 2: Конфигурация beets (`~/.config/beets/config.yaml`)
|
||
```yaml
|
||
directory: /mnt/audio/music
|
||
library: ~/.config/beets/library.db
|
||
|
||
import:
|
||
write: yes
|
||
copy: yes
|
||
move: yes
|
||
autotag: yes
|
||
group_albums: no
|
||
|
||
paths:
|
||
default: $albumartist/$album%aunique{}/$track - $title
|
||
singleton: Non-Album/$artist - $title
|
||
comp: Various Artists/$album%aunique{}/$track - $title
|
||
|
||
plugins: fetchart embedart
|
||
|
||
fetchart:
|
||
auto: yes
|
||
minwidth: 500
|
||
maxwidth: 1000
|
||
enforce_ratio: yes
|
||
sources: [filesystem, coverart, itunes, amazon]
|
||
|
||
embedart:
|
||
auto: yes
|
||
compare_threshold: 0
|
||
ifempty: no
|
||
```
|
||
|
||
### Шаг 3: Обход блокировок MusicBrainz (Xray-туннель)
|
||
Если MusicBrainz недоступен из вашей сети, поднимите локальный SOCKS5-прокси через Xray (см. документацию `xray-client.md`). Запуск импорта через прокси:
|
||
```bash
|
||
https_proxy=socks5h://127.0.0.1:1080 http_proxy=socks5h://127.0.0.1:1080 beet import -q /mnt/audio/НоваяПапка
|
||
```
|
||
|
||
### Шаг 4: Исправление кириллицы (CP1251 → UTF-8)
|
||
Старые сборники часто содержат теги в Windows-1251. Перед импортом конвертируйте:
|
||
```bash
|
||
find /mnt/audio/ЦелеваяПапка -type f -name "*.mp3" -print0 | xargs -0 mid3iconv -e cp1251
|
||
```
|
||
Проверка результата: `mid3v2 -l файл.mp3 | grep -E "TIT2|TPE1|TALB"`
|
||
|
||
## 🧩 Плагины и умные плейлисты
|
||
Навигроум поддерживает WASM-плагины. Для работы рекомендаций используется `listenbrainz-daily-playlist`.
|
||
|
||
### Шаг 1: Установка плагина
|
||
```bash
|
||
cd /mnt/service/navidrome/plugins
|
||
sudo curl -L -o listenbrainz-daily-playlist.ndp https://github.com/kgarner7/navidrome-listenbrainz-daily-playlist/releases/latest/download/listenbrainz-daily-playlist.ndp
|
||
sudo chown 1000:1000 listenbrainz-daily-playlist.ndp
|
||
```
|
||
|
||
Шаг 2: Получение токена ListenBrainz
|
||
1. Зарегистрируйтесь на https://listenbrainz.org
|
||
2. Перейдите в `Profile Settings` → `User Token`
|
||
3. Скопируйте токен и вставьте в `docker-compose.yml` в переменную `ND_PLUGINS_LISTENBRAINDAILYPLAYLIST_LISTENBRAINZTOKEN`
|
||
4. Перезапустите контейнер: `sudo docker compose restart navidrome`
|
||
|
||
### Шаг 3: Включение скробблинга в клиенте (Symfonium)
|
||
Настройки → Интеграции → ListenBrainz → Включить → Вставить токен → Сохранить.
|
||
Плейлист «Моя волна» появится в разделе «Плейлисты» после 5-10 прослушанных треков и автоматической генерации (раз в 24ч).
|
||
|
||
### 🎵 Плейлисты из папок (M3U-импорт)
|
||
|
||
Navidrome автоматически импортирует файлы `.m3u` и `.m3u8`, размещённые внутри музыкальной директории. Это позволяет создавать плейлисты на основе содержимого папок без ручного добавления треков.
|
||
|
||
#### Создание плейлиста из папки
|
||
|
||
```bash
|
||
cd /mnt/audio/music/Сборники/savedtracks
|
||
find . -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.ogg" -o -iname "*.m4a" \) -printf '%P\n' | sort > savedtracks.m3u
|
||
```
|
||
|
||
**Что делает команда:**
|
||
- `find . -type f` — рекурсивный поиск файлов
|
||
- `\( -iname "*.mp3" -o ... \)` — фильтрация по аудио-расширениям
|
||
- `-printf '%P\n'` — вывод относительных путей (без `./`, как требует Navidrome)
|
||
- `sort` — сортировка по имени для фиксированного порядка треков
|
||
- `> savedtracks.m3u` — сохранение в файл плейлиста
|
||
|
||
#### Применение изменений
|
||
|
||
После создания или обновления M3U-файла запустите сканирование библиотеки:
|
||
|
||
```bash
|
||
curl -k -s "https://music.zailon.ru/rest/startScan?u=zailon&p=13qeadZC&v=1.16.1&c=curl"
|
||
```
|
||
|
||
Или через веб-интерфейс: `Настройки → Библиотека → Пересканировать`.
|
||
|
||
#### Проверка результата
|
||
|
||
```bash
|
||
curl -k -s "https://music.zailon.ru/rest/getPlaylists?u=zailon&p=13qeadZC&v=1.16.1&c=curl" | grep -i savedtracks
|
||
```
|
||
|
||
Ожидаемый вывод:
|
||
```xml
|
||
<playlist name="savedtracks" songCount="692" .../>
|
||
```
|
||
|
||
Плейлист появится в веб-интерфейсе и в подключённых клиентах (Symfonium, Substreamer) после синхронизации.
|
||
|
||
#### Требования к путям в M3U
|
||
|
||
✅ Правильно (относительные пути):
|
||
```text
|
||
001. Эдита Пьеха - Песня остаётся с человеком (1965).mp3
|
||
002. Муслим Магомаев - Лучший город Земли (1965).mp3
|
||
```
|
||
|
||
❌ Неправильно (абсолютные пути — Navidrome не сопоставит):
|
||
```text
|
||
/mnt/audio/music/Сборники/savedtracks/001. Эдита Пьеха....mp3
|
||
```
|
||
|
||
Используйте `-printf '%P\n'` в `find`, чтобы гарантировать правильный формат.
|
||
|
||
#### Переименование плейлиста
|
||
|
||
Имя плейлиста в Navidrome соответствует имени файла `.m3u`. Чтобы изменить название:
|
||
|
||
```bash
|
||
mv /mnt/audio/music/Сборники/savedtracks/savedtracks.m3u /mnt/audio/music/Сборники/savedtracks/Избранное.m3u
|
||
curl -k -s "https://music.zailon.ru/rest/startScan?u=zailon&p=13qeadZC&v=1.16.1&c=curl"
|
||
```
|
||
|
||
После сканирования плейлист будет называться «Избранное».
|
||
|
||
## 📱 Подключение Android-клиента (Symfonium)
|
||
1. Установите Symfonium из Google Play / F-Droid
|
||
2. Настройки → Аккаунты → Добавить → Subsonic
|
||
3. Заполните:
|
||
URL: `https://music.вашдомен.ru`
|
||
Логин/Пароль: от Navidrome
|
||
SSL/HTTPS: ✅ Включить
|
||
Транскодинг: ❌ Выключить
|
||
4. Нажмите «Проверить подключение» → «Сохранить»
|
||
5. Включите скробблинг в разделе Интеграции (см. выше)
|
||
|
||
## Полезные команды
|
||
### Управление контейнером
|
||
```bash
|
||
sudo docker compose up -d # Запуск
|
||
sudo docker compose down # Остановка
|
||
sudo docker compose logs -f # Логи в реальном времени
|
||
sudo docker exec navidrome /navidrome --rescan # Принудительное сканирование
|
||
```
|
||
|
||
### Работа с beets
|
||
```bash
|
||
beet import -q /mnt/audio/ # Тихий импорт всей библиотеки
|
||
beet ls -f '$albumartist/$album/$title' | head -20 # Просмотр структуры в БД
|
||
beet remove -d 'album:"Название"' # Удалить из БД (файлы останутся)
|
||
beet update # Обновить БД при изменении тегов на диске
|
||
```
|
||
|
||
### Миграция и бэкап
|
||
```bash
|
||
# Создание архива для переноса
|
||
cd /mnt/service/navidrome
|
||
sudo tar -cf navidrome.tar data docker-compose.yml plugins
|
||
|
||
# Восстановление на новом сервере
|
||
sudo tar -xf navidrome.tar
|
||
sudo chown -R 1000:1000 data plugins
|
||
```
|
||
|
||
## 🚨 Решение проблем
|
||
| Проблема | Причина | Решение |
|
||
|----------|---------|---------|
|
||
| `OCI runtime exec failed: navidrome not found` | Неверный путь к бинарнику в контейнере | Используйте `sudo docker exec navidrome /navidrome --rescan` |
|
||
| Кракозябры вместо кириллицы | Теги в CP1251 | `find /mnt/audio -name "*.mp3" -print0 \| xargs -0 mid3iconv -e cp1251` |
|
||
| `MusicBrainz not reachable` | Блокировка API или таймаут | Запускайте `beet` с `https_proxy=socks5h://127.0.0.1:1080` |
|
||
| Плагин не грузится | Ошибка в конфиге или правах | Проверьте `sudo docker compose logs navidrome \| grep plugin`, убедитесь что `.ndp` читается пользователем 1000 |
|
||
| Плейлист «Моя волна» пуст | Нет скробблов в ListenBrainz | Послушайте 5+ треков в Symfonium, проверьте ленту на listenbrainz.org, подождите 24ч |
|
||
| Навидром не видит новые файлы | Отключено автосканирование или права | `sudo chmod -R a+rX /mnt/audio`, в UI: Настройки → Библиотека → Пересканировать |
|
||
|
||
## 🔐 Безопасность
|
||
Настройки для продакшена
|
||
✅ Reverse Proxy: Всегда проксируйте порт 4533 через Nginx Proxy Manager с Let's Encrypt SSL
|
||
✅ Subsonic API: Никогда не открывайте порт 4533 напрямую в интернет. Используйте только HTTPS
|
||
✅ Xray-туннель: Прокси слушает только `127.0.0.1:1080`. Не меняйте на `0.0.0.0`
|
||
✅ Права доступа: Контейнер работает от `1000:1000` с `no-new-privileges:true`
|
||
✅ Пароли: Смените пароль администратора по умолчанию, используйте сложные токены для плагинов
|
||
✅ Резервное копирование: Регулярно архивируйте папку `data/` — в ней хранится вся история прослушиваний и плейлисты
|
||
|
||
## Обновление
|
||
### Обновление ядра Navidrome
|
||
```bash
|
||
cd /mnt/service/navidrome
|
||
sudo docker compose pull
|
||
sudo docker compose up -d
|
||
# Конфигурация и база данных сохраняются в томах, миграция происходит автоматически
|
||
```
|
||
|
||
### Обновление плагинов
|
||
```bash
|
||
cd /mnt/service/navidrome/plugins
|
||
sudo curl -L -o plugin-name.ndp <новая_ссылка>
|
||
sudo docker compose restart navidrome
|
||
```
|
||
|
||
## 💡 Рекомендации по поддержке
|
||
• Проводите `mid3iconv` для всей библиотеки один раз при первичном развёртывании
|
||
• Используйте флаг `-q` в `beet import` для больших библиотек (10k+ треков)
|
||
• Включите `ND_PLUGINS_AUTORELOAD=true` только на время отладки плагинов
|
||
• Для мониторинга используйте встроенные логи Navidrome и `htop` внутри контейнера |