一、初衷 / 背景
- 现在大多数音乐平台:
要充会员
音质一般,有损压缩普遍在 320k 或更低
- 无损音频体积大:
一首歌(FLAC / ALAC)约 20–30 MB
2 TB 空间大约可存 6 万首左右
- 歌曲会下架、版权乱七八糟:
平台说没就没了
想系统地保存自己的收藏,只能自己存。
目标:
- 用网盘(比如 Dropbox)当音乐仓库
- VPS 作为中枢:
挂载网盘
清洗、统一管理音乐文件
提供 Web/客户端播放接口
- 效果类似“自建 Spotify”,完全自己掌控库、音质、访问方式。
二、总体架构
1. 逻辑架构
云端存储(Dropbox / 其它网盘 / 本地磁盘)
↑
rclone mount → /mnt/dropbox (或其它挂载点)
↑
└── /mnt/dropbox/Music/library ← beets 清洗后得到的“干净音乐库”
↑
└── Docker 容器中的 /music
↑
└── Navidrome 扫描 /music,提供 Web / API 播放
如果你本地磁盘足够大,也可以跳过 rclone,直接用本地路径当 Music/library,整体逻辑不变。
三、基础环境与前提
1. 硬件与系统
- 一台 VPS / 服务器,示例配置(你目前实际用的是类似的):
CPU:4 vCPU
内存:16 GB
磁盘:200 GB NVMe
每月流量:16 TB
- 操作系统:
推荐:Debian / Ubuntu 系(本文命令以 Debian / Ubuntu 为例)
注意:宿主机需要支持 FUSE(大部分 KVM VPS 没问题,OpenVZ/LXC 有的会被云服务商阉割)。
2. 以 root 用户操作
为了少扯权限问题,本文默认所有命令都在 root 下执行:
# 如果你目前不是 root,可以先切换:
sudo -i
生产环境建议用普通用户 + sudo,这里为了“新手跟着抄就能跑”直接用 root。
3. 需要安装的软件
后面会一一展开,这里先整体列一下:
- rclone(挂载网盘)
- fuse3(FUSE 支持,让 rclone 能挂载)
- beets(音乐库管理)
- ffmpeg(给 beets 的 replaygain 等插件用)
- python3-pylast(beets 的 lastgenre 插件依赖)
- Docker + docker compose(跑 Navidrome)
四、部分一:挂载网盘(以 Dropbox + rclone 为例)
1. 安装 rclone
apt update
apt install -y rclone
确认安装成功:
rclone version
2. 配置 Dropbox 远程(remote)
执行:
rclone config
交互步骤:
- 输入
n→ 新建一个 remote - 起名(例):
dropbox_music - 选择存储类型:在列表中选择
Dropbox对应的编号(例如13,以实际界面为准) client_id/client_secret:
- 默认回车即可(不自建 app 的话)
Edit advanced config?→ 输入nUse auto config?:
- 有桌面浏览器在当前机器上 →
y - 纯 SSH 服务器(常见)→
n
无浏览器环境(VPS)下授权方法
在 VPS 上选择 Use auto config? = n 后,rclone 会提示你在另一台机器运行:
rclone authorize "dropbox"
操作步骤:
- 在你自己电脑上也安装 rclone
- 在“有浏览器”的那台电脑上执行:
rclone authorize "dropbox"
- 浏览器会打开 Dropbox 登录/授权页面,按提示完成
- 授权成功后,终端会输出一段 JSON,例如:
{"access_token":"xxxx","token_type":"bearer", ...}
- 把整段 JSON 复制粘贴回 VPS 上
rclone config的提示中,回车 - 在菜单中确认 remote
dropbox_music已存在 → 输入q退出
3. 测试 remote 是否可用
rclone lsd dropbox_music:
正常情况会列出 Dropbox 顶层目录,例如:
-1 2025-xx-xx xx:xx:xx Obsidian
-1 2025-xx-xx xx:xx:xx 文件
-1 2025-xx-xx xx:xx:xx 未归档
...
如果这里就报错,说明 Dropbox 授权 / 网络 / remote 名有问题,先修这个再往下走。
4. 安装 FUSE3(解决 fusermount3 报错)
如果直接 mount,会遇到类似错误:
Fatal error: failed to mount FUSE fs: fusermount: exec: "fusermount3": executable file not found in $PATH
原因:系统没装 FUSE3,rclone 找不到 fusermount3。
安装:
apt install -y fuse3
检查:
which fusermount3
有路径输出即可。
5. 创建挂载点
mkdir -p /mnt/dropbox
6. 创建 systemd 服务,开机自动挂载
新建服务文件:
nano /etc/systemd/system/rclone-dropbox.service
内容:
[Unit]
Description=Rclone Mount Dropbox (Music)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/rclone mount dropbox_music: /mnt/dropbox --dir-cache-time=72h --vfs-cache-mode=full --vfs-cache-max-size=50G --vfs-cache-max-age=336h --tpslimit=10 --buffer-size=16M --umask=000 --log-file=/var/log/rclone-dropbox.log --log-level=INFO
ExecStop=/bin/fusermount3 -u /mnt/dropbox
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
注意:
ExecStart必须是一行,systemd 不认\换行。- 如果你的
fusermount3不在/bin,用which fusermount3找到路径后改掉。
加载并启动服务:
systemctl daemon-reload
systemctl enable rclone-dropbox
systemctl start rclone-dropbox
systemctl status rclone-dropbox
7. 验证挂载是否成功
df -h | grep dropbox
ls /mnt/dropbox
如果可以看到 Dropbox 顶层目录,例如:
Obsidian docFile dysk mac project 应用 文件 未归档
说明挂载成功,此时对上层软件来说,/mnt/dropbox 就是一个“本地盘”。
五、部分二:规划音乐目录 & 使用 beets 清洗音乐库
1. 规划音乐目录结构
基于已挂载的 /mnt/dropbox,规划音乐相关目录:
mkdir -p /mnt/dropbox/Music/{incoming,library,trash}
mkdir -p /mnt/dropbox/Music/incoming/{albums,singles}
约定:
incoming/:新音乐临时区
incoming/albums:专辑(每个文件夹一张专辑)
incoming/singles:散单曲 / live / remix 等
library/:beets 整理好的正式音乐库(Navidrome 将指向这里)trash/:丢弃但暂不物理删除的文件(可选)
2. 安装 beets 及依赖
apt install -y beets ffmpeg python3-pylast
确认:
beet version
正常输出类似:
beets version 1.6.0
Python version 3.11.x
plugins: embedart, fetchart, lastgenre, lyrics, replaygain, scrub
如果之前没装 python3-pylast,会看到:
ModuleNotFoundError: No module named 'pylast',装上就好。
3. 配置 beets
创建配置文件:
mkdir -p /root/.config/beets
nano /root/.config/beets/config.yaml
推荐配置:
directory: /mnt/dropbox/Music/library
library: /root/.config/beets/music.db
import:
move: yes # 导入后移动文件到 library
copy: no
write: yes # 写回标签到音频文件
from_scratch: no
incremental: yes
quiet_fallback: asis
timid: no # 尽量少问,多自己决定
languages: zh en
paths:
default: $albumartist/$album%aunique{}/$track - $title
singleton: Singles/$artist/$title
comp: Compilations/$album%aunique{}/$track - $title
plugins:
- fetchart
- embedart
- lastgenre
- lyrics
- scrub
- replaygain
fetchart:
auto: yes
embedart:
auto: yes
lastgenre:
auto: yes
canonical: yes
lyrics:
auto: yes
replaygain:
backend: ffmpeg
4. 专辑导入(批量)
把专辑按“一个专辑一文件夹”的形式放到:
/mnt/dropbox/Music/incoming/albums/
BTS - Agust D - D-2 (2020)/
...
标准交互导入
beet import /mnt/dropbox/Music/incoming/albums
beets 会:
- 按目录分专辑
- 在线匹配(MusicBrainz)
- 对每张专辑给出候选:
典型交互示例(你实际遇到过的):
No matching release found for 10 tracks.
[S]kip, Use as-is, as Tracks, Group albums, Enter search, enter Id, aBort?
Enter search (e):自己输入搜索词(如Agust D D-2)- 匹配到后:
Artist: Agust D - D-2
Album: BTS
...
(A)pply, More candidates, Skip, Use as-is...
按 A 接受匹配。
导入完成后,目录会变成类似:
/mnt/dropbox/Music/library/Agust D/D-2/01 - 저 달.m4a
...
确认:
tree -L 3 /mnt/dropbox/Music/library | head -n 50
beet ls Agust D
更自动的导入(专辑一锅炖)
标签质量还可以、懒得每张确认时:
beet import -q -A /mnt/dropbox/Music/incoming/albums
-q:少说话-A:自动接受匹配
5. 单曲导入(singletons)
散单曲、Soundcloud 下载、非正式 live 等,建议全部放到:
/mnt/dropbox/Music/incoming/singles/
单曲导入命令(整目录):
beet import -s /mnt/dropbox/Music/incoming/singles
-s/--singletons:告诉 beets「这些是散曲,不要按专辑处理」
导入过程中:
- 匹配不到专辑时,常用选项 →
Use as-is - 最终路径会按
singleton规则生成,比如你现有的:
/mnt/dropbox/Music/library/Singles/NewJeans/Ditto.flac
/mnt/dropbox/Music/library/Singles/NewJeans/New Jeans.flac
/mnt/dropbox/Music/library/Singles/NewJeans/Super Shy.flac
单首导入示例:
beet import -s /mnt/dropbox/Music/incoming/singles/JENNIE_Live_2025_second_week.mp3
建议:导入前,用本地标签工具(mp3tag/kid3 等)至少补好 Artist 和 Title,避免出现类似
__/00 -.mp3 这种抽象命名(你已经见识过一次了)。
6. 导入后的日常操作流程
以后推荐日常习惯是:
- 下载/同步音乐 → 丢进 incoming:
- 专辑 →
incoming/albums/某专辑目录/ - 单曲 →
incoming/singles/
- 定期跑两条命令:
# 批量导入专辑
beet import -q -A /mnt/dropbox/Music/incoming/albums
# 导入单曲
beet import -s -q /mnt/dropbox/Music/incoming/singles
- 导入完后,
/mnt/dropbox/Music/library就是干净、可被 Navidrome 直接使用的音乐库。
六、部分三:Docker 方式部署 Navidrome
1. 安装 Docker & docker compose 插件(Debian/Ubuntu 示例)
apt install -y docker.io docker-compose-plugin
systemctl enable docker
systemctl start docker
确认:
docker version
docker compose version
2. 准备 Navidrome 目录与 docker-compose
创建目录:
mkdir -p /srv/navidrome
cd /srv/navidrome
mkdir -p /srv/navidrome/data
创建 docker-compose.yml:
nano /srv/navidrome/docker-compose.yml
内容:
version: "3.8"
services:
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
restart: unless-stopped
ports:
- "4533:4533"
environment:
ND_MUSICFOLDER: "/music"
ND_DATAFOLDER: "/data"
ND_ADDRESS: "0.0.0.0"
ND_PORT: "4533"
ND_LOGLEVEL: "info"
TZ: "Asia/Shanghai" # 或你自己的时区
volumes:
# beets 清洗后的音乐库(rclone 挂载的 Dropbox 目录)
- /mnt/dropbox/Music/library:/music:ro
# Navidrome 自己的数据
- /srv/navidrome/data:/data
注意:
MusicFolder映射的是 beets 整理后的库/music:ro只读挂载,避免 Navidrome 改你文件内容
3. 启动 Navidrome
cd /srv/navidrome
docker compose up -d
docker compose ps
浏览器访问:
http://你的VPSIP:4533/
第一次打开会让你创建管理员账号,按照页面提示完成。
Navidrome 会自动扫描 /music,即 /mnt/dropbox/Music/library,
此时你应该能看到:
Agust D / D-2JENNIE / Live 2025 second weekSingles / NewJeans / Ditto ...
这些都已经在你的库里出现。
前提:rclone 的挂载服务已启动,即 /mnt/dropbox 已经挂好。
如果 Navidrome 启动时 /mnt/dropbox 是空的,它就只会扫描空气。
七、使用 Navidrome 客户端
1. Web 端
- 直接浏览器访问:
http://你的VPSIP:4533/ - 或将 Navidrome 放在 Nginx/Caddy 反代后,用
https://music.你的域名/
Web 界面支持:
- 按专辑 / 艺人 / 歌曲浏览
- 搜索
- 歌单
- 随机播放等
2. 其他客户端(手机/桌面)
Navidrome 兼容 Subsonic API,可以用很多第三方客户端,例如:
- 桌面:Feishin(跨平台)
- Android:Substreamer / Symfonium / Ultrasonic
- iOS:iSub 等(具体按你喜好选)
一般配置方式:
- 服务器地址:
http://你的VPSIP:4533或https://你的域名 - 用户名 / 密码:Navidrome 中创建的账号
- 协议类型:Subsonic/Navidrome(视客户端选项)
八、常见坑与踩坑记录(你实际遇到过的)
1. fusermount3 找不到,rclone 挂载失败
报错:
Fatal error: failed to mount FUSE fs: fusermount: exec: "fusermount3": executable file not found in $PATH
解决:
apt install -y fuse3
然后重启 rclone-dropbox 服务。
2. /etc/fuse.conf 不存在
你一开始用了:
sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
结果系统回答:
sed: can't read /etc/fuse.conf: No such file or directory
原因:很多系统默认没有这个文件。
在你当前方案中:
- 使用 root 运行 rclone
- 没用
--allow-other
所以可以完全忽略 fuse.conf。
若未来要用 --allow-other,手动创建 /etc/fuse.conf 并写入:
user_allow_other
即可。
3. systemd 里的 ExecStart 写成多行,挂载一直失败但服务显示 running
你一开始写成:
ExecStart=/usr/bin/rclone mount dropbox_music: /mnt/dropbox \
--dir-cache-time=72h \
...
systemd 不会像 shell 那样识别反斜杠换行,结果 rclone 收到一堆乱七八糟的参数,挂载失败但服务状态还是 active。
解决:
把 ExecStart 改成完整的一行:
ExecStart=/usr/bin/rclone mount dropbox_music: /mnt/dropbox --dir-cache-time=72h --vfs-cache-mode=full --vfs-cache-max-size=50G --vfs-cache-max-age=336h --tpslimit=10 --buffer-size=16M --umask=000 --log-file=/var/log/rclone-dropbox.log --log-level=INFO
然后:
systemctl daemon-reload
systemctl restart rclone-dropbox
4. beets 插件 lastgenre 报 pylast 缺失
报错:
** error loading plugin lastgenre:
ModuleNotFoundError: No module named 'pylast'
解决:
apt install -y python3-pylast
# 或 pip install pylast
然后再 beet version 验证插件加载正常。
5. beets 导入时出现 __/00 -.mp3 这种奇怪路径
你遇到的例子:
/mnt/dropbox/Music/library/__/00 -.mp3
原因:
- 文件本身几乎没有标签(artist/album/title 为空)
- beets 按
paths.default规则尝试拼路径 - 空字符串被降级成
__/00/-之类占位
解决办法:
- 导入前用标签工具至少补上 artist/title,或者
- 导入后用 beets 修改:
beet modify path:/mnt/dropbox/Music/library/__/00\ -.mp3 artist=JENNIE albumartist=JENNIE album="Live 2025" title="Live 2025 second week" track=1
beet move path:/mnt/dropbox/Music/library/__/00\ -.mp3
这样文件就会被重新移动到正常路径下。
6. SoundCloud / 非官方来源的专辑/单曲匹配不上
你遇到 BTS - Agust D - D-2 (2020) 这样的目录,来自 SoundCloud。
beets 提示:
No matching release found for 10 tracks.
[S]kip, Use as-is, as Tracks, Group albums, Enter search, enter Id, aBort?
正确姿势就是:
- 按
e(Enter search),输入Agust D D-2 - 选中正确的 MusicBrainz release
- 按
A(Apply)接受匹配
最终得到的就是现在这样:
Agust D/D-2/01 - 저 달.m4a
...
九、总结:整条链路的日常使用流程
- 网盘挂载
- rclone + fuse3 →
/mnt/dropbox - systemd 管理,开机自动挂载
- 音乐放入
- 专辑:
/mnt/dropbox/Music/incoming/albums/... - 单曲:
/mnt/dropbox/Music/incoming/singles/...
- beets 清洗
# 专辑批量导入
beet import -q -A /mnt/dropbox/Music/incoming/albums
# 单曲导入
beet import -s -q /mnt/dropbox/Music/incoming/singles
- Navidrome 播放
- Docker 映射
/mnt/dropbox/Music/library:/music:ro - 浏览器 / 客户端访问 Navidrome
- 长远维护
- 偶尔查看:
/var/log/rclone-dropbox.log(挂载情况)
docker compose logs navidrome(播放服务情况)
- 如需升级:
rclone / beets 用 apt 升级
Navidrome:
cd /srv/navidrome
docker compose pull
docker compose up -d
这份文档已经把你一路折腾过的东西、所有关键命令和坑基本都装进去了,一个“什么都不懂的新手”只要照着从上往下抄,正常是能搭起来一套跟你现在一样的环境的。
你后面要再补「安全 / HTTPS / 反代」之类的章节,可以在这个基础上继续加一节“对外发布与安全加固”。
评论区