7.9 KiB
NAS(群晖+飞牛)MoviePilot/TMM TMDB刮削 终极稳定技术方案
一、问题背景与核心故障根源
1.1 设备环境差异
-
群晖NAS:Mihomo代理正常、Hysteria2节点正常、UDP链路通畅、全局代理生效,MoviePilot/TMM刮削全部正常。
-
飞牛fnOS:无系统全局代理、OVS虚拟交换机拦截UDP、Hysteria2(QUIC/UDP)链路大面积失效,导致所有TMDB API请求超时/握手失败,媒体刮削完全不可用。
1.2 核心技术故障定论
本次故障不是节点、密钥、TLS版本、DNS污染问题,是环境硬限制:
-
TMDB CloudFront 强制仅支持 TLS1.3;
-
传统TCP隧道(Vmess/Vless/AnyTLS/Mieru)存在内层TLS1.3报文损坏缺陷;
-
唯一稳定的Hysteria2(QUIC/UDP)协议,被飞牛fnOS OVS/路由器UDP拦截;
-
飞牛Docker容器不会自动继承宿主机代理,裸网访问TMDB必然失败。
结论:飞牛无法本地稳定运行HY2代理,放弃飞牛本地代理,采用「双方案冗余架构」解决刮削问题。
二、整体架构设计(双冗余方案)
主方案(长期日常使用):飞牛容器复用群晖Mihomo代理(全接口覆盖)
备方案(断代理兜底):Cloudflare Worker带鉴权+缓存TMDB中转(无需任何代理、纯裸网可用)
两套方案可随时切换,彻底解决飞牛TMDB刮削不稳定问题。
三、主方案:飞牛复用群晖Mihomo代理(推荐默认启用)
3.1 前置必备条件(必须配置)
群晖Mihomo config.yaml 核心配置(允许局域网访问):
mixed-port: 7890
allow-lan: true
listen-address: 0.0.0.0
ipv6: false
群晖防火墙放行 7890端口,飞牛与群晖处于同一局域网、无跨VLAN隔离。
3.2 MoviePilot 完整部署配置
飞牛docker-compose.yml,直接复用群晖SOCKS5代理,自动解决TMDB/Github/豆瓣全部外网请求。
version: "3.8"
services:
moviepilot:
image: jxxghp/moviepilot:latest
container_name: moviepilot
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- /volume1/moviepilot:/app/config
environment:
- TZ=Asia/Shanghai
# 核心代理配置:远端解析域名,规避DNS污染
- PROXY_HOST=socks5h://192.168.1.100:7890
# Github加速,解决插件/资源下载失败
- GITHUB_PROXY=https://mirror.ghproxy.com/
network_mode: bridge
⚠️ 替换:192.168.1.100 为你的群晖真实内网IP,目录按需修改。
3.3 MoviePilot 网页端配置
-
无需修改TMDB接口地址,保持官方默认
-
PROXY_HOST已由环境变量注入,无需重复填写
-
正常填写TMDB API Key即可
3.4 TinyMediaManager(TMM) 部署配置
version: "3.8"
services:
tinymediamanager:
image: tinymediamanager/tinymediamanager:latest
container_name: tinymediamanager
restart: unless-stopped
ports:
- "4000:4000"
volumes:
- /volume1/tmm:/config
environment:
- TZ=Asia/Shanghai
- ALL_PROXY=socks5h://192.168.1.100:7890
- NO_PROXY=127.0.0.1,localhost,192.168.0.0/16
network_mode: bridge
3.5 TMM 网页端代理配置(优先推荐)
-
Proxy type: SOCKS5
-
Host: 群晖内网IP
-
Port: 7890
-
开启:Resolve hostnames remotely(远端域名解析,等价socks5h)
3.6 连通性验证命令(飞牛SSH执行)
docker exec -it moviepilot curl -v --socks5-hostname 192.168.1.100:7890 https://api.themoviedb.org/3/movie/550?api_key=你的TMDB密钥
返回JSON即为代理通路正常。
四、备方案:CF Worker 鉴权+缓存 TMDB 中转(无代理兜底)
适用场景:群晖关机、代理节点故障、飞牛UDP彻底不通,零代理依赖完成TMDB刮削。
核心优势:TCP链路传输、不受UDP/OVS限制、带密码防盗刷、自带缓存提速、节省TMDB/CF额度。
4.1 主中转Worker代码(鉴权+缓存)
新建Worker,清空默认代码,粘贴如下完整版:
export default {
async fetch(request, env) {
// 自定义你的访问密钥
const ACCESS_SECRET = "自定义随机密钥";
// 缓存有效期1小时,可改为600(10分钟)/86400(24小时)
const CACHE_TTL = 3600;
const auth = request.headers.get("X-Tmdb-Secret");
if (!auth || auth !== ACCESS_SECRET) {
return new Response("Access Denied", { status: 403 });
}
const targetHost = "api.themoviedb.org";
const url = new URL(request.url);
url.hostname = targetHost;
const newReq = new Request(url, request);
newReq.headers.set("Host", targetHost);
// GET请求缓存加速
if (request.method === "GET") {
const cacheKey = new Request(newReq.url, newReq);
const cache = caches.default;
let response = await cache.match(cacheKey);
if (!response) {
response = await fetch(newReq);
response = new Response(response.body, response);
response.headers.set("Cache-Control", `s-maxage=${CACHE_TTL}`);
await cache.put(cacheKey, response.clone());
}
return response;
}
return await fetch(newReq);
}
}
4.2 缓存清理方案(三种方式)
方式1:临时绕过缓存(单影片刷新,最简单)
链接后追加参数:&_nocache=随机数字
方式2:全局一键清缓存(批量重刷库)
修改任意一行Worker代码并重新部署,CF边缘节点缓存全部自动清空。
方式3:精准单条缓存删除(进阶)
单独部署purge清理Worker,支持指定路径删除缓存(文档末尾附代码)。
4.3 MoviePilot 切换Worker配置
-
清空 PROXY_HOST(关闭代理)
-
TMDB API地址:
https://你的worker域名.workers.dev/3 -
自定义请求头新增:
X-Tmdb-Secret: 你的自定义密钥 -
保留原有TMDB Key
4.4 TMM 切换Worker配置
-
TMDB API URL 替换为Worker地址
-
Custom HTTP Headers 添加
X-Tmdb-Secret: 你的密钥 -
关闭软件内代理设置
4.5 缓存清理Purge Worker代码(精准删除单条缓存)
export default {
async fetch(request, env) {
const ACCESS_SECRET = "和主Worker一致的密钥";
const auth = request.headers.get("X-Tmdb-Secret");
if (!auth || auth !== ACCESS_SECRET) {
return new Response("Access Denied", { status: 403 });
}
const url = new URL(request.url);
const targetPath = url.searchParams.get("path");
if (!targetPath) {
return new Response("Missing ?path=/3/movie/550", { status: 400 });
}
const cacheUrl = new URL(`https://你的主worker域名.workers.dev${targetPath}`);
const cacheReq = new Request(cacheUrl);
const cache = caches.default;
await cache.delete(cacheReq);
return new Response(`Purged: ${cacheUrl.toString()}`);
}
}
五、两套方案取舍标准
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 群晖代理复用(主) | 日常长期使用、群晖开机 | 全覆盖(TMDB/Github/豆瓣)、无额度限制、速度稳定 | 依赖群晖在线 |
| CF Worker中转(备) | 群晖关机、代理故障、UDP拦截 | 零代理依赖、抗网络污染、自带缓存加速 | 仅覆盖TMDB、有每日免费额度 |
六、通用排坑清单(飞牛专属)
-
禁止使用127.0.0.1:容器内回环地址指向自身,必须填写群晖内网IP
-
必须开启allow-lan: true:群晖Mihomo禁止仅监听127.0.0.1
-
飞牛关闭IPv6:规避隧道TLS1.3握手异常
-
放弃飞牛本地HY2:fnOS OVS+路由器UDP拦截为硬故障,无法修复
-
优先软件内置代理:MoviePilot/TMM原生代理优于系统环境变量代理
七、最终落地规范
-
日常默认:群晖Mihomo代理复用方案
-
故障兜底:CF Worker鉴权缓存中转方案
-
永久废弃:飞牛本地Hysteria2代理、TCP隧道(AnyTLS/Mieru/Vmess)
(注:部分内容可能由 AI 生成)