Doce construcciones

Un seedbox en un nodo de almacenamiento de 50 TB, con permisos que se mantienen

qBittorrent en un S-50 con capa de preparación NVMe, una unidad endurecida, permisos de grupo que sobreviven a cada nueva descarga y un proxy que mantiene la interfaz fuera de la internet pública.

Qué construye esto

Un nodo de almacenamiento que ejecuta qBittorrent como un servicio sin privilegios: los datos incompletos se escriben en el nivel NVMe, los datos completados se mueven al nivel de cincuenta terabytes, todo pertenece a un grupo compartido para que una segunda cuenta pueda leerlos por SFTP sin arqueología de chmod, y una interfaz web accesible solo mediante un proxy autenticado.

El enfoque obvio es instalar el paquete, hacer clic en la interfaz y seguir con su día. Eso funciona durante una quincena, hasta que el primer archivo llega con el grupo incorrecto y su usuario de sincronización no puede leerlo, y para entonces hay cuarenta mil archivos con el grupo incorrecto.

Antes de empezar

  • Una S-50: cincuenta terabytes de almacenamiento masivo tras un nivel NVMe de un terabyte, en un puerto de diez gigabits. El tráfico no está medido bajo uso justo, y la política de uso aceptable es breve y específica sobre lo que puede cruzarla. Los derechos de distribución son su problema, no una nota al pie.
  • Debian 13, root y un nombre de host como box.example.com.

1. Usuarios, grupos, estructura

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

Dos cuentas, un grupo. El demonio se ejecuta como qbt y nunca inicia sesión; sync es la cuenta con la que usted extrae archivos y puede no escribir nada. Ahora los directorios, y las dos banderas que hacen que esto funcione permanentemente:

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

El modo 2775 establece el bit setgid, de modo que cada archivo creado dentro hereda el grupo media en lugar del grupo principal del usuario creador. La ACL predeterminada otorga a ese grupo lectura y escritura en las nuevas entradas independientemente del umask del proceso. Juntas significan que la cuestión de permisos se resuelve una vez en lugar de después de cada descarga.

En una S-50 el nivel masivo y el NVMe son dispositivos de bloque separados. Confirme cuál es cuál antes de comprometerse con las rutas:

lsblk -o NAME,SIZE,ROTA,MOUNTPOINT

2. El demonio

Inícielo una vez para que escriba un archivo de configuración, luego deténgalo y edite ese archivo. Pelear con la interfaz por configuraciones que viven en un archivo de texto es perder una tarde.

sudo -u qbt qbittorrent-nox --webui-port=8080 &
sleep 5 && pkill -u qbt qbittorrent-nox

Edite /srv/qbt/.config/qBittorrent/qBittorrent.conf para que las secciones [BitTorrent] y [Preferences] contengan:

[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

El almacenamiento temporal en NVMe es todo el truco. Las escrituras de Torrent son pequeñas y dispersas, lo cual es el peor patrón posible para el nivel masivo; el NVMe las absorbe, y el archivo completado se mueve como una copia secuencial. La preasignación evita la fragmentación en el camino.

3. Una unidad que no puede vagar

/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.target

UMask=0002 y Group=media son lo que mantiene los archivos nuevos con escritura de grupo. Sin la primera, setgid le da el grupo correcto en archivos que nadie en ese grupo puede escribir, lo cual es un éxito a medias sutil e irritante.

systemctl daemon-reload && systemctl enable --now qbittorrent

4. Kernel y firewall

Diez gigabits con varios cientos de pares necesitan buffers de socket más grandes y una tabla de conexiones que no se llene:

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

Firewall: el puerto de torrent abierto en ambas familias, SSH y HTTPS abiertos, la interfaz web enlazada a loopback y por lo tanto sin necesidad de nada.

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. La interfaz, detrás de un proxy

certbot certonly --standalone -d box.example.com
htpasswd -c /etc/nginx/qbt.htpasswd you
server {
  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;
  }
}

Verifíquelo

Use algo con un enjambre grande y bien sembrado y una licencia inequívoca. Una imagen de instalador de Debian actual es la elección tradicional y satura un puerto de diez gigabits más convincentemente que cualquier otra cosa con la que pueda probar legalmente.

Añada el torrent a través de la interfaz y luego observe cómo se llena el nivel de almacenamiento temporal:

watch -n2 "du -sh /srv/nvme/incomplete /srv/bulk/complete"

Mientras se ejecuta, confirme que el puerto es realmente accesible en lugar de simplemente abierto en su propio firewall, ya que un puerto inalcanzable produce un seedbox que descarga aceptablemente y no siembra a nadie:

ss -tn state established sport = :51413 | wc -l

Conexiones entrantes en ese puerto significan que los pares lo encontraron. Cero, con muchas conexiones salientes, significa que solo usted está llamando hacia afuera.

Cuando la descarga se complete, verifique las tres cosas para las que existe esta construcción:

ls -l /srv/nvme/incomplete
ls -ln /srv/bulk/complete
sudo -u sync cat /srv/bulk/complete/*.iso > /dev/null && echo "sync can read"

El directorio de almacenamiento temporal está vacío, los archivos completados muestran el grupo 3000 con lectura y escritura de grupo, y la cuenta sync puede leerlos sin ninguna corrección manual de permisos. Ese tercer comando es el que demuestra que el setgid y el trabajo de ACL valieron la pena.

Finalmente, demuestre que la interfaz no está expuesta:

curl -m5 http://box.example.com:8080/ ; echo "exit $?"
curl -sI https://box.example.com/ | head -1

El primero debería fallar en la conexión, el segundo debería devolver 401. Cualquier otra cosa y el enlace de dirección en el paso dos no se aplicó.

Después

Establezca una proporción de siembra global o un límite de tiempo de compartir a menos que pretenda sembrar todo para siempre, porque cincuenta terabytes se llenan más rápido de lo que cualquiera espera. Si alguna vez nos llega una queja sobre el tráfico de su instancia, el proceso se describe en la página de abuso: se reenvía a usted, y nosotros no vamos a buscar en su disco.

Listo cuando tú lo estés

Elige una ciudad. Elige un tamaño. Paga con monedas.

Sin fórmulas sobre quién eres, sin esperar a que un humano te apruebe, sin llamada telefónica para verificar nada. La factura se liquida y las credenciales llegan a tu bandeja de entrada.