Saltar al contenido principal

Backup y Restauración

Un backup sin probar es un rumor. Esta página te dice qué es de verdad irreemplazable, cómo capturarlo, y — la parte que todo el mundo se salta — cómo probar que lo puedes restaurar.

Propósito​

Poder perder el host completo y estar corriendo de nuevo, con tus usuarios, bibliotecas, reglas e historial intactos.

Cuándo usar esto​

  • Ahora. Antes de que lo necesites.
  • Antes de cualquier actualización (ver Actualizar).
  • Antes de rotar ENCRYPTION_KEY o de hacerle cirugía a la base de datos.
  • Antes de mudarte a un servidor nuevo.

Requisitos previos​

  • Acceso a la shell del host de Docker.
  • Un lugar donde poner los backups que no sea el host que estás respaldando.
Mira este tutorial

Video próximamente.

Conceptos​

Qué es de verdad irreemplazable​

Sé preciso con esto. Respaldar las cosas equivocadas desperdicia almacenamiento; respaldar muy pocas pierde tu instalación.

ElementoDónde vive¿Respaldarlo?Por qué
PostgreSQLvolumen postgres_dataSí — críticoCada pieza de estado duradero. Usuarios, roles, motores, bibliotecas, elementos de medios, listas de seguimiento, fuentes y reglas RSS, reglas de automatización, trabajos, el registro de auditoría.
.envRaíz del repo, en el hostSí — críticoContiene ENCRYPTION_KEY. No está en tu dump de la base de datos.
Medios / descargasvolumen downloadsSí, si lo valorasTus medios de verdad. También contiene la sesión de rTorrent en /downloads/.session.
Config de Prowlarrvolumen prowlarr_configRecomendadoDefiniciones y ajustes de indexadores. Reconstruible, pero tedioso.
Config de qBittorrentvolumen qbittorrent_configRecomendadoAjustes del motor + la sesión de torrents.
Redisvolumen redis_dataNoCaché y broker de trabajos. Sin estado duradero.
Catálogo de IMDbDentro de PostgresViene gratis con el dump de la DBEstá en el dump. Si lo excluyes para ahorrar espacio, lo puedes reimportar desde los datasets.
El archivo .env es la mitad de tu backup

ENCRYPTION_KEY cifra los secretos TOTP, las claves API de los indexadores, la clave de Prowlarr y las contraseñas de los motores en reposo, dentro de la base de datos. Un dump de Postgres sin el .env restaura esas columnas como texto cifrado indescifrable. Tendrías tus usuarios y tus bibliotecas, y ningún 2FA ni clave API que sirva.

Guarda el .env en un gestor de contraseñas o en un almacén de secretos, fuera del host.

Las dos estrategias de backup​

EstrategiaQué esA favorEn contra
Dump lógico (pg_dump) — recomendadoUna exportación de la base de datos en SQL o en formato customPortátil entre versiones y arquitecturas de Postgres; se puede tomar en caliente, con el stack corriendo; comprime bienMás lento de restaurar con un catálogo de IMDb muy grande
Snapshot de volumenCopiar el directorio postgres_dataRápidoHay que detener la base de datos primero o queda inconsistente; no es portátil entre versiones mayores de Postgres

Usa pg_dump. Usa los snapshots de volumen solo como un complemento.

Pasos​

1. Respalda PostgreSQL​

El formato custom (-Fc) va comprimido y restaura selectivamente — prefiérelo.

cd /path/to/ultratorrent

# Backup en caliente — el stack puede seguir corriendo.
docker compose exec -T postgres \
pg_dump -U ultratorrent -d ultratorrent -Fc \
> "ultratorrent-$(date +%F-%H%M).dump"

Una variante en SQL plano, si quieres algo que puedas leer y pasarle grep:

docker compose exec -T postgres \
pg_dump -U ultratorrent -d ultratorrent \
| gzip > "ultratorrent-$(date +%F-%H%M).sql.gz"
Excluir el catálogo de IMDb

El catálogo de IMDb puede tener 8.9 millones de filas y va a dominar el tamaño de tu dump. Es totalmente reimportable desde los datasets de IMDb, así que lo puedes excluir:

docker compose exec -T postgres \
pg_dump -U ultratorrent -d ultratorrent -Fc \
--exclude-table-data='imdb_titles' \
--exclude-table-data='imdb_episodes' \
--exclude-table-data='imdb_akas' \
> "ultratorrent-slim-$(date +%F).dump"

El esquema sigue incluido — solo se salta la data de las filas. Después de restaurar, reimporta los datasets desde Medios → Ajustes → IMDb, y deja que los índices de trigramas se reconstruyan (se construyen CONCURRENTLY en segundo plano durante el arranque). Tu lista de seguimiento conserva sus ids de IMDb de todos modos, porque esos viven en tus tablas.

2. Respalda el .env​

cp .env "env-backup-$(date +%F)"
# ...luego muévelo a un lugar seguro y FUERA de este host.

Mejor todavía: pégalo en tu gestor de contraseñas. Es pequeño y es la diferencia entre una instalación recuperable y una irrecuperable.

3. Respalda los medios (opcional, pero casi siempre lo quieres)​

# Encuentra dónde vive de verdad el volumen downloads
docker volume inspect ultratorrent_downloads --format '{{ .Mountpoint }}'

# Luego sincronízalo a otro lado (rsync, restic, borg, un share de NAS, ...)
sudo rsync -aHAX --info=progress2 \
"$(docker volume inspect ultratorrent_downloads --format '{{ .Mountpoint }}')/" \
/mnt/backup/ultratorrent-downloads/

Si montaste un directorio del host para las descargas en vez de usar el volumen nombrado, respalda ese directorio directamente — ya sabes dónde está.

4. Respalda los volúmenes de los acompañantes (opcional)​

for v in prowlarr_config qbittorrent_config; do
docker run --rm \
-v "ultratorrent_${v}:/data:ro" \
-v "$(pwd):/backup" \
alpine tar czf "/backup/${v}-$(date +%F).tar.gz" -C /data .
done

5. Automatízalo​

Un cron nocturno mínimo que conserva 14 días:

# /etc/cron.d/ultratorrent-backup
0 3 * * * root cd /path/to/ultratorrent && \
docker compose exec -T postgres pg_dump -U ultratorrent -d ultratorrent -Fc \
> /mnt/backup/ultratorrent-$(date +\%F).dump && \
find /mnt/backup -name 'ultratorrent-*.dump' -mtime +14 -delete
Cron y $(date)

Los signos de por ciento hay que escaparlos (\%) en los archivos de crontab. Esto le pasa a todo el mundo una vez.

Restauración​

Restaurar la base de datos​

# 1. Detén la app para que nada escriba mientras restauras.
docker compose stop backend

# 2. Elimina y vuelve a crear la base de datos.
docker compose exec -T postgres \
psql -U ultratorrent -d postgres -c "DROP DATABASE IF EXISTS ultratorrent;"
docker compose exec -T postgres \
psql -U ultratorrent -d postgres -c "CREATE DATABASE ultratorrent OWNER ultratorrent;"

# 3. Restaura el dump.
docker compose exec -T postgres \
pg_restore -U ultratorrent -d ultratorrent --no-owner --clean --if-exists \
< ultratorrent-2026-07-11-0300.dump

# 4. Levanta el backend de nuevo. Corre `prisma migrate deploy` al arrancar,
# así que un dump de una versión MÁS VIEJA se migra hacia adelante automáticamente.
docker compose up -d backend

Para un dump en SQL plano:

gunzip -c ultratorrent-2026-07-11.sql.gz | \
docker compose exec -T postgres psql -U ultratorrent -d ultratorrent

Restaurar el .env​

Pon el archivo de vuelta en la raíz del repo, y luego recrea:

docker compose up -d --force-recreate backend
Restaura el ENCRYPTION_KEY ORIGINAL

Si restauras un dump de la base de datos pero le pones un ENCRYPTION_KEY distinto, cada secreto TOTP y cada clave API de ese dump quedan indescifrables. El .env y el dump son un par pareado. Restáuralos juntos.

Simulacro de restauración​

Haz esto una vez, ahora. Un backup que nunca has restaurado no es un backup.

El simulacro, en un host desechable o en un segundo proyecto de Compose:

# 1. Directorio nuevo, mismo repo, MISMO .env (ese es el punto).
git clone https://github.com/ultratorrentofficial/ultratorrent.git drill
cd drill
cp /path/to/backup/env-backup-2026-07-11 .env

# 2. Levanta SOLO los almacenes de datos.
docker compose up -d postgres redis

# 3. Espera por Postgres, y luego restaura.
until docker compose exec -T postgres pg_isready -U ultratorrent; do sleep 1; done
docker compose exec -T postgres \
pg_restore -U ultratorrent -d ultratorrent --no-owner --clean --if-exists \
< /path/to/backup/ultratorrent-2026-07-11.dump

# 4. Levanta la app.
docker compose up -d --build backend frontend

Ahora verifica — este es el simulacro de verdad:

  • La UI carga y puedes iniciar sesión con tu contraseña real.
  • El 2FA funciona en una cuenta que lo tenía. (Esto prueba que el ENCRYPTION_KEY calzó. Si el 2FA falla, tu .env y tu dump no coinciden — el fallo de backup roto más común que hay.)
  • Tus usuarios y roles están presentes.
  • Tus bibliotecas y elementos de medios están presentes.
  • Tus fuentes RSS y reglas están presentes.
  • Una prueba de conexión de indexador pasa. (Esto también prueba que la clave de cifrado calzó — la clave API se descifró.)
  • El registro de auditoría tiene tu historial adentro.

Después tumba el simulacro (docker compose down -v — seguro, es desechable).

Si alguna de esas falla, tu backup está roto y te acabas de enterar barato.

Recuperación ante desastres​

El host ya no está. Reconstruye desde cero.​

Secuencia completa:

# 1. Host nuevo, con Docker instalado.
git clone https://github.com/ultratorrentofficial/ultratorrent.git ultratorrent
cd ultratorrent

# 2. Restaura el .env — el ORIGINAL, con el ENCRYPTION_KEY ORIGINAL.
# (Desde tu gestor de contraseñas. Lo respaldaste. ¿Verdad?)

# 3. Los almacenes de datos primero.
docker compose up -d postgres redis
until docker compose exec -T postgres pg_isready -U ultratorrent; do sleep 1; done

# 4. Restaura la base de datos.
docker compose exec -T postgres \
pg_restore -U ultratorrent -d ultratorrent --no-owner --clean --if-exists \
< /mnt/backup/ultratorrent-latest.dump

# 5. Restaura los medios (si los respaldaste), dentro del volumen downloads.
docker volume create ultratorrent_downloads
sudo rsync -aHAX /mnt/backup/ultratorrent-downloads/ \
"$(docker volume inspect ultratorrent_downloads --format '{{ .Mountpoint }}')/"

# 6. Todo arriba.
docker compose --profile qbittorrent up -d --build

# 7. Verifica.
docker compose exec backend wget -qO- http://127.0.0.1:4000/api/system/live

Después de cualquier restauración, espera esto​

CosaEsperaHaz
MigracionesEl backend corre prisma migrate deploy en el arranque, así que un dump más viejo se migra hacia adelante automáticamenteNada — pero vigila el log
P3009 en el arranquePosible si una migración se interrumpeResuélvelo
Trabajos huérfanosCualquier trabajo que estuviera running en el dumpSe reconcilian solos en el arranque — se marcan como fallidos con Interrupted by a service restart
Índices de trigramas de IMDbSe reconstruyen CONCURRENTLY en segundo plano durante el arranqueNada. Las búsquedas van lentas hasta que terminen
MotoresLas filas de los motores se restauran, pero los containers de los motores son nuevosVuelve a probar la conexión bajo Infraestructura → Motores
Sesión de torrentsVive en el motor, no en PostgresRestaura el volumen downloads (la sesión de rTorrent está en /downloads/.session) o el volumen de config de qBittorrent
Rutas de las bibliotecasSe restauran tal como estabanSi las rutas del host nuevo son distintas, reapunta las bibliotecas
La sesión de torrents no está en la base de datos

La base de datos de UltraTorrent registra lo que sabe sobre los torrents; el motor guarda la sesión de verdad. Restaurar solo Postgres te devuelve tus reglas, bibliotecas e historial — pero el motor va a arrancar con ningún torrent cargado a menos que también restaures su sesión (el volumen downloads para rTorrent, o qbittorrent_config para qBittorrent).

Solución de problemas​

Síntoma después de una restauraciónCausaSolución
El login funciona, el 2FA noEl ENCRYPTION_KEY no coincide con el dumpRestaura el .env original
Rechazan las claves del indexador/ProwlarrLo mismo — clave que no coincideLo mismo, o vuelve a ingresar las claves
El backend entra en bucle de reinicios, P3009Migración interrumpidaResuélvelo
El backend entra en bucle de fallos, P1000El volumen postgres_data nuevo se inicializó con otra contraseñaP1000
Todo está lento por un ratoLos índices de trigramas todavía se están construyendo en segundo planoEspera. Revisa indisvalid
El motor no muestra torrentsRestauraste la DB pero no la sesión del motorRestaura el volumen downloads / qbittorrent_config
pg_restore da errores sobre la propiedadEl dump lo hizo otro rolAñade --no-owner (los comandos de arriba lo hacen)

Consejos​

  • Prueba la restauración, no el backup. Que pg_dump salga con 0 no te dice casi nada.
  • Mantén el .env y el dump juntos, o al menos mantenlos en sincronía. Son un par pareado.
  • Respalda antes de cada actualización. Cuesta 30 segundos y es la diferencia entre un rollback y un incidente.
  • Excluye el catálogo de IMDb si el tamaño del dump te molesta — es reimportable.
  • No respaldes Redis. No te sirve de nada.

Preguntas frecuentes​

¿Puedo respaldar con el stack corriendo? Sí. pg_dump toma un snapshot consistente sin detener nada. Los snapshots de volumen, en cambio, requieren detener Postgres primero.

¿Necesito respaldar Redis? No. Es un caché y un broker de trabajos sin estado duradero.

¿Puedo restaurar un dump de una versión más vieja? Sí. El backend corre prisma migrate deploy en el arranque, así que el esquema se migra hacia adelante automáticamente. Restaurar un dump más nuevo en una versión más vieja de la app no está soportado.

¿De qué tamaño va a ser mi dump? Dominado por el catálogo de IMDb si lo importaste (8.9M+ filas). Sin él, el dump de una instalación típica es pequeño — megabytes, no gigabytes.

Perdí mi .env. ¿Qué tan malo es? Tus torrents, bibliotecas, usuarios e historial están todos bien. Pero cada valor cifrado en reposo — secretos TOTP, claves API de indexadores, la clave de Prowlarr, las contraseñas de los motores — es permanentemente ilegible. Pon un ENCRYPTION_KEY nuevo, haz que los usuarios vuelvan a inscribir el 2FA, y vuelve a ingresar las claves. Ver Seguridad → Rotar secretos.

¿Debo respaldar las imágenes de Docker? No. Se reconstruyen desde el código.

Lista de verificación​

Configúralo

  • Un pg_dump nocturno corre automáticamente
  • Los backups aterrizan fuera del host
  • El .env está guardado en un gestor de contraseñas / almacén de secretos
  • Los backups viejos se podan (para que el disco no se llene)
  • Los medios están respaldados, o has aceptado conscientemente perderlos

Pruébalo

  • Has corrido el simulacro de restauración al menos una vez
  • En el simulacro, el 2FA funcionó (esa es la prueba del ENCRYPTION_KEY)
  • En el simulacro, una prueba de indexador pasó
  • Sabes cuánto se tarda una restauración completa

Antes de cada actualización

  • Dump fresco tomado
  • Copia del .env tomada

Ver también​