Navidrome 은 Go 로 쓰인 자체 호스팅 음악 서버다. Subsonic API 를 구현하므로 기존 Subsonic 클라이언트를 그대로 쓸 수 있다. 메타데이터는 SQLite 에 담고, 음원 파일은 읽기만 한다.
운영에서 부딪히는 것은 대부분 스캔이다. 파일은 디스크에 있는데 화면에 안 나오거나, 태그를 고쳤는데 반영되지 않거나, 곡이 회색으로 표시되고 재생되지 않는다.
원인을 가르는 순서가 있다. 위에서부터 확인하면 대부분 중간에 끝난다.
1. 프로세스가 파일을 읽을 수 있는가. 컨테이너로 돌리는 경우 마운트 경로와 UID/GID 가 어긋나 일부 디렉터리만 안 보이는 일이 흔하다.
docker exec -it navidrome ls -l /music/some/album
docker exec -it navidrome id
2. 태그가 있는가. Navidrome 은 파일 경로가 아니라 태그로 화면을 구성한다. 앨범 · 아티스트 태그가 비어 있으면 파일을 읽었어도 목록에 자리를 잡지 못한다.
ffprobe -hide_banner -show_entries format_tags 문제파일.flac
3. 증분 스캔이 변경을 놓쳤는가. 이미 있는 아티스트 폴더에 파일을 추가한 경우, 상위 디렉터리의 수정 시각이 바뀌지 않아 증분 스캔이 지나치는 경우가 있다. 전체 스캔으로 확인한다.
docker exec -it navidrome ./navidrome scan --full
4. 경로와 태그를 한꺼번에 바꿨는가. Navidrome 은 경로와 메타데이터를 같이 보고 기존 레코드와 맞춘다. 파일을 옮기면서 태그도 고치면 매칭에 실패해 "기존 곡은 없어졌고 새 곡이 생겼다"로 처리된다. 재생 횟수와 별점이 끊긴다. 옮긴 뒤 스캔하고, 그다음에 태그를 고친다.
5. 회색으로 표시된다. 파일이 실제로 없다는 뜻이다. NAS 마운트가 끊겼거나 경로가 바뀐 상태로 스캔이 돌면 이렇게 된다. 마운트를 되살리고 다시 스캔하면 복구된다. 정말 없앤 파일이면 관리 화면에서 정리한다.
여기까지 해도 안 되면 DB 를 지우고 전면 재색인한다. 재생 횟수 · 별점 · 재생목록이 함께 사라지므로 마지막 수단이다. 미리 백업한다.
docker exec -it navidrome sqlite3 /data/navidrome.db ".backup '/data/navidrome.db.bak'"
스캔이 실제로 무엇을 했는지는 로그에만 남는다.
docker logs navidrome 2>&1 | grep -i scan | tail -50
문제를 쫓는 동안에는 로그 수위를 올린다.
ND_LOGLEVEL=debug
곡이 수만 단위가 되면 기본 설정으로는 스캔이 오래 걸리고 UI 가 느려진다.
DB 와 음원을 다른 디스크에 둔다. 이게 가장 효과가 크다. 스캔 중에는 메타데이터 읽기와 SQLite 쓰기가 동시에 몰리므로, DB 는 SSD 에 두고 음원은 HDD 에 두면 체감이 달라진다.
volumes:
- /mnt/ssd/navidrome:/data
- /mnt/hdd/music:/music:ro
음원 볼륨은 읽기 전용으로 붙여도 된다. 태그 편집 기능을 쓰지 않는다면 그쪽이 안전하다.
열 수 있는 파일 수를 늘린다. 곡 수가 많으면 기본 nofile 로 모자란다.
ulimits:
nofile:
soft: 65535
hard: 65535
cat /proc/$(pgrep navidrome)/limits | grep "open files"
inotify watch 여유를 확인한다. 파일 변경을 감시하는 기능을 켜 두면 디렉터리마다 watch 를 잡는다. 호스트 전체가 공유하는 자원이라 다른 컨테이너와 나눠 쓴다.
cat /proc/sys/fs/inotify/max_user_watches
cat /proc/sys/fs/inotify/max_user_instances
echo "fs.inotify.max_user_watches=524288" > /etc/sysctl.d/90-inotify.conf
sysctl --system
Navidrome 은 파일이 아니라 디렉터리 단위로 감시하므로 곡 수만큼 필요하지는 않다. 그래도 라이브러리가 커질 것을 보고 넉넉히 잡아 둔다.
마운트 옵션에서 atime 을 끈다. 스캔은 대량의 메타데이터 읽기라 접근 시각 갱신이 그대로 쓰기 IO 가 된다.
/dev/sdb1 /mnt/hdd/music xfs defaults,noatime,nodiratime 0 0
스캔 주기를 늘린다. 변경 감시를 켜 두었다면 전체 스캔을 자주 돌릴 이유가 없다. 주기 설정과 감시 설정의 키 이름은 버전에 따라 바뀌어 왔으므로 (확인 필요), 쓰는 버전의 설정 문서를 보고 navidrome.toml 또는 ND_ 환경변수로 넣는다.
트랜스코딩을 제한한다. 동시 트랜스코딩은 CPU 를 그대로 먹는다. 내부망에서 원본을 그대로 재생한다면 아예 끄고, 모바일 스트리밍이 있으면 동시 실행 수만 묶는다.
Navidrome 은 자기 디스크의 파일만 재생한다. Spotify 나 다른 스트리밍 서비스의 음원을 중계해 주는 기능은 없고, 그렇게 하는 것은 해당 서비스 약관 위반이기도 하다.
연동이라고 부르는 것은 두 가지다.
재생목록을 다른 서비스와 맞추고 싶다면 Navidrome 밖의 도구를 쓴다. Navidrome 은 Subsonic API 로 재생목록을 읽고 쓸 수 있으므로 동기화 스크립트를 붙이는 식이 된다.
Navidrome 자체에는 플러그인 구조가 없다. 기능을 붙이려면 Subsonic API 를 쓰는 별도 프로그램을 두는 것이 유일한 방법이다 (확인 필요 — 최근 버전에서 플러그인 기능이 추가되었는지는 릴리스 노트를 확인한다).