【OpenList + rclone + Jellyfin】Jellyfin播放天翼云盘影音

教程综述与架构

本教程旨在指导您在一个 eMMC + SSD 的设备上,从一个纯净的 Armbian 系统开始,搭建一套以 1Panel 为管理核心,以天翼云盘为存储后端,以 Jellyfin 为播放前端的、稳定可靠的家庭影音中心。

  • Part 1: 搭建一个系统与数据分离、配置优化的 Armbian + 1Panel 基础环境。
  • Part 2: 在此基础上,部署 OpenList + rclone + Jellyfin 服务栈,并提供全自动手动启动两种模式供您选择。

Part 1:搭建 Armbian + 1Panel 基础环境

第一阶段:系统与硬盘准备

  1. 系统更新与工具安装
    • 通过 SSH 登录您的 Armbian 系统。
ssh root@你的设备IP

更新系统并安装必要工具。

apt update && apt upgrade -y
apt install -y fdisk parted htop ncdu curl

配置 SSD 数据盘

  • 【警告】此步骤会清空您的 SSD,请确保没有重要数据。
# 1. 识别您的 SSD 盘符 (通常是 /dev/sda)
fdisk -l

# 2. 创建 GPT 分区表并新建一个占满全盘的分区
#    请将下面的 /dev/sda 替换为您的实际盘符
parted /dev/sda mklabel gpt
parted /dev/sda mkpart primary ext4 1MiB 100%

# 3. 格式化新分区 (注意分区名末尾有数字 "1")
mkfs.ext4 /dev/sda1

# 4. 获取新分区的 UUID (复制 UUID="xxxx-..." 引号内的值)
blkid /dev/sda1

# 5. 编辑 fstab 配置文件以实现开机自动挂载
nano /etc/fstab

在文件末尾添加新的一行 (将 UUID 替换为您复制的实际值):

# Mount SSD Data Disk
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /mnt/mydisk ext4 defaults,nofail 0 2

保存并退出 (Ctrl + X -> Y -> Enter)。

挂载并创建基础目录

# 创建挂载点目录
mkdir -p /mnt/mydisk

# 应用 fstab 配置并检查挂载是否成功
mount -a
df -h | grep mydisk
# 预期应能看到 /dev/sda1 挂载到了 /mnt/mydisk

# 在 SSD 上创建我们规划好的基础目录
mkdir -p /mnt/mydisk/docker
mkdir -p /mnt/mydisk/opt

第二阶段:安装 Docker 与 1Panel (数据分离)

  1. 安装并配置 Docker
# 1. 使用官方脚本安装 Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# 2. 使用 cat 命令精确写入 Docker 配置文件,将其数据目录指向 SSD
cat <<EOF > /etc/docker/daemon.json
{
  "data-root": "/mnt/mydisk/docker"
}
EOF

# 3. 重启 Docker 使配置生效并设置为开机自启
systemctl restart docker
systemctl enable docker

# 4. 验证数据目录是否已更改
docker info | grep "Docker Root Dir"
# 预期应输出 Docker Root Dir: /mnt/mydisk/docker

5.安装 1Panel 并将其程序目录链接到 SSD

# 1. 将系统默认的 /opt 目录内容移动到 SSD,然后创建符号链接
#    这个操作确保了 1Panel 本体会被安装到 SSD 上
mv /opt/* /mnt/mydisk/opt/
rmdir /opt
ln -s /mnt/mydisk/opt /opt

# 2. 执行 1Panel 安装脚本
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && bash quick_start.sh

【重要】 安装完成后,请务必妥善保存最后输出的 1Panel 访问地址、用户名和密码

Part 2:部署 Jellyfin 媒体中心服务栈

第三阶段:宿主机环境准备

  1. 在 SSD 上创建项目目录并设置权限
# 1. 创建所有需要的目录
sudo mkdir -p /mnt/mydisk/appdata/openlist
sudo mkdir -p /mnt/mydisk/appdata/jellyfin/config
sudo mkdir -p /mnt/mydisk/appdata/jellyfin/cache
sudo mkdir -p /mnt/mydisk/appdata/rclone/config
sudo mkdir -p /mnt/mydisk/appdata/rclone/cache
sudo mkdir -p /mnt/mydisk/cloud_mount

# 2. 设置宽松权限,避免 Docker 容器因 PUID/PGID 问题无法写入
sudo chmod -R 777 /mnt/mydisk/appdata

7、安装 rclone

sudo apt install -y rclone

第四阶段:部署核心服务

  1. 部署 OpenList
    • 登录 1Panel,进入 应用 -> 创建应用 -> Compose
    • 名称: openlist
    • 内容: 粘贴以下代码:
version: '3.8'
services:
  openlist:
    image: openlistteam/openlist:latest
    container_name: openlist
    restart: unless-stopped
    ports:
      - "5244:5244"
    volumes:
      - /mnt/mydisk/appdata/openlist:/opt/openlist/data

点击 确认 部署。部署成功后,访问 http://<您的IP>:5244,登录您的天翼云盘,并记下 WebDAV 的用户名和密码

9、配置 rclone 并迁移配置

# 1. 运行交互式配置
rclone config
# 按提示创建名为 tianyi-webdav 的 webdav remote
# URL 填 http://127.0.0.1:5244/,并填入上一步记下的用户名和密码

# 2. 将生成的配置文件移动到 SSD
sudo mv /root/.config/rclone/rclone.conf /mnt/mydisk/appdata/rclone/config/

10.创建 rclone 智能挂载服务

  • 执行以下命令块,创建一个能等待 OpenList 就绪的 systemd 服务。
sudo tee /etc/systemd/system/rclone-mount.service > /dev/null <<'EOF'
[Unit]
Description=Rclone Mount for Tianyi WebDAV (waits for OpenList)
Requires=docker.service
After=network-online.target docker.service
[Service]
Type=simple
User=root
Group=root
ExecStartPre=/bin/sh -c 'echo "Waiting for OpenList WebDAV..."; for i in $(seq 1 60); do if curl -sS --fail http://127.0.0.1:5244/ >/dev/null 2>&1; then echo "OpenList is ready!"; exit 0; fi; echo "Attempt $i/60..."; sleep 2; done; echo "OpenList did not become ready in time!"; exit 1'
ExecStart=/usr/bin/rclone mount "tianyi-webdav:/天翼云盘" /mnt/mydisk/cloud_mount --config=/mnt/mydisk/appdata/rclone/config/rclone.conf --cache-dir=/mnt/mydisk/appdata/rclone/cache --log-file=/mnt/mydisk/appdata/rclone/rclone.log --log-level=INFO --allow-other --uid=1000 --gid=1000 --dir-cache-time=48h --vfs-cache-mode=writes --vfs-cache-max-size=30G
ExecStop=/bin/fusermount -uz /mnt/mydisk/cloud_mount
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF

启动并验证服务:

sudo systemctl daemon-reload
sudo systemctl enable --now rclone-mount
sudo systemctl status rclone-mount # 确认 active (running)

第五阶段:部署 Jellyfin (二选一)

现在,请根据您的偏好,从以下两个方案中选择一个来部署 Jellyfin。


方案A:全自动版 (推荐)

  • 优点:一劳永逸,系统重启后所有服务会自动、按顺序可靠恢复,无需人工干预。
  • 部署:在 1Panel 中创建名为 jellyfin-stack 的 Compose 应用,粘贴以下内容:
version: "3.8"
services:
  wait-for-mount:
    image: busybox
    container_name: wait-for-mount
    restart: "no"
    command: |
      /bin/sh -c '
      echo ">>> [Phase 1] Waiting for mount point directory /media/cloud to exist...";
      while ! [ -d /media/cloud ]; do sleep 2; done;
      echo ">>> [Phase 2] Mount point exists. Giving rclone 5 seconds to stabilize...";
      sleep 5;
      echo ">>> [Phase 3] Starting deep readability test...";
      TEST_DIR="/media/cloud";
      if [ -d "/media/cloud/电影" ]; then
        TEST_DIR="/media/cloud/电影";
      fi;
      until ls -la "$TEST_DIR" > /dev/null 2>&1; do
        echo "Mount point is not fully readable yet, retrying...";
        sleep 3;
      done;
      echo ">>> [SUCCESS] Mount point is fully readable. Jellyfin can now start.";
      '
    volumes:
      - type: bind
        source: /mnt/mydisk/cloud_mount
        target: /media/cloud
        read_only: true
        bind:
          propagation: rslave
    healthcheck:
      test: ["CMD-SHELL", "ls -la /media/cloud >/dev/null 2>&1"]
      interval: 5s
      timeout: 3s
      retries: 10
  jellyfin:
    image: nyanmisaka/jellyfin:latest-rockchip
    container_name: jellyfin
    restart: unless-stopped
    depends_on:
      wait-for-mount:
        condition: service_healthy
    ports:
      - "8096:8096"
    volumes:
      - /mnt/mydisk/appdata/jellyfin/config:/config
      - /mnt/mydisk/appdata/jellyfin/cache:/cache
      - type: bind
        source: /mnt/mydisk/cloud_mount
        target: /media/cloud
        read_only: true
        bind:
          propagation: rslave
    privileged: true
    devices:
      - /dev/dri:/dev/dri
      - /dev/dma_heap:/dev/dma_heap
      - /dev/mali0:/dev/mali0
      - /dev/rga:/dev/rga
      - /dev/mpp_service:/dev/mpp_service
      - /dev/iep:/dev/iep
      - /dev/mpp-service:/dev/mpp-service
      - /dev/vpu_service:/dev/vpu_service
      - /dev/vpu-service:/dev/vpu-service
      - /dev/hevc_service:/dev/hevc_service
      - /dev/hevc-service:/dev/hevc-service
      - /dev/rkvdec:/dev/rkvdec
      - /dev/rkvenc:/dev/rkvenc
      - /dev/vepu:/dev/vepu
      - /dev/h25e:/dev/h265e

方案B:手动启动版

  • 优点:配置简单。缺点:每次系统重启后,都需要您手动登录 1Panel 启动 Jellyfin。
  • 部署:在 1Panel 中创建名为 jellyfin-stack 的 Compose 应用,粘贴以下内容:
version: "3.8"
services:
  jellyfin:
    image: nyanmisaka/jellyfin:latest-rockchip
    container_name: jellyfin
    restart: "no"
    ports:
      - "8096:8096"
    volumes:
      - /mnt/mydisk/appdata/jellyfin/config:/config
      - /mnt/mydisk/appdata/jellyfin/cache:/cache
      - type: bind
        source: /mnt/mydisk/cloud_mount
        target: /media/cloud
        read_only: true
        bind:
          propagation: rslave
    privileged: true
    devices:
      - /dev/dri:/dev/dri
      - /dev/dma_heap:/dev/dma_heap
      - /dev/mali0:/dev/mali0
      - /dev/rga:/dev/rga
      - /dev/mpp_service:/dev/mpp_service
      - /dev/iep:/dev/iep
      - /dev/mpp-service:/dev/mpp-service
      - /dev/vpu_service:/dev/vpu_service
      - /dev/vpu-service:/dev/vpu-service
      - /dev/hevc_service:/dev/hevc_service
      - /dev/hevc-service:/dev/hevc-service
      - /dev/rkvdec:/dev/rkvdec
      - /dev/rkvenc:/dev/rkvenc
      - /dev/vepu:/dev/vepu
      - /dev/h265e:/dev/h265e

Part 3:收尾与日常维护

  1. 配置 Jellyfin 媒体库
    • 访问 http://<您的IP>:8096,完成初始化设置。
    • 添加媒体库时,文件夹路径请选择 /media/cloud
  2. 终极重启测试
    • 在 SSH 终端执行 sudo reboot
    • 等待 2-3 分钟后,根据您选择的方案进行验证:
      • 全自动版:直接访问 Jellyfin 网页,应可正常使用。
      • 手动版:SSH 登录后用 ls -l /mnt/mydisk/cloud_mount 检查挂载,然后去 1Panel 手动启动 jellyfin-stack
  3. 日常更新媒体库流程
    1. 上传新文件到天翼云盘。
    2. 执行 SSH 命令刷新 rclone 缓存:sudo systemctl kill -s SIGHUP rclone-mount.service
    3. 登录 Jellyfin,在 控制台 -> 媒体库 中手动触发 扫描媒体库
  4. 更方便的终极更新媒体库方法:在1panel面板中添加计划任务,用下面的代码,并停止脚本,以后上传电影后,只需在面板中点击计划任务执行即可。
#!/bin/bash

# ================= 配置区域 (请修改这里) =================
# --- 1. OpenList (Alist) 配置 ---
# OpenList 的访问地址 (本机通常是 127.0.0.1:5244)
OPENLIST_URL="http://127.0.0.1:5244"
# OpenList 的登录用户名
OPENLIST_USER="admin"
# 【必填】OpenList 的登录密码 (请在此处填入你的密码)
OPENLIST_PASS="你的OpenList密码"
# 刷新路径:设置为根目录,确保整个天翼云盘都能更新
OPENLIST_PATH="/天翼云盘"

# --- 2. Jellyfin 配置 ---
# (已填入你提供的 API Key)
JELLYFIN_API_KEY="在jelyfin中获取的apikey"
JELLYFIN_URL="http://127.0.0.1:8096"

# --- 3. Rclone 配置 ---
RCLONE_SERVICE="rclone-mount.service"
# =======================================================

echo "🚀 [第一步] 正在登录 OpenList 获取 Token..."
# 1. 登录 OpenList 获取鉴权 Token
LOGIN_RESP=$(curl -s -X POST "$OPENLIST_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"$OPENLIST_USER\", \"password\": \"$OPENLIST_PASS\"}")

# 提取 Token
TOKEN=$(echo "$LOGIN_RESP" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')

if [ -z "$TOKEN" ]; then
    echo "❌ OpenList 登录失败!请检查脚本里的用户名和密码。"
    exit 1
else
    echo "✅ OpenList 登录成功。"
fi

echo "🔄 [第二步] 正在通知 OpenList 强制刷新: $OPENLIST_PATH ..."
# 2. 调用 OpenList 接口强制刷新云端目录 (refresh: true)
REFRESH_RESP=$(curl -s -X POST "$OPENLIST_URL/api/fs/list" \
  -H "Authorization: $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"path\": \"$OPENLIST_PATH\", \"password\": \"\", \"page\": 1, \"per_page\": 1, \"refresh\": true}")

if [[ "$REFRESH_RESP" == *"\"code\":200"* ]]; then
    echo "✅ OpenList 刷新指令已发送!正在等待云端同步..."
else
    echo "⚠️ OpenList 刷新可能未生效,返回信息: $REFRESH_RESP"
fi

# 【关键等待 1】 OpenList 去连接天翼云盘需要时间
# 这里设置 5 秒,防止 Rclone 刷新时 OpenList 还没准备好新数据
echo "⏳ 等待 5 秒 (让 OpenList 拉取云端数据)..."
sleep 5

echo "🔄 [第三步] 正在平滑刷新 Rclone 缓存 (SIGHUP)..."
# 3. 发送平滑刷新信号 (不中断连接,但在后台重置目录结构)
sudo systemctl kill -s SIGHUP $RCLONE_SERVICE

if [ $? -eq 0 ]; then
    echo "✅ Rclone 缓存刷新信号已发送。"
else
    echo "❌ Rclone 服务未找到或发送失败!"
    exit 1
fi

# 【关键等待 2】 Rclone 清理本地缓存需要时间
# 这里设置 3 秒,防止 Jellyfin 扫描时读取到旧缓存
echo "⏳ 等待 3 秒 (让 Rclone 重置本地挂载点)..."
sleep 3

echo "🔍 [第四步] 正在命令 Jellyfin 扫描媒体库..."
# 4. 触发 Jellyfin 扫描
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${JELLYFIN_URL}/Library/Refresh?api_key=${JELLYFIN_API_KEY}")

if [ "$HTTP_CODE" -eq 204 ]; then
    echo "✅ 成功!Jellyfin 已开始后台扫描。"
    echo "🚀 全流程结束!新电影很快就会出现。"
else
    echo "❌ Jellyfin 触发失败,HTTP 状态码: $HTTP_CODE"
fi

至此,您的家庭影音中心已完美部署。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注