Saltar al contenido principal

Nube y VPS

Resumen​

Un VPS en la nube es un host Linux que alquilas. La instalación es idéntica. Lo que cambia es que está en el internet público, lo que convierte tres cosas opcionales en obligatorias:

  1. Un firewall. Expón solo el 80/443 — nunca el 8080, nunca el 4000, nunca el 5000.
  2. HTTPS. Sin excepciones.
  3. Copias de seguridad que guardes en otro lugar. Una instancia en la nube puede desaparecer.

Y dos cosas que tienes que entender antes de gastar dinero:

  • El ancho de banda se mide casi en todas partes, y BitTorrent es ancho de banda. De ahí salen las facturas sorpresa.
  • La política de uso aceptable (AUP) de tu proveedor te aplica a ti. Léela.
Lee primero la AUP de tu proveedor

Algunos proveedores prohíben el tráfico de BitTorrent de plano, otros lo toleran, y otros cancelan tu cuenta con el primer aviso de DMCA. Esto es una cuestión de política, no técnica, y corre completamente por tu cuenta. UltraTorrent es una plataforma de adquisición de medios — úsala para contenido sobre el que tengas derechos.

Verificado por la comunidad

Los proveedores de nube no están entre los destinos de despliegue propios de este proyecto. Las partes de UltraTorrent de abajo están fundamentadas en el repositorio; los detalles de cada proveedor siguen su práctica estándar y sus consolas cambian constantemente. Verifica contra la documentación vigente del proveedor.

Mira este tutorial

Video próximamente.

Requisitos previos​

  • Una cuenta en la nube y un nombre de dominio (lo necesitas para HTTPS).
  • Acceso SSH por llave a la instancia.
  • Una tarjeta de crédito que estés vigilando.

Requisitos​

RecursoMínimoCómodoPor qué
vCPU22–4La compilación; el estado estable es liviano
RAM4 GB4–8 GBLa compilación llega a un pico de unos 2 GB libres — un droplet de 1 GB fallará al compilar
Disco de arranque20 GB40 GBSO + imágenes
Disco de datosConecta almacenamiento en bloquetan grande como tu bibliotecaLos discos de arranque son pequeños y caros
Ancho de bandarevisa el topesin medir o generosoAquí está el costo real

A grandes rasgos, por proveedor:

ProveedorInstancia inicial sensataNotas sobre el ancho de banda
HetznerCX22 / CPX21 (2 vCPU, 4 GB)Tráfico incluido generoso — normalmente la opción sensata más barata
DigitalOceanBasic 2 vCPU / 4 GBLa cuota de transferencia se agrupa por cuenta; el exceso se factura
Vultr2 vCPU / 4 GB RegularModelo similar al de DO
Oracle CloudAmpere A1 (ARM) — 4 OCPU / 24 GB en la capa gratuitaCapa gratuita grande, pero la capacidad muchas veces no está disponible, y el egress más allá de la cuota gratuita se factura
AWS EC2t3.medium / t4g.mediumEl egress es caro. Esta es la plataforma clásica de la factura sorpresa
GCPe2-mediumEgress facturado por GB
AzureB2sEgress facturado por GB
Linode/Akamai2 GB shared → 4 GB2 GB es muy poco para compilar
El egress en los hiperescaladores

En AWS/GCP/Azure, la transferencia de datos de salida se factura por gigabyte. Un cliente de torrents compartiendo (seeding) es una máquina para generar transferencia de datos de salida. Hay gente que ha acumulado facturas de cuatro cifras así. Si usas un hiperescalador, limita tu tasa de subida, configura una alarma de facturación y conoce el precio de tu egress antes de empezar.

Las instancias ARM64 (Graviton, Ampere, Axion) funcionan — las imágenes base son multiarquitectura.

Puertos​

Puerto¿Abierto al internet?
22 (SSH)Solo por llave, e idealmente restringido a tu IP
80Sí — redirección HTTP→HTTPS y ACME
443Sí — la UI
8080No. Enlázalo a 127.0.0.1 y deja que el proxy lo alcance
4000 (backend)Nunca. No se publica de forma predeterminada; déjalo así
5000 (SCGI)Nunca. Control remoto total sin autenticación
Puertos de paresOpcional, y solo si entiendes la exposición

Volúmenes​

Usa almacenamiento en bloque para las descargas, no el disco de arranque:

# después de conectar el volumen en la consola del proveedor
lsblk # encuentra el dispositivo, p. ej. /dev/sdb
sudo mkfs.ext4 /dev/sdb
sudo mkdir -p /mnt/downloads
echo '/dev/sdb /mnt/downloads ext4 defaults,nofail,discard 0 2' | sudo tee -a /etc/fstab
sudo mount -a
sudo chown -R 1000:1000 /mnt/downloads
# docker-compose.override.yml
volumes:
downloads:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/downloads
nofail importa en la nube

Sin él, una instancia que arranca antes de que el volumen se conecte cae a un shell de emergencia y nunca vuelve — y te toca depurarla por consola serial.

Permisos​

Linux estándar — la carpeta de descargas tiene que ser escribible por el uid 1000 (o por tu PUID/PGID). Ver Permisos.

La pregunta de permisos más importante en un VPS es quién puede iniciar sesión: solo llaves, sin autenticación por contraseña, sin login de root.

Paso a paso​

1. Crea la instancia​

  • Image: Ubuntu 24.04
  • Type: CX22 (2 vCPU, 4 GB) o mayor
  • Volume: conecta almacenamiento en bloque para las descargas
  • Firewall: crea uno que permita 22 (tu IP), 80, 443 — nada más
  • SSH key: agrega la tuya

La cuota de tráfico incluida de Hetzner es generosa, y por eso es la respuesta usual para esta carga de trabajo.

2. Endurece la máquina — antes de instalar nada​

sudo apt update && sudo apt upgrade -y

# SSH: solo llaves
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart ssh

# Actualizaciones de seguridad automáticas
sudo apt install -y unattended-upgrades fail2ban

Cortafuegos del host, además del de la nube:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Docker atraviesa ufw

Docker escribe sus propias reglas de iptables y un puerto publicado se salta ufw. ufw deny 8080 no protege un container publicado en 0.0.0.0:8080. La única solución confiable es no publicarlo públicamente — enlázalo a localhost (próximo paso) y usa el firewall de la nube como capa exterior.

3. Instala Docker + UltraTorrent​

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER" # cierra sesión y vuelve a entrar

git clone https://github.com/ultratorrentofficial/ultratorrent.git
cd ultratorrent
cp .env.example .env
for k in JWT_ACCESS_SECRET JWT_REFRESH_SECRET ENCRYPTION_KEY; do
sed -i "s|^$k=.*|$k=$(openssl rand -base64 48 | tr -d '\n')|" .env
done
nano .env
POSTGRES_PASSWORD=lettersAndNumbers123
ADMIN_PASSWORD=a-genuinely-strong-password # esta da la cara al internet
FRONTEND_PORT=8080
CORS_ORIGIN=https://torrents.example.com # tu origen público real

4. Enlaza la UI a localhost​

Este es el paso que mantiene el puerto HTTP crudo fuera del internet.

# docker-compose.override.yml
services:
frontend:
ports: !override
- "127.0.0.1:8080:8080"

volumes:
downloads:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/downloads
Verificado por la comunidad

!override necesita un Compose v2 reciente. Si el tuyo lo rechaza, edita la línea ports: directamente en docker-compose.yml — un override sencillo agrega puertos en vez de reemplazarlos, lo que dejaría 0.0.0.0:8080 publicado.

Verifícalo después. Este comando es el punto entero de esta sección:

sudo ss -tlnp | grep 8080
# QUEREMOS: 127.0.0.1:8080
# NO: 0.0.0.0:8080

5. Compila, inicia, siembra la base de datos​

docker compose --profile rtorrent up -d --build
docker compose exec backend npx prisma db seed

6. Pon un proxy al frente, con HTTPS​

Apunta el registro A de tu dominio a la IP de la instancia y luego — el camino correcto más corto:

sudo apt install -y caddy
# /etc/caddy/Caddyfile
torrents.example.com {
encode gzip
reverse_proxy 127.0.0.1:8080
}
sudo systemctl reload caddy

Caddy obtiene el certificado, redirige de HTTP a HTTPS, renueva automáticamente y hace de proxy de los WebSockets de forma transparente. Otros proxies (NGINX, Traefik, HAProxy): Proxy inverso. Los certificados a fondo: TLS.

7. Inicia sesión​

https://torrents.example.com → inicia sesión como admin.

De inmediato: cambia la contraseña de admin desde el menú de perfil y habilita la autenticación de dos factores. Este login está en el internet público. Ver Seguridad y Usuarios.

Luego agrega el motor: Infraestructura → Motores → Agregar motor → rTorrent · SCGI sobre TCP · host rtorrent · puerto 5000 → Probar conexión → Agregar motor. Y Configuración → Ruta raíz predeterminada → /downloads.

Verificación​

# Nada peligroso está escuchando públicamente
sudo ss -tlnp | grep -E '0\.0\.0\.0:(8080|4000|5000)'
# ^ esto no debe imprimir NADA

# La app responde por HTTPS
curl -s https://torrents.example.com/api/system/live
curl -s https://torrents.example.com/api/system/version

Confirma que el WebSocket hace upgrade a través del proxy — de lo contrario la UI se verá bien y nunca se actualizará:

curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
https://torrents.example.com/ws/
HTTP/1.1 101 Switching Protocols

Desde otra computadora, comprueba que los puertos crudos están cerrados:

curl -m 5 http://<public-ip>:8080 # tiene que dar timeout / ser rechazado
curl -m 5 http://<public-ip>:4000 # tiene que dar timeout / ser rechazado

El Panel de UltraTorrent servido por HTTPS desde un VPS

Proxy inverso​

Obligatorio. Ver Proxy inverso. El upgrade de WebSocket no es opcional — la UI en vivo depende de él.

HTTPS​

Obligatorio. Let's Encrypt vía Caddy es el camino más corto; certbot + NGINX es el clásico. Ver TLS.

Actualizaciones​

cd ultratorrent
docker compose exec -T postgres pg_dump -U ultratorrent ultratorrent > backup-$(date +%F).sql
# copia el dump FUERA de la instancia:
scp backup-$(date +%F).sql you@home:/backups/

git pull
docker compose --profile rtorrent up -d --build
docker compose exec backend npx prisma db seed

Toma un snapshot del proveedor de la instancia antes de una actualización — es el equivalente en la nube de un snapshot de Proxmox y te da una reversión de la máquina completa. Procedimiento completo: Actualizar.

Mantén el SO parchado: unattended-upgrades ya lo está haciendo si lo instalaste en el paso 2.

Copias de seguridad​

Fuera de la instancia o no cuentan.

# Cada noche: haz el dump y luego mándalo a otro lugar
docker compose exec -T postgres pg_dump -U ultratorrent ultratorrent \
| gzip > /mnt/downloads/backups/ut-$(date +%F).sql.gz

# luego sácalo de la máquina con rclone/scp/s3

Respalda también el .env — sin el ENCRYPTION_KEY, los secretos de 2FA guardados son irrecuperables.

Los snapshots del proveedor son convenientes, pero viven en la misma cuenta que un compromiso de seguridad o un fallo de facturación se llevaría por delante. Guarda una copia en otro lugar. Ver Copias de seguridad y restauración.

Resolución de problemas​

SíntomaCausaSolución
La compilación muere por falta de memoria (OOM)La instancia es muy pequeña — 1–2 GB de RAMRedimensiona a 4 GB, o agrega swap y recompila lentamente
Puerto abierto en la consola de la nube y aun así inalcanzableTambién hay un firewall del host en el medio (ufw, o las iptables horneadas de Oracle)Ábrelo también localmente: ufw allow 443/tcp, o iptables -I INPUT ... && netfilter-persistent save
ufw deny 8080 no hace nada — el 8080 sigue accesibleDocker se salta ufw escribiendo sus propias reglas de iptables para los puertos publicadosNo lo publiques: enlázalo a 127.0.0.1:8080 y confía en el firewall de la nube
Falla la emisión del certificadoEl puerto 80 está bloqueado, o el DNS no ha propagadoAbre el 80 en ambos firewalls; verifica que el registro A realmente resuelva
Factura de ancho de banda escandalosaEstás compartiendo (seeding) en un proveedor que cobra el egress por GBLimita la tasa de subida, detén los seeds completados, configura una alarma de facturación, múdate a un proveedor de tarifa plana
La instancia no arranca tras agregar un volumenUna entrada en fstab sin nofailAgrega nofail; recupera vía la consola serial/de rescate
Disco de descargas lleno, el stack se degradaUsaste el disco de arranque para las descargas, o el volumen se llenóLas descargas van en almacenamiento en bloque; monitorea el espacio libre
La UI carga por HTTPS pero nunca se actualizaEl WebSocket no está haciendo upgrade a través del proxyCorre la prueba de 101 Switching Protocols de arriba; ver Proxy inverso
Intentos de fuerza bruta en los logsEs una página de login públicaADMIN_PASSWORD fuerte, habilita 2FA, fail2ban, y considera autenticación a nivel del proxy
Cuenta suspendidaAUP del proveedor / DMCAEs un problema de política, no técnico. Lee la AUP antes de desplegar

Más: Resolución de problemas · Seguridad.

Mejores prácticas​

  • Nunca publiques el 8080, el 4000 ni el 5000 al internet. Enlaza a 127.0.0.1 y pon un proxy al frente.
  • Dos firewalls: el de la nube y el del host. Recuerda que Docker atraviesa ufw para los puertos publicados.
  • HTTPS desde el día uno. Una página de login en HTTP plano en el internet público manda tu contraseña en texto claro.
  • Habilita 2FA en la cuenta de admin de inmediato.
  • SSH: solo llaves, sin login de root, fail2ban.
  • Conoce el precio de tu egress y configura una alarma de facturación antes de compartir nada.
  • Limita la tasa de subida en un proveedor que mide el tráfico.
  • Almacenamiento en bloque para las descargas, con nofail en el fstab.
  • Manda las copias de seguridad fuera de la instancia.
  • Parcha el SO automáticamente (unattended-upgrades).
  • Lee la AUP del proveedor. Ese es el riesgo que acaba con el proyecto, no un puerto mal configurado.
  • Prefiere qBittorrent si vas a manejar una biblioteca grande en una máquina remota a la que no le vas a estar pendiente.

Preguntas frecuentes​

¿Cuál proveedor es el más barato para esto? Los proveedores de tarifa plana o con tráfico generoso (Hetzner y similares) le ganan dramáticamente a los hiperescaladores que cobran el egress por GB cuando la carga de trabajo consume mucho ancho de banda. Eso es un hecho aritmético, no una preferencia.

¿Puedo usar la capa gratuita de Oracle? Sí — Ampere A1 es ARM64 y las imágenes son multiarquitectura. Espera dolores de cabeza con la capacidad, y acuérdate de las reglas de iptables horneadas en la imagen.

¿Alcanza con un droplet de 1 GB? No. Solo la compilación quiere ~2 GB libres. Usa 4 GB.

¿Esto es un seedbox? Puede serlo. Si tu proveedor está contento con eso es una pregunta que solo su AUP puede contestar.

¿Necesito un dominio? Para HTTPS, en la práctica sí. Let's Encrypt no emite certificados para una IP pelada.

¿Cómo evito que le hagan fuerza bruta al login de admin? Contraseña fuerte, 2FA, fail2ban y, opcionalmente, una capa de autenticación en el proxy (Cloudflare Access, basic auth). Ver Seguridad.

¿Puedo ponerlo detrás de Cloudflare? Para la interfaz web, sí — un Tunnel incluso evita abrir cualquier puerto de entrada. Ver Proxy inverso. El tráfico de pares de BitTorrent no pasa por Cloudflare.

Lista de verificación​

  • AUP del proveedor leída y entendida
  • Instancia de ≥ 2 vCPU / 4 GB de RAM
  • Almacenamiento en bloque conectado para las descargas, montado con nofail
  • Firewall de la nube: 22 (tu IP), 80, 443 — nada más
  • Firewall del host habilitado también (y las iptables locales de Oracle, si aplica)
  • Solo llaves SSH; login de root apagado; fail2ban instalado
  • unattended-upgrades instalado
  • .env: POSTGRES_PASSWORD alfanumérica, ADMIN_PASSWORD fuerte, tres secretos distintos, CORS_ORIGIN = tu origen HTTPS
  • Frontend enlazado a 127.0.0.1:8080 — verificado con ss -tlnp
  • Proxy inverso + certificado TLS válido
  • /ws/ devuelve 101 Switching Protocols a través del proxy
  • curl http://<public-ip>:8080 desde afuera falla (como debe ser)
  • Contraseña de admin cambiada y 2FA habilitada
  • Alarma de facturación configurada; tasa de subida limitada si el egress se mide
  • Copias de seguridad corriendo y enviadas fuera de la instancia

Ver también​