确认 nginx 网络存在
docker network ls | grep nginx-net如果不存在,需要先创建:
docker network create nginx-net1、创建宿主机普通服务用户
这里以创建 openlist 用户为例:
查看openlist用户是否存在,如果不存在则新建openlist用户
id openlist || useradd -m -s /usr/sbin/nologin openlist查看 UID/GID:
id openlist例如输出:
uid=1000(openlist) gid=1000(openlist) groups=1000(openlist)
记录 UID/GID:
APP_UID=$(id -u openlist)
APP_GID=$(id -g openlist)
echo "APP_UID=${APP_UID}"
echo "APP_GID=${APP_GID}"后续 OpenList 和 qBittorrent 都使用这个 UID/GID。
2、创建目录并设置权限
mkdir -p /opt/openlist/data
mkdir -p /opt/openlist/cert
mkdir -p /opt/qbittorrent/config
APP_UID=$(id -u openlist)
APP_GID=$(id -g openlist)
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/网盘"3、准备 OpenList 可读取的证书目录
因为 OpenList 不再用 root 运行,如果直接挂载 /opt/cert,可能会遇到证书私钥权限不足的问题。
因此建议把证书复制到:
/opt/openlist/cert4、创建 OpenList 证书自动同步脚本
由于 OpenList 使用普通用户运行,不建议直接读取 /opt/cert 下的私钥。用脚本把证书自动同步到**/opt/openlist/cert/**
创建脚本:
cat > /opt/openlist/cert/sync-openlist-cert.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
OPENLIST_DOMAIN="网址.com"
APP_USER="openlist"
APP_UID="$(id -u "${APP_USER}")"
APP_GID="$(id -g "${APP_USER}")"
CERT_SRC="/opt/cert/${OPENLIST_DOMAIN}.fullchain.crt"
KEY_SRC="/opt/cert/${OPENLIST_DOMAIN}.key"
CERT_DST_DIR="/opt/openlist/cert"
CERT_DST="${CERT_DST_DIR}/${OPENLIST_DOMAIN}.fullchain.crt"
KEY_DST="${CERT_DST_DIR}/${OPENLIST_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 "证书未变化,无需处理。"
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}"
if docker ps -a --format '{{.Names}}' | grep -qx nginx; then
docker exec nginx nginx -t
docker restart nginx
else
echo "nginx 容器不存在,跳过 nginx reload。"
fi
if docker ps -a --format '{{.Names}}' | grep -qx openlist; then
docker restart openlist
else
echo "openlist 容器不存在,跳过 OpenList 重启。"
fi
echo "OpenList 证书已同步,nginx 已 reload,OpenList 已重启。"
EOF设置权限
chmod +x /opt/openlist/cert/sync-openlist-cert.sh手动执行一次初始化同步,第一次需要手动执行一次:
/opt/openlist/cert/sync-openlist-cert.sh查看同步结果:
ls -l /opt/openlist/cert正常应该看到类似:
-rw------- 1 openlist openlist 网址.com.key
5、添加 cron 自动检测证书变化
编辑 crontab:
crontab -e加入:
17 * * * * /opt/openlist/cert/sync-openlist-cert.sh >> /opt/openlist/cert/sync-openlist-cert.log 2>&1说明:
每小时检查一次证书是否变化。
如果证书没有变化,不会 reload nginx,也不会 restart OpenList。
如果 acme 自动续期了证书,脚本会自动同步新证书并重载相关服务。
查看日志:
tail -f /opt/openlist/cert/sync-openlist-cert.log6、安装 OpenList
创建环境变量文件:
cd /opt/openlist
APP_UID=$(id -u openlist)
APP_GID=$(id -g openlist)
cat > .env <<EOF
APP_UID=${APP_UID}
APP_GID=${APP_GID}
EOF创建 /opt/openlist/docker-compose.yml:
nano /opt/openlist/docker-compose.ymlservices:
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
编辑/opt/openlist/data/config.json
nano /opt/openlist/data/config.json找到或修改这些字段:
{
"site_url": "https://网址.com",
"scheme": {
"address": "0.0.0.0",
"http_port": 5244,
"https_port": 55246,
"force_https": false,
"cert_file": "/cert/网址.com.fullchain.crt",
"key_file": "/cert/网址.com.key"
}
}测试:
docker restart openlist
curl -I https://网址.com:552468、安装 qBittorrent PT 稳定版
创建环境变量文件:
cd /opt/qbittorrent
APP_UID=$(id -u openlist)
APP_GID=$(id -g openlist)
cat > .env <<EOF
APP_UID=${APP_UID}
APP_GID=${APP_GID}
EOF创建 /opt/qbittorrent/docker-compose.yml:
nano /opt/qbittorrent/docker-compose.ymlservices:
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
mem_limit: 16g
mem_reservation: 2g
sysctls:
- net.core.somaxconn=1024
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
nginx-net:
external: true启动:
cd /opt/qbittorrent
docker compose up -d查看 WebUI 临时密码:
docker logs qbittorrent | grep -i password首次登录:
用户名:admin
密码:docker logs qbittorrent 中显示的临时密码
9、配置 Nginx 反代 OpenList
创建 /opt/nginx/conf.d/openlist.conf:
nano /opt/nginx/conf.d/openlist.conf#server {
# listen 80;
# server_name 网址.com;
#
# return 301 https://$host$request_uri;
#}
server {
listen 443 ssl;
http2 on;
server_name 网址.com;
ssl_certificate /etc/nginx/cert/网址.com.fullchain.crt;
ssl_certificate_key /etc/nginx/cert/网址.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。
10、配置 Nginx 反代 qBittorrent
创建 /opt/nginx/conf.d/qbittorrent.conf:
nano /opt/nginx/conf.d/qbittorrent.confserver {
listen 80;
server_name qb.网址.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name qb.网址.com;
ssl_certificate /etc/nginx/cert/qb.网址.com.fullchain.crt;
ssl_certificate_key /etc/nginx/cert/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;
}
}11、测试并重载 Nginx
docker exec nginx nginx -tdocker exec nginx nginx -s reload访问测试:
https://网址.com
https://网址.com:55246
https://qb.网址.com12、显示磁盘容量
在openlist根目录中新建本地磁盘空间.txt文件 在'设置'-'全局'-'自定义内容'内输入以下内容,将 xhttp.open后面修改为TXT的下载地址
<!-- 自定义样式 -->
<style>
/* 隐藏原底部版权和管理 */
.footer span,
.footer a:nth-of-type(1),
.footer a:nth-of-type(2) {
display: none !important;
}
/* 移除搜索栏中的键盘图标:这个选择器可能会随版本变化失效 */
.hope-stack.hope-c-dhzjXW.hope-c-PJLV.hope-c-PJLV-ihYBJPK-css {
display: none !important;
}
/* 自定义底部区域 */
#custom-footer {
display: none;
text-align: center;
padding: 8px 0;
font-size: 14px;
}
#disk-space-content {
text-align: center;
white-space: pre-wrap;
margin-bottom: 4px;
}
#custom-footer p {
margin: 0;
}
#custom-footer a {
text-decoration: none;
}
#custom-footer span {
margin: 0 6px;
}
</style>
<script>
(function () {
const TXT_URL = "https://www.网址.com/xx.txt";
function createCustomFooter() {
const footer = document.querySelector(".footer");
if (!footer || document.querySelector("#custom-footer")) {
return;
}
const customFooter = document.createElement("div");
customFooter.id = "custom-footer";
customFooter.innerHTML = `
<div id="disk-space-content">正在读取磁盘容量...</div>
<p>
<a href="https://openlist.nn.ci/zh/" target="_blank" rel="noopener noreferrer">© Powered by openlist</a>
<span>|</span>
<a href="/@manage">管理</a>
</p>
`;
footer.insertAdjacentElement("afterend", customFooter);
customFooter.style.display = "block";
loadDiskText();
}
async function loadDiskText() {
const content = document.querySelector("#disk-space-content");
if (!content) {
return;
}
try {
const separator = TXT_URL.includes("?") ? "&" : "?";
const url = TXT_URL + separator + "_t=" + Date.now();
const response = await fetch(url, {
cache: "no-store"
});
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
const text = await response.text();
// 用 textContent 更安全,避免 TXT 内容被当成 HTML 执行
content.textContent = text.trim();
} catch (error) {
content.textContent = "磁盘容量信息暂时无法读取";
console.warn("读取磁盘容量失败:", error);
}
}
function init() {
createCustomFooter();
const observer = new MutationObserver(function () {
createCustomFooter();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// 防止一直监听,15 秒后停止
setTimeout(function () {
observer.disconnect();
}, 15000);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
</script>创建sh文件
nano /opt/openlist/显示磁盘剩余空间.sh输入以下内容
#!/bin/bash
all=$(df -Bg | grep -w /dev/vda1 | awk '{ print $2 }') #注意将/dev/vda1修改为当前磁盘的路径 -w为完全匹配,避免返回多个结果
free=$(df -Bg | grep -w /dev/vda1 | awk '{ print $4 }') #注意将/dev/vda1修改为当前磁盘的路径 -w为完全匹配,避免返回多个结果
if [ ${free}x != $(awk '{print $2}' /html/网盘/other/本地磁盘空间.txt)x ]
then
sed -i "1c 本地磁盘可用空间: ${free} / ${all}" /html/网盘/other/本地磁盘空间.txt #此处是前面建立的存储磁盘容量信息的TXT文件的路径
fi给与权限
chmod +x /opt/openlist/显示磁盘剩余空间.sh执行
/opt/openlist/显示磁盘剩余空间.sh设置定时器
crontab -e每分钟执行一次
* * * * * /opt/openlist/显示磁盘剩余空间.sh >/dev/null 2>&1可以在设置-全局- 隐藏文件中加入/\/本地磁盘空间.txt/i来隐藏TXT文件
可以在设置-元信息- 隐藏中加入^文件夹名称$来隐藏文件夹,在用户中关闭 可以看到隐藏选项。如果是将^文件夹名称$直接复制过去的话,需要回车,否则可能不生效。如果文件加名称是中文,比如 ^中文目录$,不能放到第一个。
13、qBittorrent PT 推荐设置
登录 WebUI 后,立即修改用户名和密码:
工具 → 选项 → Web UI
用户名:改成你自己的
密码:改成强密码
下载目录:
工具 → 选项 → 下载默认保存路径:/downloads
监听端口:
工具 → 选项 → 连接监听端口:45000
PT 推荐关闭:
工具 → 选项 → BitTorrent关闭 DHT
关闭 PeX
关闭本地用户发现 / Local Peer Discovery
不要启用匿名模式
不要设置全局分享率达到后自动停止
14、防火墙和安全组设置
放行 HTTP/HTTPS:
ufw allow 80/tcp
ufw allow 443/tcp放行 qBittorrent BT 端口:
ufw allow 45000/tcp
ufw allow 45000/udp55246 是给其他 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 仅允许中转机 IP15、IYUU 安装
创建 IYUUPlus 目录
mkdir -p /opt/iyuu/iyuu
mkdir -p /opt/iyuu/data
chmod -R 755 /opt/iyuu如果你前面使用的是 openlist 用户统一管理 OpenList 和 qBittorrent 权限,也给 IYUU 目录设置同样权限:
APP_UID=$(id -u openlist)
APP_GID=$(id -g openlist)
chown -R ${APP_UID}:${APP_GID} /opt/iyuu创建 IYUUPlus docker-compose.yml
nano /opt/iyuu/docker-compose.yml写入:
services:
iyuuplus:
image: iyuucn/iyuuplus-dev:latest
container_name: iyuuplus
restart: always
stdin_open: true
tty: true
environment:
- TZ=Asia/Shanghai
volumes:
- /opt/iyuu/iyuu:/iyuu
- /opt/iyuu/data:/data
- /opt/qbittorrent/config/qBittorrent/BT_backup:/BT_backup:ro
networks:
- nginx-net
networks:
nginx-net:
external: true这里没有把 IYUUPlus 的端口暴露到公网,因为后面会通过 Nginx 容器内网反代访问。
启动 IYUUPlus
cd /opt/iyuu
docker compose up -d查看日志:
docker logs -f iyuuplus
#等日志中出现 “Press Ctrl+C to stop. Start success.” 才算安装完成 确认容器是否运行:
docker ps | grep iyuuplus确认 IYUUPlus 容器内监听端口
docker exec -it iyuuplus sh -c "ss -lntp 2>/dev/null || netstat -lntp 2>/dev/null"重点看类似:
tcp 0 0 0.0.0.0:8780 0.0.0.0:* LISTEN 204/nginx: master
测试 nginx 容器能否访问 IYUUPlus
执行:
docker exec nginx sh -c "curl -I http://iyuuplus:8780"能看到 HTTP 返回头,说明 nginx 容器可以通过 Docker 网络访问 IYUUPlus。
16、配置 Nginx 反代 IYUUPlus
创建:
nano /opt/nginx/conf.d/iyuu.conf写入:
server {
listen 80;
server_name iyuu.网址.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
http2 on;
server_name iyuu.网址.com;
ssl_certificate /etc/nginx/cert/iyuu.网址.com.fullchain.crt;
ssl_certificate_key /etc/nginx/cert/iyuu.网址.com.key;
client_max_body_size 0;
location / {
proxy_pass http://iyuuplus:8780;
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 Connection "";
}
}测试并重载 Nginx:
docker exec nginx nginx -t重载 Nginx:
docker exec nginx nginx -s reload17、访问 IYUUPlus
浏览器访问:
https://iyuu.网址.comIYUUPlus 中添加 qBittorrent 下载器
下载器类型:
qBittorrent
地址填写:
http://qbittorrent:8080
用户名:
你的 qBittorrent WebUI 用户名
密码:
你的 qBittorrent WebUI 密码
下载目录映射:
qBittorrent 容器内路径:/downloadsIYUUPlus 容器内路径:/downloads
宿主机实际路径:/html/网盘/qBittorrent
因为 qBittorrent 和 IYUUPlus 都在同一个 Docker 网络nginx-net,所以 IYUUPlus 连接 qBittorrent 不需要走公网域名:
不要填:https://qb.mydisk.cc