云音乐服务的麻烦不是收费,而是歌单会灰、专辑会下架、歌词会消失。只要你有几百首已经归好类的本地音乐,一台常年开着的 Linux 主机就能把它们变成一个随时可访问的私人音乐服务。这篇文章记录的是 v0.64.2 这一版的实际做法:装起来、把封面头像歌词自动补齐、把歌词写回文件、再让手机和电脑都能连上。
流媒体平台是按授权曲库给你的,你的收藏随时可能从可播放变成灰色。本地文件不一样,它一直在你的硬盘上,缺的只是"从外部访问"这一层。Navidrome 做的就是这一层:它扫描目录里的音频文件,读标签建库,然后同时提供网页播放界面和 Subsonic/OpenSubsonic 兼容接口,于是几十个第三方客户端可以直接连上来。它自己不修改你的音频文件,只读不写,除了插件要写的那部分。
代价也很清楚:你要自己管一台机器、自己负责备份和外部访问安全,中文歌曲的封面、歌手头像和歌词不会自动出现,需要额外补。后面几节大半篇幅都花在这"额外补"上,因为这恰恰是体验差距最大的地方。
从 https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz 下载ffmpeg音频解码库,解压到某个目录,并加到环境变量PATH。
第一件事是把版本固定下来。v0.64.2 发布于 2026 年 9 月 24 日,linux amd64 的压缩包约 24.7 MB,解压后是一个约 73 MB 的静态二进制,外加 README 和 LICENSE。二进制是自包含的,不需要系统里预装 Go 或任何动态库。
如果你的网络到 GitHub 很慢甚至超时,可以在链接前面加一层代理前缀,比如 https://gh-proxy.com/ 直接拼在原始 URL 之前,实测能拿到同样的文件。这一步在国内是常态,不必怀疑版本选错了。
目录规划比想象中重要,因为后面插件要往音乐目录里写文件。建议把两个目录分开:二进制和数据库放 ~/tools/navidrome_0.64.2,音乐库单独放 ~/Music。运行 Navidrome 的用户必须对音乐目录和数据目录都有写权限,否则插件能启用、日志里也不报错,但封面和歌词永远不会出现。
同目录下新建 navidrome.toml:
这里有一处很容易摔的坑。插件作者在 README 里给的是环境变量写法,AGENTS、PLUGINS_ENABLED、PLUGINS_FOLDER、PLUGINS_AUTORELOAD、PLUGINS_LOGLEVEL、PLUGINS_CACHESIZE 一路抄进 toml,看起来很像配置文件,其实 Navidrome 只认前两个。实测在 0.64.2 上启动会逐条打印:
规律是:顶层键大小写不敏感,AGENTS 和 Agents 等价;但带层级的分组键必须写成 TOML 的表,PLUGINS_ENABLED 要写成 [Plugins] 段里的 Enabled,用下划线连接的分组键一律不认。改成表写法之后这些 warning 全部消失。至于 PLUGINS_FOLDER 被忽略为什么没让插件失效,是因为 Plugins.Enabled 本来就默认开着,Plugins.Folder 默认值 <DataFolder>/plugins 又恰好就是 ./plugins,两个默认值替你兜住了。
顺带说清数据库位置。官方选项表把 DataFolder 的默认值写的是 ./data,那是容器镜像里的路径;本地二进制实测取的是当前目录,启动日志里能看到 dbPath="navidrome.db?cache=shared&...journal_mode=WAL",数据库就是启动目录下的 navidrome.db。它开着 WAL,备份时 .db、.db-wal、.db-shm 三个文件要一起拷,或者干脆用官方的 Backup.Path 让它自己定时备份。
按你手上的启动命令,前台跑一条就够:
这条命令能起来,端口也确实监听 8002,但目录里不会出现 run.log。原因在于 -l 是 --loglevel 的短选项,不是 --logfile;run.log 被当成日志级别传进去,解析失败后回落到 info,日志全部打在终端上。实测:同一个目录下用这条命令跑完,ls 里没有 run.log;把配置改成 LogFile = "run.log" 再跑,文件立刻出现。想要日志文件,用配置项或者完整的 --logfile run.log,别用 -l。
浏览器打开 http://<主机>:8002,第一次访问会要求创建管理员账号,第一个注册的用户自动成为管理员,之后在设置里再给家里人开普通账号。到这一步音乐库会开始扫描,网页版已经能听歌了。
如果你希望它开机自启,Navidrome 自带一个服务安装子命令,Linux 上装的就是 systemd 单元:
macOS 走 launchd,Windows 走服务管理器,同一条命令按平台自动选。不喜欢它生成的单元文件,自己写一份 systemd 单元指向二进制和 -c 配置也一样。
中文歌的封面和歌词,Navidrome 自带的元数据源基本指望不上,这里用社区插件 Netease-navidrome-plugin。它的 0.0.9 版本发布于 2026 年 5 月 20 日,产物是一个 287788 字节的 netease.ndp,SHA-256 是 b55bc010df6cded8126270b201ebfe795e2f70dc8a284013a8f00ef8d4fcc361。
下载后把 netease.ndp 放进插件目录,也就是 <DataFolder>/plugins,默认情况下就是二进制旁边的 ./plugins:
插件 ID 直接取文件名去掉扩展名,所以 netease.ndp 的 ID 就是 netease,Agents = "netease,..." 里那个名字也是从这来的。放好之后,管理员登录网页,进插件页点一次 Rescan(配置里开了 AutoReload 就等它自己发现),然后启用。启用时别忘了授权:这个插件声明了 users 权限和带写入的 library 权限,需要给它访问用户和媒体库的写权限,否则它能加载但写不了文件。命令行等价的做法是 navidrome plugin rescan、navidrome plugin enable netease,再用 navidrome plugin edit netease --all-users --write-access 一次把权限给齐。
插件本身还有几个默认关闭的开关,在插件页里逐项打开:enable_write_lyrics、enable_write_cover_image、enable_write_artist_image 默认都是 false,也就是装好不配置的话什么都不会写。navidrome_user 填你自己的用户名用于解决权限问题;netease_cookie 要填网易云的 MUSIC_U,相似艺人和电台才拿得到数据,不填只是这部分功能缺失。
它的权限清单值得看一眼再决定要不要用:网络只允许访问 music.163.com、interface3.music.163.com、*.music.126.net、www.qobuz.com、static.qobuz.com,库权限是文件系统直写,另有 kvstore 用于缓存。从 0.64.0 起 Navidrome 会在连接打开时校验 IP,清单里只写域名的插件够不到内网和回环地址,这个插件不受影响(它只需要公网),但你要给插件配本地服务时就得在清单里写 IP 或 CIDR。
插件写出来的文件按作者约定的结构落盘,实测一致:
如果还开了全局歌手头像,媒体库根目录下会多出一个 artist/ 目录,里面按歌手名存 jpg,配合 ArtistArtPriority 才会在网页上显示。插件的触发时机按作者文档是这几种:还没被缓存过的刮削对象、播放曲目、scrobble 上报、打开专辑页、打开歌手页。打开专辑页看一眼歌词就有了,是这个插件最省心的用法。
插件写的是和被播放文件同名的 .lrc 文件,Navidrome 本来就能读它,默认歌词来源顺序里 .lrc 还排在 embedded 前面。既然如此为什么还要嵌入?因为 .lrc 只对认这个约定的播放器有效,歌词不跟着文件走:拷给别人、换一个不读同级 lrc 的播放器、离线听,它就不在了。写进标签之后文件是自包含的,.lrc 删掉也不影响。
直接让ai调用python的mutagen库写一个嵌入歌词的脚本即可。下面是一些经验可参考。
mp3 的处理是写入 ID3v2.4 的 USLT 帧,UTF-8 编码、语言码 eng、描述为空;不会写 ID3v2.3,因为那一版存不了 UTF-8 的帧文本。flac 走 Vorbis 注释,LYRICS 和 UNSYNCEDLYRICS 两个键都写。已经带了歌词的文件默认跳过,要重写加 --overwrite。默认还会更新文件的 mtime,因为播放器是按 mtime 判断要不要重新读标签的,保留旧时间戳的后果是它继续显示"无歌词"。
网页版本来就够用,但手机和桌面端体验更好。Navidrome 官网的 apps 页在抓取时列了 96 个客户端,口径写得很明白:任何支持 OpenSubsonic 的应用都能连。手机上 Android 有 Symfonium(收费,功能最全)、DSub、Ultrasonic、Tempo,iOS 有 substreamer、play:Sub、Amperfy;桌面端 Feishin、Sonixd、Supersonic 都是跨平台的,习惯用本地播放器的话 Strawberry 也能挂上来。连的时候填服务器地址 http://<主机>:8002 加上我自己开的账号密码就行,只有走反向代理才需要额外配 BaseUrl。
想让它在外面也能听,三条路。最省事的是内网穿透,frp、Tailscale、Cloudflare Tunnel 任选,把 8002 映射出去,客户端里直接填公网地址,跨公网记得套 HTTPS,部分客户端会拒绝明文连接。第二条是把整套东西直接部署到云主机上,这时要注意插件写入的那几个目录得交给运行用户,容器和群晖这类环境还要额外打开读写开关,否则表现就是插件启用了但目录里空空的。第三条其实不开端口也行:Navidrome 自带分享功能,把某张专辑或某个歌单生成一个链接发给朋友,比暴露整个服务安全得多。
自己家用的服务也别裸奔。端口直接对公网开放、不做任何限速和 HTTPS,等于把整个音乐库和账号体系摆出去。Navidrome 自己有一层登录失败限速,默认是同一 IP 每 20 秒 5 次,够挡掉常规的暴力尝试,但前面再套一层反向代理和证书仍然是值得的。