构建内容
一个运行 qBittorrent 作为非特权服务的存储节点:不完整数据写入 NVMe 层,完成的数据移动到五十 TB 的批量层,所有内容由一个共享组拥有,以便第二个账户可以通过 SFTP 读取而无需任何 chmod 考古,以及一个只能通过已认证代理访问的 Web 界面。
显而易见的方法是安装软件包,点击界面,然后继续你的一天。这在前两周有效,直到第一个文件到达时组错误,你的同步用户无法读取,而到那时已经有四万个文件的组错误。
开始之前
- 一个 S-50:五十 TB 批量存储,后接一 TB NVMe 层,位于十 Gbps 端口上。流量在合理使用下不受计量,可接受使用政策 简短且具体地说明了允许传输的内容。分发权是你的问题,而不是脚注。
- Debian 13,root,以及诸如
box.example.com的主机名。
1. 用户、组、布局
apt update && apt install -y qbittorrent-nox nginx apache2-utils acl
groupadd -g 3000 media
useradd -r -g media -u 3000 -d /srv/qbt -m -s /usr/sbin/nologin qbt
useradd -m -G media sync两个账户,一个组。守护进程以 qbt 身份运行,从不登录;sync 是你拉取文件的账户,不能写入任何内容。接下来是目录,以及使此永久有效的两个标志:
install -d -o qbt -g media -m 2775 /srv/nvme/incomplete
install -d -o qbt -g media -m 2775 /srv/bulk/complete
setfacl -d -m g:media:rwx /srv/bulk/complete
setfacl -d -m g:media:rwx /srv/nvme/incomplete模式 2775 设置 setgid 位,因此内部创建的每个文件继承 media 组,而不是创建用户的主组。默认 ACL 随后授予该组对新条目的读写权限,无论进程 umask 如何。它们共同意味着权限问题只需回答一次,而不是每次下载后都回答。
在 S-50 上,批量层和 NVMe 是分开的块设备。在确定路径之前确认哪个是哪个:
lsblk -o NAME,SIZE,ROTA,MOUNTPOINT2. 守护进程
先启动一次,以便写入配置文件,然后停止并编辑该文件。与界面抗争那些存在于文本文件中的设置是浪费一个下午。
sudo -u qbt qbittorrent-nox --webui-port=8080 &
sleep 5 && pkill -u qbt qbittorrent-nox编辑 /srv/qbt/.config/qBittorrent/qBittorrent.conf,使 [BitTorrent] 和 [Preferences] 部分包含:
[BitTorrent]
Session\DefaultSavePath=/srv/bulk/complete
Session\TempPath=/srv/nvme/incomplete
Session\TempPathEnabled=true
Session\Port=51413
Session\DiskCacheSize=2048
Session\MaxConnections=800
Session\MaxUploads=40
Session\GlobalMaxSeedingMinutes=-1
Session\Preallocation=true
[Preferences]
WebUI\Address=127.0.0.1
WebUI\Port=8080
WebUI\LocalHostAuth=false
WebUI\CSRFProtection=true
Downloads\UseIncompleteExtension=true在 NVMe 上进行暂存是整个诀窍。Torrent 写入小而分散,这是批量层最糟糕的模式;NVMe 吸收它们,完成后文件作为一次顺序复制移动。预分配防止进入时的碎片化。
3. 不能游荡的单元
/etc/systemd/system/qbittorrent.service:
[Unit]
Description=qBittorrent
After=network-online.target
Wants=network-online.target
[Service]
User=qbt
Group=media
UMask=0002
ExecStart=/usr/bin/qbittorrent-nox
Restart=on-failure
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
ReadWritePaths=/srv/qbt /srv/nvme/incomplete /srv/bulk/complete
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetUMask=0002 和 Group=media 是保持新文件组可写的关键。没有前者,setgid 会给你正确的组,但该组中没有人能写,这是一个微妙且令人恼火的半成功。
systemctl daemon-reload && systemctl enable --now qbittorrent4. 内核和防火墙
十 Gbps 和数百个对等方需要更大的套接字缓冲区和不会填满的连接表:
cat > /etc/sysctl.d/70-seedbox.conf <<EOF
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 65536 33554432
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.netfilter.nf_conntrack_max = 524288
EOF
sysctl --system防火墙:torrent 端口对两个家族开放,SSH 和 HTTPS 开放,Web 界面绑定到回环,因此不需要任何东西。
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iif lo accept
ip6 nexthdr icmpv6 accept
ip protocol icmp accept
tcp dport { 22, 443 } accept
tcp dport 51413 accept
udp dport 51413 accept
}
}5. 界面,在代理后面
certbot certonly --standalone -d box.example.com
htpasswd -c /etc/nginx/qbt.htpasswd youserver {
listen 443 ssl;
server_name box.example.com;
ssl_certificate /etc/letsencrypt/live/box.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/box.example.com/privkey.pem;
client_max_body_size 100m;
location / {
auth_basic "closed";
auth_basic_user_file /etc/nginx/qbt.htpasswd;
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-Host $http_host;
proxy_http_version 1.1;
}
}验证
使用具有大量、良好种子的大文件,并且具有明确的许可证。当前的 Debian 安装镜像传统上是首选,并且比任何其他合法测试的东西都更能饱和十 Gbps 端口。
通过界面添加 torrent,然后观察暂存层填充:
watch -n2 "du -sh /srv/nvme/incomplete /srv/bulk/complete"运行时,确认端口真正可达,而不仅仅是你自己防火墙中开放,因为不可达端口会产生一个下载可接受但无法向任何人做种的种子盒:
ss -tn state established sport = :51413 | wc -l该端口上的传入连接意味着对等方找到了你。为零,但有许多传出连接,意味着只有你在拨出。
当下载完成时,检查此构建存在的三件事:
ls -l /srv/nvme/incomplete
ls -ln /srv/bulk/complete
sudo -u sync cat /srv/bulk/complete/*.iso > /dev/null && echo "sync can read"暂存目录为空,完成的文件显示组 3000 并具有组读写权限,sync 账户可以读取它们而无需手动修复权限。第三个命令证明 setgid 和 ACL 工作得到了回报。
最后,证明界面没有暴露:
curl -m5 http://box.example.com:8080/ ; echo "exit $?"
curl -sI https://box.example.com/ | head -1第一个应该连接失败,第二个应该返回 401。其他任何情况都意味着第二步中的地址绑定没有生效。
之后
设置全局做种比率或分享时间限制,除非你打算永远做种所有内容,因为五十 TB 比任何人预期的更快填满。如果关于你的实例流量的投诉到达我们这里,过程在滥用页面上有描述:它会被转发给你,我们不会翻看你的磁盘。