临时

Docker 安装 OpenList 最新稳定版 + PT 适用 qBittorrent + HTTPS 访问

0. 方案说明

本方案目标:

OpenList:
https://网址.com

OpenList 直连 HTTPS 端口,用于其他 VPS 中转:
https://网址.com:55246

qBittorrent WebUI:
https://qb.网址.com

OpenList 数据目录:
/html/网盘

qBittorrent 下载目录:
/html/网盘/qBittorrent

OpenList 中读取 qBittorrent 下载目录:
/网盘/qBittorrent

版本选择:

OpenList:openlistteam/openlist:v4.2.1
qBittorrent:lscr.io/linuxserver/qbittorrent:4.6.7-libtorrentv1

说明:

  • OpenList v4.1.0 之后的版本,不包含 v4.1.0,镜像默认已经不是 root 用户。
  • OpenList 镜像内置用户为 openlist,UID/GID 为 1001:1001
  • 本教程不使用 user: "0:0"
  • 推荐创建一个宿主机普通服务用户,并让 OpenList 与 qBittorrent 使用相同 UID/GID。
  • qBittorrent 不使用 latest,而是锁定 4.6.7-libtorrentv1,更适合 PT 长期稳定使用。
  • docker-compose.yml 中不使用冗余的 expose
  • acme 证书续期后,通过宿主机脚本自动检测证书变化,并 reload nginx、restart OpenList。

1. 最终目录结构

/opt/openlist/
  docker-compose.yml
  .env
  data/
  cert/

/opt/qbittorrent/
  docker-compose.yml
  .env
  config/

/html/网盘/
/html/网盘/qBittorrent/

/opt/nginx/conf.d/
  openlist.conf
  qbittorrent.conf

/usr/local/sbin/reload-cert-services.sh

2. 修改现有 nginx Docker 配置

你当前 nginx compose 中如果只有:

ports:
  - "80:80"

需要改成:

ports:
  - "80:80"
  - "443:443"

然后重启 nginx:

cd 你的nginx-compose目录
docker compose up -d

确认 nginx 网络存在:

docker network ls | grep nginx-net

如果不存在,需要先创建:

docker network create nginx-net

3. 创建宿主机普通服务用户

如果你已经有普通用户,例如 ubuntudebianmedia,可以直接用已有用户。

这里以创建 media 用户为例:

id media || useradd -m -s /usr/sbin/nologin media

查看 UID/GID:

id media

例如输出:

uid=1000(media) gid=1000(media) groups=1000(media)

记录 UID/GID:

APP_UID=$(id -u media)
APP_GID=$(id -g media)

echo "APP_UID=${APP_UID}"
echo "APP_GID=${APP_GID}"

后续 OpenList 和 qBittorrent 都使用这个 UID/GID。


4. 创建目录并设置权限

mkdir -p /opt/openlist/data
mkdir -p /opt/openlist/cert
mkdir -p /opt/qbittorrent/config
mkdir -p "/html/网盘/qBittorrent"

APP_UID=$(id -u media)
APP_GID=$(id -g media)

chown -R ${APP_UID}:${APP_GID} /opt/openlist
chown -R ${APP_UID}:${APP_GID} /opt/qbittorrent
chown -R ${APP_UID}:${APP_GID} "/html/网盘"

chmod -R 755 /opt/openlist
chmod -R 755 /opt/qbittorrent
chmod -R 755 "/html/网盘"

5. 准备 OpenList 可读取的证书目录

因为 OpenList 不再用 root 运行,如果直接挂载 /opt/cert,可能会遇到证书私钥权限不足的问题。

因此建议把证书复制到:

/opt/openlist/cert

假设你的证书路径是:

/opt/cert/网址.com/fullchain.cer
/opt/cert/网址.com/网址.com.key

执行:

DOMAIN="网址.com"
APP_UID=$(id -u media)
APP_GID=$(id -g media)

install -d -o ${APP_UID} -g ${APP_GID} -m 750 /opt/openlist/cert

install -o ${APP_UID} -g ${APP_GID} -m 644 \
  /opt/cert/${DOMAIN}/fullchain.cer \
  /opt/openlist/cert/fullchain.cer

install -o ${APP_UID} -g ${APP_GID} -m 600 \
  /opt/cert/${DOMAIN}/${DOMAIN}.key \
  /opt/openlist/cert/${DOMAIN}.key

如果你的证书文件名不是 fullchain.cer网址.com.key,先用下面命令确认:

find /opt/cert -maxdepth 4 -type f \( -name "*fullchain*" -o -name "*.cer" -o -name "*.pem" -o -name "*.key" \) -print

6. 安装 OpenList

创建环境变量文件:

cd /opt/openlist

APP_UID=$(id -u media)
APP_GID=$(id -g media)

cat > .env <<EOF
APP_UID=${APP_UID}
APP_GID=${APP_GID}
EOF

创建 /opt/openlist/docker-compose.yml

services:
  openlist:
    image: openlistteam/openlist:v4.2.1
    container_name: openlist
    restart: always
    user: "${APP_UID}:${APP_GID}"
    environment:
      - TZ=Asia/Shanghai
      - UMASK=022
    volumes:
      - /opt/openlist/data:/opt/openlist/data
      - /opt/openlist/cert:/cert:ro
      - "/html/网盘:/html/网盘"
    ports:
      - "55246:55246"
    networks:
      - nginx-net

networks:
  nginx-net:
    external: true

启动:

cd /opt/openlist
docker compose up -d

查看初始密码:

docker logs openlist | grep -i password

如果没有看到密码,可以手动设置:

docker exec -it openlist ./openlist admin set '你的强密码'

7. 配置 OpenList 的 HTTPS 直连端口 55246

安装 jq

apt update
apt install jq -y

修改 OpenList 配置:

DOMAIN="网址.com"

cp /opt/openlist/data/config.json /opt/openlist/data/config.json.bak.$(date +%F-%H%M%S)

jq --arg domain "$DOMAIN" '
  .site_url = ("https://" + $domain) |
  .scheme.address = "0.0.0.0" |
  .scheme.http_port = 5244 |
  .scheme.https_port = 55246 |
  .scheme.force_https = false |
  .scheme.cert_file = "/cert/fullchain.cer" |
  .scheme.key_file = ("/cert/" + $domain + ".key")
' /opt/openlist/data/config.json > /tmp/openlist.config.json

mv /tmp/openlist.config.json /opt/openlist/data/config.json

APP_UID=$(id -u media)
APP_GID=$(id -g media)
chown ${APP_UID}:${APP_GID} /opt/openlist/data/config.json

docker restart openlist

测试:

curl -I https://网址.com:55246

8. 在 OpenList 中添加本地存储

访问:

https://网址.com

进入后台,添加存储:

驱动:本地存储 / Local Storage
挂载路径:/网盘
根文件夹路径:/html/网盘

添加后,OpenList 中可以看到:

/网盘/qBittorrent

对应宿主机目录:

/html/网盘/qBittorrent

9. 安装 qBittorrent PT 稳定版

创建环境变量文件:

cd /opt/qbittorrent

APP_UID=$(id -u media)
APP_GID=$(id -g media)

cat > .env <<EOF
APP_UID=${APP_UID}
APP_GID=${APP_GID}
EOF

创建 /opt/qbittorrent/docker-compose.yml

services:
  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:4.6.7-libtorrentv1
    container_name: qbittorrent
    restart: always
    environment:
      - PUID=${APP_UID}
      - PGID=${APP_GID}
      - TZ=Asia/Shanghai
      - WEBUI_PORT=8080
      - TORRENTING_PORT=45000
      - UMASK=022
    volumes:
      - /opt/qbittorrent/config:/config
      - "/html/网盘/qBittorrent:/downloads"
    ports:
      - "45000:45000/tcp"
      - "45000:45000/udp"
    networks:
      - nginx-net
    stop_grace_period: 2m

networks:
  nginx-net:
    external: true

启动:

cd /opt/qbittorrent
docker compose up -d

查看 WebUI 临时密码:

docker logs qbittorrent | grep -i password

首次登录:

用户名:admin
密码:docker logs qbittorrent 中显示的临时密码

10. qBittorrent PT 推荐设置

登录 WebUI 后,立即修改用户名和密码:

工具 → 选项 → Web UI
用户名:改成你自己的
密码:改成强密码

下载目录:

工具 → 选项 → 下载
默认保存路径:/downloads

监听端口:

工具 → 选项 → 连接
监听端口:45000

PT 推荐关闭:

工具 → 选项 → BitTorrent
关闭 DHT
关闭 PeX
关闭本地用户发现 / Local Peer Discovery
不要启用匿名模式
不要设置全局分享率达到后自动停止

建议:

不要使用 qBittorrent Enhanced Edition
不要使用作弊客户端
不要使用 latest 镜像标签
不要频繁升级 qBittorrent 主版本
升级前先确认 PT 站点白名单

11. 配置 Nginx 反代 OpenList

创建 /opt/nginx/conf.d/openlist.conf

server {
    listen 80;
    server_name 网址.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name 网址.com;

    ssl_certificate     /etc/nginx/cert/网址.com/fullchain.cer;
    ssl_certificate_key /etc/nginx/cert/网址.com/网址.com.key;

    client_max_body_size 0;

    location / {
        proxy_pass http://openlist:5244;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

说明:

OpenList 的 5244 端口不映射到宿主机。
Nginx 和 OpenList 在同一个 Docker 网络 nginx-net 内。
Nginx 可以直接通过 http://openlist:5244 访问 OpenList。

12. 配置 Nginx 反代 qBittorrent

创建 /opt/nginx/conf.d/qbittorrent.conf

server {
    listen 80;
    server_name qb.网址.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name qb.网址.com;

    ssl_certificate     /etc/nginx/cert/qb.网址.com/fullchain.cer;
    ssl_certificate_key /etc/nginx/cert/qb.网址.com/qb.网址.com.key;

    client_max_body_size 0;

    location / {
        proxy_pass http://qbittorrent:8080;

        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_http_version 1.1;
    }
}

如果你使用的是泛域名证书,例如 *.网址.com,也可以统一使用:

ssl_certificate     /etc/nginx/cert/网址.com/fullchain.cer;
ssl_certificate_key /etc/nginx/cert/网址.com/网址.com.key;

13. 测试并重载 Nginx

docker exec nginx nginx -t
docker exec nginx nginx -s reload

访问测试:

https://网址.com
https://网址.com:55246
https://qb.网址.com

14. qBittorrent 反代 403 处理

如果访问:

https://qb.网址.com

出现 403,可以关闭 Host Header Validation。

方法一:WebUI 中关闭:

工具 → 选项 → Web UI
关闭 Enable Host header validation

方法二:修改配置文件:

nano /opt/qbittorrent/config/qBittorrent/qBittorrent.conf

确认存在:

WebUI\HostHeaderValidation=false

然后重启:

docker restart qbittorrent

15. 配置证书更新后的自动 reload

你的 acme 容器负责续期证书,但证书更新后 nginx 和 OpenList 不会自动重新加载新证书。

这里使用宿主机脚本定期检查证书是否变化:

  • 如果证书没变化,不做任何操作。
  • 如果证书变化:

    • 复制新证书到 /opt/openlist/cert
    • reload nginx
    • restart OpenList

创建脚本:

cat > /usr/local/sbin/reload-cert-services.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

DOMAIN="网址.com"
APP_USER="media"

APP_UID="$(id -u "${APP_USER}")"
APP_GID="$(id -g "${APP_USER}")"

CERT_SRC="/opt/cert/${DOMAIN}/fullchain.cer"
KEY_SRC="/opt/cert/${DOMAIN}/${DOMAIN}.key"

CERT_DST_DIR="/opt/openlist/cert"
CERT_DST="${CERT_DST_DIR}/fullchain.cer"
KEY_DST="${CERT_DST_DIR}/${DOMAIN}.key"

STATE_FILE="${CERT_DST_DIR}/.cert.sha256"

if [ ! -f "${CERT_SRC}" ]; then
  echo "证书文件不存在:${CERT_SRC}"
  exit 1
fi

if [ ! -f "${KEY_SRC}" ]; then
  echo "私钥文件不存在:${KEY_SRC}"
  exit 1
fi

NEW_HASH="$(sha256sum "${CERT_SRC}" "${KEY_SRC}" | sha256sum | awk '{print $1}')"
OLD_HASH="$(cat "${STATE_FILE}" 2>/dev/null || true)"

if [ "${NEW_HASH}" = "${OLD_HASH}" ]; then
  echo "证书未变化,无需 reload。"
  exit 0
fi

install -d -o "${APP_UID}" -g "${APP_GID}" -m 750 "${CERT_DST_DIR}"

install -o "${APP_UID}" -g "${APP_GID}" -m 644 \
  "${CERT_SRC}" \
  "${CERT_DST}"

install -o "${APP_UID}" -g "${APP_GID}" -m 600 \
  "${KEY_SRC}" \
  "${KEY_DST}"

echo "${NEW_HASH}" > "${STATE_FILE}"
chown "${APP_UID}:${APP_GID}" "${STATE_FILE}"
chmod 600 "${STATE_FILE}"

docker exec nginx nginx -t
docker exec nginx nginx -s reload
docker restart openlist

echo "证书已更新,nginx 已 reload,OpenList 已重启。"
EOF

chmod +x /usr/local/sbin/reload-cert-services.sh

先手动执行一次:

/usr/local/sbin/reload-cert-services.sh

添加 cron,每小时检查一次:

crontab -e

加入:

17 * * * * /usr/local/sbin/reload-cert-services.sh >> /var/log/cert-reload.log 2>&1

说明:

这个脚本不是每小时都重启服务。
它会先比较证书和私钥 hash。
只有证书发生变化时,才会 reload nginx 和 restart OpenList。

16. 防火墙和安全组设置

放行 HTTP/HTTPS:

ufw allow 80/tcp
ufw allow 443/tcp

放行 qBittorrent BT 端口:

ufw allow 45000/tcp
ufw allow 45000/udp

55246 是给其他 VPS 中转 OpenList 用的,不建议全网开放。

只允许中转机 IP 访问:

ufw allow from 中转机IP to any port 55246 proto tcp
ufw deny 55246/tcp
ufw reload

如果不用 ufw,请在云厂商安全组中放行:

80/tcp
443/tcp
45000/tcp
45000/udp
55246/tcp 仅允许中转机 IP

17. 预留 IYUU 安装

后续建议单独安装 IYUU,方便管理。

创建目录:

mkdir -p /opt/iyuu/config

示例 /opt/iyuu/docker-compose.yml

services:
  iyuuplus:
    image: iyuucn/iyuuplus:latest
    container_name: iyuuplus
    restart: always
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /opt/iyuu/config:/IYUU/db
      - /opt/qbittorrent/config/qBittorrent/BT_backup:/BT_backup:ro
      - "/html/网盘/qBittorrent:/downloads"
    ports:
      - "8780:8780"
    networks:
      - nginx-net

networks:
  nginx-net:
    external: true

启动:

cd /opt/iyuu
docker compose up -d

IYUU 中 qBittorrent 连接信息:

地址:http://qbittorrent:8080
用户名:你的 qBittorrent WebUI 用户名
密码:你的 qBittorrent WebUI 密码
下载目录:/downloads

说明:

IYUU 和 qBittorrent 在同一个 Docker 网络 nginx-net 内,
所以可以直接通过容器名 qbittorrent 访问,
不需要走公网域名。

18. 常用管理命令

OpenList

cd /opt/openlist
docker compose pull
docker compose up -d
docker logs -f openlist
docker restart openlist

重置 OpenList 管理员密码:

docker exec -it openlist ./openlist admin set '新密码'

qBittorrent

cd /opt/qbittorrent
docker compose up -d
docker logs -f qbittorrent
docker restart qbittorrent

查看 qBittorrent 镜像版本:

docker inspect -f '{{ index .Config.Labels "build_version" }}' qbittorrent

Nginx

docker exec nginx nginx -t
docker exec nginx nginx -s reload
docker logs -f nginx

19. 最终检查清单

[ ] nginx 已映射 80 和 443
[ ] nginx-net 网络存在
[ ] 宿主机普通用户 media 已创建
[ ] OpenList 和 qBittorrent 使用相同 UID/GID
[ ] /html/网盘 权限属于 media 用户
[ ] /html/网盘/qBittorrent 权限属于 media 用户
[ ] OpenList 未使用 user: "0:0"
[ ] qBittorrent 使用 PUID/PGID
[ ] docker-compose.yml 中没有冗余 expose
[ ] OpenList 容器已启动
[ ] qBittorrent 容器已启动
[ ] OpenList 已挂载 /html/网盘
[ ] qBittorrent 下载目录是 /downloads
[ ] /downloads 对应宿主机 /html/网盘/qBittorrent
[ ] https://网址.com 可访问 OpenList
[ ] https://网址.com:55246 可直连 OpenList
[ ] https://qb.网址.com 可访问 qBittorrent
[ ] qBittorrent 已关闭 DHT、PeX、LPD
[ ] qBittorrent 已修改默认密码
[ ] 45000/tcp 和 45000/udp 已放行
[ ] 55246/tcp 只允许中转机 IP 访问
[ ] /usr/local/sbin/reload-cert-services.sh 已创建
[ ] cron 已添加证书变更检测任务
无标签
评论区
头像