如何在 VPS 上自架 Navidrome 音樂串流
學會在 VPS 執行 Navidrome,從儲存空間估算、Subsonic 用戶端與離線同步,到 TLS 設定及安全備份,隨時串流自己的音樂庫。
在 VPS 上自架音樂串流能提供什麼
在 VPS 上自架音樂串流,表示由你執行播放器並提供音樂。伺服器會保存你已擁有的檔案,任何手機都能透過網際網路使用一般登入方式存取。開始前請先確認這項取捨:它取代的是串流服務的播放器,不是串流服務的曲庫。除非你購買或擷取音樂,再將檔案複製到伺服器,否則媒體庫不會新增任何內容。
音訊對伺服器的負擔比視訊小得多。檔案較小,手機不需額外處理即可解碼所有常見格式,而且一位聽眾使用的頻寬比視訊通話少。CPU 通常不是問題。真正的限制是磁碟空間。另一個決定這項方案能否順利運作的因素,是標籤品質;手機應用程式是否支援下載音樂供離線使用,也同樣重要。
選擇哪個音樂伺服器:Navidrome、Jellyfin,還是 Funkwhale?
Navidrome 是只需要音訊時的預設選擇。它是一個容器中的單一 Go 二進位檔,並將狀態儲存在單一 SQLite 資料庫中。它提供 Subsonic API,這也是大量第三方手機應用程式得以存在的原因。2026 年 8 月的目前版本是 0.63.2。專案表示,它在小至 Raspberry Pi Zero 的硬體上也能良好運作,因此你不需要為伺服器軟體本身支付費用。
如果你已經在 VPS 上將 Jellyfin 作為媒體伺服器運作,就值得使用 Jellyfin。它的音樂資料庫功能可正常運作,而 Finamp 是適用於 Android 和 iOS 的 Jellyfin 音樂應用程式,可下載曲目以供離線聆聽。限制在於 API。Jellyfin 沒有內建的 Subsonic endpoint,而提供該功能的社群 plugin 自 2022 年起便停止更新,因此 Subsonic 應用程式生態系統不支援 Jellyfin。你必須改用支援 Jellyfin 自有 API 的應用程式,而這類應用程式較少。
Funkwhale 是聯邦式選項,2.0 版於 2026 年 3 月發布。Funkwhale 伺服器稱為 pod,pod 透過 ActivityPub(Mastodon 背後使用的通訊協定)進行聯邦,一個 pod 上的使用者可以追蹤另一個 pod 上的公開資料庫。它也支援部分 Subsonic API,但有一項值得注意的差異:每位使用者都必須在自己的設定中設定獨立的 Subsonic 密碼,因為 Subsonic protocol 預期伺服器可以讀回密碼。Funkwhale 的安裝較為複雜,因為除了 web app 外,還需要 PostgreSQL 和 task queue。
除非你需要聯邦功能,或已經在執行 Jellyfin,否則請選擇 Navidrome。本指南其餘部分將使用 Docker 設定 Navidrome。
Subsonic API 如何決定你使用哪個手機 App
Subsonic 是一套音樂伺服器,其 HTTP API 後來成為自架音訊服務的通用介面;OpenSubsonic 則是持續擴充這套介面的社群專案。這段歷史造就了多種手機 App 可供選擇。Navidrome 不提供自有的行動 App,也不需要提供,因為任何 Subsonic 用戶端都能使用伺服器位址與帳號資訊登入。
這對離線同步尤其重要,因為這項功能會決定整套服務能否適合日常使用。手機進入隧道後無法連線到伺服器,因此用戶端必須事先將檔案複製到本機儲存空間。每個用戶端都能串流,但只有部分用戶端支援下載。位於 navidrome.org/apps 的用戶端目錄會說明哪些用戶端支援下載;兩個平台都有多種選擇:Android 上有 Substreamer 和 Ultrasonic,iOS 上有 Amperfy 和 play:Sub。多個功能最完整的用戶端都是付費 App,而 Android 上最常被提到的是 Symfonium。請先安裝兩個再做決定,因為這是你每天都會直接使用的系統部分。
音樂資料庫需要多少儲存空間?
The data behind this chart
[
{
"label": "Opus 128k",
"kbps": 128,
"gb_per_1000_albums": 43
},
{
"label": "MP3 320k",
"kbps": 320,
"gb_per_1000_albums": 108
},
{
"label": "FLAC 16/44.1",
"kbps": 900,
"gb_per_1000_albums": 304
},
{
"label": "FLAC 24/96",
"kbps": "3,000",
"gb_per_1000_albums": "1,013"
}
]這些是根據位元率推算出的數量級,而不是實際收藏的測量值。計算方式很簡單,可以用自己的檔案驗算。將一張專輯視為 45 分鐘,也就是 2,700 秒。將每秒千位元的位元率乘以 2,700,再除以 8,000,即可得到 MB。在 320 kbps 下,一張專輯約為 108 MB,因此 1,000 張專輯約為 108 GB。
無損格式會改變結果。一般音訊素材的 CD 品質 FLAC 平均接近 900 kbps,因此同樣的 1,000 張專輯約需 304 GB。24 bit、96 kHz 的資料庫約需 1,013 GB;對一個可以列在紙上的收藏來說,這已經是完整的 1 TB。適合手機的 128 kbps Opus 副本,則能將同樣的 1,000 張專輯壓縮在 43 GB 內。對現有的資料庫執行 du -sh /path/to/music,因為規劃方案時,真正重要的只有你自己的平均位元率。
頻寬只占總成本較小的一部分。320 kbps 的串流每秒傳輸 40 KB,因此聆聽 1 小時約會傳輸 144 MB。每月聆聽 100 小時約為 14 GB,這通常不會讓 VPS 的流量額度感到負擔。例外是手機首次進行離線同步,單一晚間就可能傳輸數十 GB。
儲存層還是運算層?
音樂伺服器主要存放大量冷資料,幾乎不需要運算。以每秒 40 kilobytes 的速度讀取檔案時,任何磁碟都幾乎處於閒置狀態;CPU 只有在掃描媒體庫或轉碼時才會工作,而你大多不會執行轉碼。因此,運算方案提供的高速 NVMe 在這裡沒有實際效益,反而是每 gigabyte 的價格讓你無法上傳 FLAC 副本。這正是儲存型 VPS 優於一般 VPS的情況,因為這類方案是按 terabyte 計價,而不是按 core 計價。
記憶體需求不高。Navidrome 為個人媒體庫提供服務時只需幾百 megabytes,尖峰用量出現在掃描期間,而不是播放期間。為伺服器配置 1 GB 或 2 GB RAM,將其餘預算用於磁碟空間。
使用 Docker Compose 安裝 Navidrome
先建立目錄,並將擁有者設為容器執行時使用的 user id。如果你不熟悉 Compose,VPS 上的 Docker Compose 會說明此檔案所依賴的設定。
sudo install -d -m 755 -o 1000 -g 1000 /srv/navidrome /srv/music在獨立目錄中建立 docker-compose.yml,檔案內容不需加入其他設定:
services:
navidrome:
image: deluan/navidrome:0.63.2
user: "1000:1000"
ports:
- "127.0.0.1:4533:4533"
restart: unless-stopped
environment:
ND_LOGLEVEL: "info"
ND_SESSIONTIMEOUT: "24h"
ND_SCANNER_SCHEDULE: "@every 24h"
ND_BACKUP_PATH: "/data/backup"
ND_BACKUP_SCHEDULE: "0 4 * * *"
ND_BACKUP_COUNT: "7"
volumes:
- /srv/navidrome:/data
- /srv/music:/music:rodocker compose up -d
docker compose psdocker compose ps 應顯示服務正在執行,而不是持續重新啟動。容器反覆重新啟動,幾乎都是因為 /srv/navidrome 的權限問題;docker compose logs navidrome 會指出容器無法寫入的檔案名稱。
該檔案中有 4 個細節值得說明。連接埠只繫結至 127.0.0.1,因此伺服器會透過反向代理提供存取,而不會直接在公開網際網路上開放 4533 埠:Docker 會自行寫入防火牆規則,因此即使在 ufw 顯示所有連線都遭拒絕的主機上,單純的 4533:4533 仍會保持暴露。音樂資料卷設為唯讀,因此即使掃描器發生錯誤,也無法刪除唯一的音樂副本。ND_SCANNER_SCHEDULE 預設為停用;在 Navidrome 0.55 之前撰寫的指南會將它稱為 ND_SCANSCHEDULE,但這個名稱已不存在。最後 3 個備份設定會啟用內建資料庫備份,下一節的備份流程會依賴這項功能。
將音樂放到伺服器
使用 rsync 複製音樂庫。連線中斷時,rsync 會從中斷處繼續,而不必重新開始。
rsync -av --info=progress2 ~/Music/ user@music.example.com:/srv/music/來源路徑結尾的斜線很重要。省略斜線會得到 /srv/music/Music。複製完成後,修正檔案擁有權:
sudo chown -R 1000:1000 /srv/music
id -u容器以 user id 1000 執行,且掛載內容為唯讀,因此每個檔案都必須能由該 id 讀取。如果 VPS 上的 SSH 帳號 uid 不是 1000,複製的檔案會由其他使用者擁有,掃描時找不到任何曲目,網頁介面也會維持空白。id -u 會顯示實際的 id;Docker 容器中的 PUID 與 PGID 運作方式則完整說明這項對應關係。
反向代理與 TLS,讓手機可從任何地方使用
將 DNS A 記錄指向 VPS,然後提供 Caddy 以下 3 行設定:
music.example.com {
reverse_proxy 127.0.0.1:4533
}sudo systemctl reload caddyCaddy 會在收到第一個請求時申請憑證。80 和 443 埠都必須開放,因為 ACME(自動憑證管理環境)挑戰會在 80 埠上回應。使用 nginx 時,請在 location 區塊加入 proxy_buffering off;:Navidrome 會透過一條長時間保持的連線,將進度事件推送到 Web 介面。啟用 buffering 時,介面會一直等待 nginx 尚未釋出的回應。若不是使用獨立子網域,而是以 /music 這類路徑提供服務,請將 ND_BASEURL 設為相同路徑,否則介面會載入空白頁面。3 種常見代理的比較請參閱 VPS 上的 Nginx、Caddy 與 Traefik。
開啟網站並建立第一個帳號。系統沒有預設密碼,第一位訪客會被要求建立管理員使用者。因此,請在告知他人網址前完成這項操作。接著測試手機用戶端實際使用的完整路徑:
SALT=$(openssl rand -hex 6)
TOKEN=$(printf '%s%s' 'YOUR_PASSWORD' "$SALT" | md5sum | cut -d' ' -f1)
curl -s "https://music.example.com/rest/ping.view?u=YOUR_USER&t=$TOKEN&s=$SALT&v=1.16.1&c=curl&f=json"正常回應會以 {"subsonic-response":{"status":"ok" 開頭,並將 navidrome 列為伺服器類型。若回應本文包含 "status":"failed" 且錯誤碼為 40,表示代理運作正常,但認證資訊錯誤。此時應優先修正憑證錯誤,因為大多數手機用戶端會拒絕無效憑證,且顯示的訊息通常無法協助使用者判斷問題。
首次掃描後媒體庫顯示不正確的原因
Navidrome 會依標籤而不是資料夾瀏覽,因此標籤決定你看到的內容。沒有專輯演出者標籤的曲目會歸到該曲目的演出者底下。這就是為什麼每首曲目由不同演出者演出的合輯,會變成 20 張各自只有 1 首曲目的專輯。請直接在檔案中修正標籤,不要在 Navidrome 中處理:MusicBrainz Picard 和 beets 都會在 MusicBrainz 資料庫中查詢專輯,並將標準標籤寫回檔案。
Navidrome 也會將包含多位演出者的標籤拆成個別演出者。因此,名稱包含分隔符號的樂團可能會被錯誤拆分,AC/DC 就是最常見的例子。ND_SCANNER_ARTISTSPLITEXCEPTIONS 放置絕對不可拆分的名稱。
新檔案寫入後幾秒,檔案監控程式就會偵測到這些檔案。監控程式依賴核心的變更通知;對於從另一台機器掛載的網路共用,這些通知不會傳送到本機。因此,在這類環境中,定期執行的 ND_SCANNER_SCHEDULE 才能讓媒體庫維持最新狀態。完整重新掃描會讀取每個檔案的標籤;大型媒體庫執行速度很慢,這也是值得保護下方資料庫的原因之一。
使用者、播放清單與分享
管理員會在 Web 介面中建立其他帳號,不提供自行註冊功能。每位使用者都有獨立的播放次數、播放清單、最愛項目與評分,因此家庭成員不會共用同一份偏好設定。
播放清單有兩種來源。在用戶端建立的播放清單會儲存在資料庫中。將 .m3u 檔案放入媒體庫資料夾後,系統會在掃描期間匯入;這是從桌面播放器轉移播放清單的簡便方式。智慧型播放清單是 .nsp 檔案,也就是以相同方式匯入的小型 JSON 規則檔案,並會隨媒體庫變更自動更新。
從 0.63.0 版本起,分享功能預設啟用;該版本於 2026 年 7 月發布。使用者可以為專輯建立公開連結,任何人都能在未登入的情況下開啟。如果伺服器包含完整媒體庫,這項設定可能不符合需求;將 ND_ENABLESHARING 設為 false 即可停用分享功能。
將資料庫與音樂檔案分開備份
Navidrome 本身的備份只涵蓋資料庫。文件對此說得很直接:備份程序會備份資料庫,也就是使用者、播放次數及其他資料,但不會備份音樂或設定檔。這樣區分才是正確的理解方式,因為這兩部分的故障情況不同。音樂檔案可以再從存放原始檔案的磁碟複製回來。播放次數、評分、最愛項目與播放清單沒有其他來源,重新掃描也無法還原這些資料。
compose file 已設定在每晚將副本寫入 /data/backup,並保留七份。升級前,先手動建立一份:
sudo docker compose run --rm navidrome backup create還原會清除目前的資料庫,並將備份複製到原本的位置,而且必須在 Navidrome 停止時執行。伺服器仍在運作時進行還原,沒有任何安全性可言。
這些檔案仍位於同一台 VPS,因此無法在 VPS 故障時保留。請排程將 /srv/navidrome 推送到另一台機器或 object storage;這正是 restic 與 BorgBackup 適合處理的工作。整個目錄很小,通常遠低於 1 GB,因此每天建立一份加密的異機副本,成本幾乎可忽略,卻能保留重新掃描無法恢復的所有資料。
FAQ
我需要在 VPS 上轉碼音樂嗎?
幾乎不需要。手機和瀏覽器都能自行解碼 MP3、AAC、Opus 和 FLAC,因此伺服器只需原樣傳送檔案,幾乎不會使用 CPU。只有一種情況值得啟用:透過行動數據串流 FLAC 音樂庫時,將約 900 kbps 轉換為 128 kbps 的 Opus,可讓數據用量降低約 7 倍。Navidrome 可針對個別使用者和播放器設定此功能,而且在你啟用前會維持關閉。
為什麼手機應用程式無法下載音樂供離線聆聽?
因為離線儲存是用戶端功能,不是伺服器功能。Subsonic API 允許任何用戶端取得完整檔案,但是否將副本保留在手機上,取決於應用程式。請查看 navidrome.org/apps 的用戶端目錄,選擇描述中提到離線下載或快取功能的用戶端。有些用戶端只會快取你已播放的內容,這不同於在旅程前同步整張專輯。
為什麼掃描後,一張專輯被分成數張專輯?
因為曲目的專輯演出者標籤遺失,或各曲目之間的值不一致。Navidrome 依標籤而非資料夾分組,因此 12 首曲目若有 12 個不同的演出者值,且沒有共用的專輯演出者值,看起來就會是 12 張專輯。在專輯的每首曲目上設定專輯演出者標籤;合輯通常設為 Various Artists,然後讓 Navidrome 重新掃描。MusicBrainz Picard 或 beets 可以一次處理整個資料夾。
自架音樂串流服務能取代 Spotify 嗎?
它取代的是播放器和音樂庫,不是音樂目錄。你可以在每台裝置上使用自己的收藏,以及不會因授權變更而被收回的播放清單和播放次數。你不會取得新發行的音樂,也不會取得根據其他人聆聽習慣建立的推薦。多數架設這類服務的人會購買音樂,並保留價格低廉的串流帳號來探索新音樂。