前言
最近总算是想要摆脱尴尬的听歌处境了。
自从网抑云百万版权倒了之后,下载到本地就变成了唯一的结果。下载的过程也花不了多少时间,下完之后直接就能听,没有任何版权损失的风险。中间试图转成过 QQ
,但果然还是被劝退了。
上述列举的都是本地音乐的好处,但如果本地音乐全是好处的话那自然也不会有云音乐的兴起。本地音乐的缺点也很明显,就是多设备同步。
设备一多,事情就开始不对劲了。你开始希望在什么地方都能听到你库存的音乐,但听的前提是你需要把音乐拷贝一份到对应的目标机器上;当你想要分享音乐时,你只能分享一个小至几 M
,大至百余兆的音乐文件;以及由于失去了云端的优势,播放记录、播放列表之类的功能也就难以实现与同步。这都是本地播放的劣势。
不知道又没有人说过,解决一切问题的终极手段就是 self-host
,音乐也不例外。在有前人
目标
为这个平台,我们定下了以下几个目标:
- 音乐文件全部存储在
Google Drive
上。 - 通过
rclone
挂载目录的形式使Airsonic
能够读取。 - 通过
docker
部署。
目标 1 的出现是因为服务器的硬盘大小不够,不足以支撑将全部文件存下;而目标 2 则是为实现目标 1 而选择的具体方案;至于目标 3,则是为了快速部署而提出的要求。
Google Drive 的实现方案
在目标 2 中,我们指出了计划的实现方案,即通过 rclone
挂载。但 rclone
直接挂载存在两个问题:
- 需要守护进程,这一点可以通过
systemd
简单解决。 - 迁移过程复杂,这一点有一部分恰好是上一点的解决方案带来的。
并且,由于我们提出了 docker
部署的目标,挂载在外部反而某种意义上使得整个程序过于分散。因此最后我们选择将 Google Drive
挂载为 docker
的 volume
。
docker-volume-rclone[2]
就是最终的目标了。我们利用这个 Plugin
运行 rclone mount
。
安装
安装的话只要通过 docker plugin
就可以完成了:
在安装完成后,我们需要配置 rclone
,这里直接把你的 rclone.conf
复制过来就可以了。我选择存放在 ~/.config/rclone/rclone.conf
。
Airsonic Advanced
在准备完音乐源之后,接下来就是本体的搭建了。我们选择的是 Airsonic Advanced[3]
,这是一个快速迭代的 Airsonic fork
,相比原版慢悠悠的开发基调能够更快地发现并解决问题
作者在 Readme
中给出了 docker
的部署方案,我们只要照着抄一份就行了(
部署
这里我采用了 docker-compose
进行部署,主要是因为需要挂载的 volume
数量有点多了……
在 environments
中可以看到 PUID
和 PGID
,可以修改成你想要的 UID
和 GID
;CONTEXT_PATH
是为反向代理不在根目录准备的,如在 /music
下,不能以 /
结尾。
airsonic
的最后是 healthcheck
,这部分主要是为防止 rclone
异常退出而准备的。当挂载目录无法访问,即 rclone
出现故障时,走正常 docker
错误流程就可以了。
最后是 volumes
。前三个 local
都没什么问题,最后的两个 airsonic
挂载盘的 args
需要加上 --allow-other
才能让 Airsonic
访问到。而为了使 allow-other
不报错,你还需要修改 /etc/fuse.conf
:
把 user_allow_other
的注释去掉,或者如果没有这一行的话,加上即可。
启动
最后就是启动的步骤了。如果你仔细观察了上面的 yaml
,你会发现 RCLONE_CONF_BASE64
这个变量。这是我们为了使用 docker-compose
需要准备的。但问题在于我们需要使用 sudo
执行 docker-compose
,因此最后我们需要通过 bash -c
执行脚本:
这里需要注意的是 RCLONE_CONF_BASE64=
的等号右边,需要用一对引号括住 base64
命令的执行结果,防止由于换行引起的问题。
反向代理
最后的最后就是反代了,这也是让外界能够访问这个服务的关键所在。我简单给一个 Caddy
的配置吧:
自己部署记得把上面的 tls self_signed
改成其他正常的 TLS
方案(
配置中的 transparent
是让 Airsonic
使用的,而 X-Forwarded-Proto
则是历史遗留,我也不清楚这样配置能不能让 Airsonic
强制走 https
。
下面的两行 header_upstream
则是为 WebSocket
准备的,使 Airsonic Advanced
的 WebSocket
同步能够正常使用。不难发现,这两行和 websocket
预设的效果是一样的[4]。
而最后的 CSP
则是强制 https
的关键,通过 CSP
策略强制浏览器升级不安全的请求。支持 CSP
的浏览器会在读到这个 header
后,会把页面中所有 http
请求都升级到 https
。
CSP
怎么办?这样的浏览器还有存在的必要吗(无慈悲)
结语
平台的搭建可以说是费了一番周折,主要可能是在平台选取这一方面耽误了太多的时间。Java
的 Airsonic
一开始并没有在我的考虑范围之内,因为我觉得我的服务器似乎顶不住它的占用。但经过一番尝试后,最终我还是用回了 Airsonic
。
Airsonic Advanced
的问题是什么呢?由于它是 Airsonic
的 fork
,因此不可能逃出 Airsonic
的局限框架之外。虽然它在 Airsonic
原版的基础上改进了很多,但有一些核心功能的缺失却是没有办法避免的,比如歌词。
不过事物的发展是不可能一蹴而就的。在目前的阶段,能有自行车就不错了,毕竟音乐本身才是重点,因此我将眼光更多地放在了音乐内容的整理上。我创建了一个共享盘专门用来让 Airsonic
挂载,并尝试对手头的音乐进行整理。
在我看来,问题最大的是 Artist
的标签。在设计之初他们就没有考虑到多艺术家的复杂之处。艺术家不仅能有多个,还应该有别名。因此计划的第一步就是将手头音乐的艺术家全部都整理成统一的格式:
如果你有愿加入音乐的整理,而且我也认识,可以在下面留言或者 TG/Twi
上 PM
我(
嘛,就是这样(