Ubuntu 22.04 为 Jellyfin 配置代理

问题背景

最近捡了一个 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_proxyhttps_proxy 这两个环境变量, 那解决思路就很清晰了:

  1. 获取一个代理服务器;
  2. 给 Jellyfin 配上这两个环境变量, 指向代理服务器的 [地址:端口] 就可以了.

代理服务器我用本机 (和 Jellyfin 进程运行在同一个系统上), 代理软件选的是 Clash, 端口: 12333.

系统级环境变量 (❌) ☹️

开发组在那个关于代理的 issue 是这么说的:

I think it can already be done by setting environment variables http_proxy and https_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 环境变量有两种类型:

  1. 适用于所有 services;
  2. 适用于单个 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 元数据刮削就一切正常了.

PS: Jellyfin 有个坑点, 至少对于我测试的两个地址: 一个是环回地址 (127.0.0.1), 一个是局域网地址 (192.168.68.198, 使用局域网的另一台设备做代理服务器) 来说, 设置环境变量时不能加上协议头 (http:// 或 https://), 否则就算设置成功也不会生效, 不清楚是不是 Jellyfin 的玄学 bug, 亦或者说是神奇 feature 😑. 所以上文写的都是没有加协议头的配置, 可以走代理并正常工作, 加了即使设置成功, 在 Jellyfin 里也无效 (然而在其他环境这两个环境变量的协议头是可加可不加的, 不影响).

References

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值