问题背景
最近捡了一个 1L 小主机, 目前装上了 Ubuntu 22.04, 打算把这个小东西当作家庭服务器用起来. 玩这个当然少不了搭建一套私有影音系统啦, 于是在网上找解决方案, 自然而然地搭起了一套 Jellyfin 环境, 然后就开始踩坑了:).
在了解了什么是刮削、怎么刮削、为什么要用刮削器之后很自然地就去看 TMM 这东西, 然后发现它新版 (v4) 收费 (不吐槽收费, 只是我觉得我没必要用, 而且我也不想为了规避收费就用老版). 再一个就是谁家服务器跑 GUI 呢? TMM 有 CLI 但好像是从 v4 才开始支持的? 具体没有细看, 最后想了想手动刮削还是太折腾. 那么能不能用 Jellyfin 自带的刮削器呢? 让它定期自动扫描自动刮削? 瞄了一眼 Jellyfin 的配置, 默认装的插件就有 IMDB、TVDB 等站点的元数据匹配功能, 只是由于懂得都懂的原因连不上这些 API 而已. 那么解决思路就很清晰了: 使用魔 (ke) 法 (xue), 给 Jellyfin 上代理 buff.
Jellyfin 配置代理
首先安装是通过 官方文档 进行的, 没有选择 docker 容器的方式进行安装, 而是直接安装在系统级作为一个 service:
Once installed, Jellyfin will be running as a service. Manage it with sudo systemctl {action} jellyfin.service or sudo service jellyfin {action}.
由于 Jellyfin 是不支持在管理页面的网络设置里直接配代理的, 根据 这个 issus 我们知道 Jellyfin 支持 http_proxy
和 https_proxy
这两个环境变量, 那解决思路就很清晰了:
- 获取一个代理服务器;
- 给 Jellyfin 配上这两个环境变量, 指向代理服务器的 [地址:端口] 就可以了.
代理服务器我用本机 (和 Jellyfin 进程运行在同一个系统上), 代理软件选的是 Clash, 端口: 12333.
系统级环境变量 (❌) ☹️
开发组在那个关于代理的 issue 是这么说的:
I think it can already be done by setting environment variables
http_proxy
andhttps_proxy
, at least on Linux. Not sure we need to add support for this in the server itself.
最开始我误解了这个答案, 以为直接提供系统级环境变量就可以了, 但是不管是修改 /etc/environment 还是 /etc/profile (/etc/profile.d), 亦或是修改 non-login shell 的 rc 配置文件 (如: /etc/bashrc), 配置对 Jellyfin 均无效, 但是它们都可以在对应的环境中生效 (login / non-login shell 环境都测试过, 没有问题), 测试方式就是直接 curl www.google.com
, 有回应即说明代理生效.
最后回过神来, Jellyfin 是由 systemd 管理的一个 service, systemd 环境变量的配置是不依赖任何外部环境的, 包括 /etc/environment、login / non-login shell 环境配置文件等. 那么就要换一个思路: 给 systemd service 单独设置环境变量.
Systemd 环境变量 (✔️) 😄
经过查阅资料, 我了解到 systemd 环境变量有两种类型:
- 适用于所有 services;
- 适用于单个 service.
配置所有的 services
适配于所有 services 的环境变量原理是修改 systemd 的配置文件: /etc/systemd/system.conf, 修改 DefaultEnvironment= 这一条目就可以为所有 services 指定默认的环境变量, 具体可以看这个 post, 我的原则是能不改配置文件就不改, 于是采取头疼医头, 脚疼医脚的策略, 单独配置 Jellyfin 这个 service.
单独配置某个 service
使用 systemctl edit {service}
即可编辑某个 service, 如:
sudo systemctl edit jellyfin.service
执行之后会看唤起编辑器 (我这里是 nano), 看到这样的显示:
### Editing /etc/systemd/system/jellyfin.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
### Lines below this comment will be discarded
按照注释的提示在两块注释之间写的内容会被保留下来, 本文只关注环境变量的配置, 其他配置的修改请自行查阅文档.
Environment 写法
很简单, 直接用赋值即可, 可以出现多个 Environment = , 例如:
[Service]
Environment = "http_proxy=127.0.0.1:12333"
Environment = "https_proxy=127.0.0.1:12333"
EnvironmentFile 写法
这种写法是指定一个外部文件作为环境变量的内容, 可以使 service 配置和环境变量配置解耦, 具体可以参阅一下 Jellyfin 的默认 service 配置, 它用的就是这种写法. 同理, 也可以出现多个 EnvironmentFile = , 比如我们写一个外部配置:
[Service]
EnvironmentFile = /etc/default/jellyfin_proxy.env
文件 /etc/default/jellyfin_proxy.env 内容如下:
http_proxy=127.0.0.1:12333
https_proxy=127.0.0.1:12333
效果和直接设定 Environment 是一样的.
最后我们要保存的内容就是:
### Editing /etc/systemd/system/jellyfin.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
Environment = "http_proxy=127.0.0.1:12333"
Environment = "https_proxy=127.0.0.1:12333"
### Lines below this comment will be discarded
或者是 (别忘了创建对应的外部配置文件):
### Editing /etc/systemd/system/jellyfin.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
EnvironmentFile = /etc/default/jellyfin_proxy.env
### Lines below this comment will be discarded
编辑 && 保存完成后, 我们让 systemd 重新载入一下它的守护进程, 并重启 Jellyfin service:
sudo systemctl daemon-reload && sudo systemctl restart jellyfin.service
结果验证
我们先通过 sudo systemctl status jellyfin.service
查看 service 状态, 得到以下输出:
● jellyfin.service - Jellyfin Media Server
Loaded: loaded (/lib/systemd/system/jellyfin.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/jellyfin.service.d
└─override.conf
Active: active (running) since Sun 2023-02-12 21:36:54 CST; 2min 6s ago
Main PID: 519127 (jellyfin)
Tasks: 15 (limit: 38223)
Memory: 81.9M
CPU: 6.216s
CGroup: /system.slice/jellyfin.service
└─519127 /usr/bin/jellyfin --webdir=/usr/share/jellyfin/web --restartpath=/usr/lib/jellyfin/restart.sh --ffmpeg=/usr/lib/jellyfin-ffmpeg/ffmpeg
可以看到输出这里的 Drop-In 部分包含了一个文件: /etc/systemd/system/jellyfin.service.d/override.conf, 这个文件实际上是我们刚刚编辑保存的, systemd 自动在它的管理路径里创建了这个文件, 以后我们可以直接对这个文件进行更改, 保存后也是一样先让 systemd 重新载入一下它的守护进程, 并重启对应的 service 即可以完成更改. 这个 Drop-In 的原理可以理解为运行时合入, 它会在 service 启动时将其默认的配置文件和 override.conf 动态合并并作为 service 运行时的新配置, 这样就可以在不改变 service 默认配置的情况下为 service 提供额外的配置. 我个人更喜欢这种方式而不是改变 systemd 的配置以此来让所有 services 拥有同样的默认环境, 因为它不用修改原来的配置文件, 在软件更新的时候 (无论是 systemd 还是 service 更新) 不用考虑上游的配置文件覆盖本地的问题.
双重验证: 对待问题应该要有刨根究底的态度, 我们到底解决了这个问题没有? 显示 Drop-In 就说明环境变量真的生效了么?
回答这两个问题我们可以直接查看 Jellyfin 对应进程的运行时环境变量, 使用如下命令:
cat /proc/519127/environ | tr '\0' '\n' | grep http
其中 519127 是我们刚才通过 systemd 获取到的 Jellyfin 进程的 PID, 输出如下:
http_proxy=127.0.0.1:12333
https_proxy=127.0.0.1:12333
这下我们就可以放心了, 环境变量设置成功, 经过后续测试 Jellyfin 元数据刮削就一切正常了.文章来源:https://www.toymoban.com/news/detail-454943.html
PS: Jellyfin 有个坑点, 至少对于我测试的两个地址: 一个是环回地址 (127.0.0.1), 一个是局域网地址 (192.168.68.198, 使用局域网的另一台设备做代理服务器) 来说, 设置环境变量时不能加上协议头 (http:// 或 https://), 否则就算设置成功也不会生效, 不清楚是不是 Jellyfin 的玄学 bug, 亦或者说是神奇 feature 😑. 所以上文写的都是没有加协议头的配置, 可以走代理并正常工作, 加了即使设置成功, 在 Jellyfin 里也无效 (然而在其他环境这两个环境变量的协议头是可加可不加的, 不影响).文章来源地址https://www.toymoban.com/news/detail-454943.html
References
- hoping settings to let the jellyfin getting metadata through proxy;
- why-doesnt-etc-environment-work-for-systemd-services;
- Systemd is not using environment from /etc/profile.d on CentOS 7;
- how-to-set-environment-variable-in-systemd-service;
- set-environment-variable-for-all-services-running-under-systemd.
到了这里,关于Ubuntu 22.04 为 Jellyfin 配置代理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!