Un servidor blade negro mate e iluminado en un centro de datos a oscuras, que emite una cinta de partículas de datos color esmeralda hacia un duplicado de sí mismo en wireframe luminoso, sellado por un candado luminoso
Guía de copias de seguridad

Hacer backup de un VPS que de verdad se puede restaurar

Casi todo el que administra un servidor tiene algo a lo que llama copia de seguridad. Muy pocos la han restaurado alguna vez, y la distancia entre esas dos frases es exactamente donde desaparecen los datos de verdad. Esto es cómo construir una copia que sobreviva a las tres cosas que de verdad destruyen los servidores — sus propias manos, un compromiso de seguridad y una cuenta que deja de controlar — sin acabar pegando, sin darse cuenta, una identidad verificada a una máquina anónima.

Mantenemos tres copias de cada byte que hace funcionar esta red, y hemos restaurado desde ellas, a propósito, un martes cualquiera, más veces de las que jamás hemos necesitado hacerlo en una emergencia real. Eso no es diligencia porque sí. Es la única manera de saber que lo que hay en el repositorio es una copia de seguridad, y no una carpeta de ruido cifrado con un nombre tranquilizador.

Los consejos que siguen son deliberadamente pasados de moda. No implican un producto de backup con panel de control, suscripción mensual ni cola de soporte, porque todas esas cosas son, en el fondo, una cuenta — y una cuenta es un nombre, una tarjeta y una jurisdicción: tres cosas en las que quizá se haya esforzado de verdad por mantener alejadas de este servidor. Implican una segunda máquina, unas cuarenta líneas de shell, y un hábito que casi nadie mantiene.

Debería poder completar todo esto en una tarde. Las herramientas están orientadas a Debian 13 y Ubuntu 24.04; todo se traslada a derivados de RHEL con las sustituciones obvias. Si su servidor es nuevo, haga el endurecimiento de la primera hora antes de esta página y no después — hacer una copia de seguridad de una máquina que ya es de otro es una forma de preservar su trabajo.

Qué es lo que realmente destruye los datos en un servidor alquilado

Pregunte a cualquiera por qué hace copias de seguridad y la respuesta suele ser “por si se estropea el disco”. En un VPS moderno, eso está cerca de ser lo menos probable que le vaya a pasar. Su volumen vive en NVMe dentro de una matriz redundante, con un hipervisor que le migrará fuera de un host que esté fallando antes de que usted lo note; el fallo de disco es problema del proveedor, y es un problema ya resuelto. Construir toda su estrategia de copias de seguridad alrededor de eso es como comprar un extintor para una casa que se inunda.

Esto es lo que de verdad se lleva por delante los datos de la gente, más o menos por orden de frecuencia. Primero, y por un margen amplio: usted. Un rm -rf con una variable que se expandió a nada. Un DROP DATABASE en la terminal equivocada porque dos pestañas parecían idénticas. Un script de migración ejecutado dos veces. Un docker compose down -v en el que la -v fue memoria muscular. Esto no es exótico; es un martes cualquiera.

Segundo, aplicaciones que borran sus propios datos. Una actualización que ejecuta una migración destructiva y falla a mitad de camino. Un plugin que vacía un directorio de caché que resultó no ser una caché. Una rotación de logs configurada contra la ruta equivocada. Tercero, el compromiso de seguridad — y note que este es el caso en el que un atacante quiere que las copias de seguridad desaparezcan, lo cual cambia el diseño de formas a las que volveremos más abajo. Cuarto, y fácil de olvidar en un hosting no-KYC: perder la cuenta. Un saldo que llegó a cero mientras usted estaba fuera, una entrada del gestor de contraseñas que nunca anotó, una dirección de correo que abandonó. Nosotros suspendemos a las pocas horas de un saldo a cero y destruimos a los siete días, y eso es deliberadamente inflexible — es la aritmética que nos permite no preguntar quién es usted. No hay ningún agente de soporte que pueda consultar su identidad y hacer una excepción, porque no hay ninguna identidad que consultar.

Esa última categoría es la que separa el hosting centrado en la privacidad del hosting convencional, y debería determinar su plan. Todo control que hace que este servidor sea difícil de atribuirle a usted también hace difícil que nadie — nosotros incluidos — pueda devolvérselo. La copia de seguridad es lo que convierte ese intercambio de un riesgo en una elección.

Por qué un snapshot no es una copia de seguridad

Los snapshots son maravillosos y debería usarlos. Tome uno antes de cada actualización de kernel, cada migración de base de datos, cada vez que esté a punto de hacer algo que preferiría poder deshacer. Se restauran en segundos, cuestan casi nada, y le salvarán una tarde una docena de veces al año.

Aun así, no son copias de seguridad, por tres razones estructurales que ningún marketing de proveedor cambia. Viven dentro de la misma cuenta: quien pueda entrar en su panel puede borrarlos, y si la cuenta deja de funcionar, los snapshots dejan de existir con ella. Viven en el mismo dominio de fallo: mismo proveedor, mismo plano de control, a menudo el mismo clúster de almacenamiento, lo que significa que un único incidente puede perfectamente llevarse tanto el original como la copia. Y son opacos: el snapshot de una máquina en marcha captura una base de datos a mitad de una escritura con la misma fidelidad con la que captura todo lo demás, así que restaurar un snapshot de un servidor MySQL con actividad le da un escenario de recuperación ante fallos, no una base de datos limpia.

La vieja regla 3-2-1 — tres copias, en dos tipos de soporte, una de ellas remota — se suele recitar sin reparar en que la cláusula del medio no significa nada en infraestructura alquilada. Usted no tiene dos tipos de soporte. Tiene un dispositivo de bloques virtual, y otro dispositivo de bloques virtual, y los dos son la SAN de otra persona. Lo que sobrevive al trasladar la regla a un VPS es la parte que siempre importó de verdad: al menos una copia debe estar en algún sitio al que un único incidente no pueda llegar. Proveedor distinto, o como mínimo región distinta, credenciales distintas, cuenta distinta, y — si el motivo por el que aloja su servidor offshore es legal y no técnico — jurisdicción distinta, para que una sola orden judicial no alcance las dos copias a la vez.

El destino forma parte de su modelo de amenazas

Esta es la sección que no tienen otros tutoriales de copias de seguridad, y es la que más importa si pagó este servidor en Monero.

El consejo por defecto en todo internet es hacer push de sus copias de seguridad a un almacenamiento de objetos: Backblaze B2, Amazon S3, Wasabi, un Google Drive vía rclone. Es barato, es duradero, funciona. También, en un solo comando, deshace buena parte de lo que estaba usted intentando conseguir. Abrir esa cuenta exigió una tarjeta y, normalmente, un documento de identidad. Desde el momento en que se sube el primer snapshot, ese proveedor guarda un registro con marca de tiempo que asocia su nombre y sus datos de pago con la dirección IP de su servidor, actualizado cada hora, para siempre. Usted no verificó su identidad con nosotros; la verificó con ellos, y después trazó una línea entre los dos.

La segunda mitad es peor, y es la parte que se le escapa a la gente. La clave de API que autoriza esas subidas es un archivo en el servidor de producción. Cualquiera que consiga root en esa máquina — o cualquiera que adquiera el disco por vías legales — no solo obtiene sus datos. Obtiene una credencial que resuelve, en una sola llamada a la API, una identidad de facturación. El servidor anónimo se ha convertido en un cartel que señala directamente a su banco.

Nada de esto convierte el almacenamiento de objetos en algo incorrecto. Lo convierte en una decisión, en lugar de en algo por defecto. Hay tres salidas, en orden descendente de lo bien que preservan aquello con lo que empezó:

  • Un segundo VPS no-KYC, idealmente en una jurisdicción distinta de la de producción, pagado con el mismo saldo en cripto. El destino hereda las propiedades de anonimato del origen en lugar de contradecirlas. Esto es lo que hacemos nosotros y lo que asume el resto de esta guía.
  • Un proveedor de almacenamiento que acepte cripto sin identidad. Existen; son más pequeños; compruebe si la vía de pago es de verdad libre de identidad antes de fiarse del marketing, y revise el precio del tráfico de salida antes de descubrirlo durante una restauración.
  • Una máquina que posea físicamente, que haga pull a través de WireGuard desde detrás de su propia conexión. Excelente para el anonimato, pobre para la disponibilidad, y significa que su velocidad de restauración es la velocidad de subida de su conexión doméstica. Razonable como tercera copia, débil como única copia.

Elija lo que elija, la cuenta que guarda las copias de seguridad no debería compartir credenciales, dirección de correo ni vía de recuperación con la cuenta que aloja la producción. Todo el sentido de esto es que un inicio de sesión comprometido no pueda alcanzar a ambas. Es la misma disciplina que mantener las identidades separadas en cualquier otro sitio, aplicada al rincón menos glamuroso del sistema.

Push, pull, y la razón por la que el ransomware encuentra sus copias de seguridad

Casi todos los tutoriales de copias de seguridad producen la misma arquitectura: una tarea de cron en el servidor de producción que se autentica contra un repositorio remoto y escribe en él. Es simple, funciona, y tiene una propiedad que nadie menciona — el servidor de producción guarda una credencial capaz de borrar el repositorio entero. Podar snapshots antiguos exige permisos de borrado, así que la clave que ejecuta su tarea nocturna es también la clave que vacía la bóveda.

Piense en lo que eso significa durante un compromiso de seguridad. Un atacante con root en la máquina no necesita encontrar sus copias de seguridad; usted, amablemente, le ha dejado una credencial funcional y un archivo de configuración que indica dónde está el repositorio. Enumerar y destruir las copias de seguridad antes de disparar nada visible no es un refinamiento hipotético — es práctica habitual, porque es lo que convierte un incidente en una negociación. Su tarea nocturna era el reconocimiento previo.

Hay tres diseños posibles, y la diferencia entre ellos es enteramente una cuestión de qué máquina guarda qué clave.

El push simple es el de arriba. Producción tiene lectura, escritura y borrado. Cómodo, y falla por completo justo en el escenario en el que más necesita una copia de seguridad. Úselo solo si la única amenaza que de verdad le preocupa son sus propios dedos.

El push append-only conserva la misma forma pero elimina el verbo peligroso. El repositorio lo sirve algo que entiende el protocolo y rechaza los borrados: rest-server --append-only para restic, o borg serve --append-only forzado desde authorized_keys. Producción puede crear snapshots nuevos y no puede eliminar los antiguos. La poda ocurre más tarde, desde otro sitio, usando una clave distinta. Es una mejora grande por unos veinte minutos de trabajo, y para la mayoría de la gente es el punto correcto donde detenerse.

El pull invierte la conexión. El host de backup se conecta a producción por SSH, copia lo que necesita, y ejecuta la herramienta de copia de seguridad de forma local, en su propio disco. Producción no guarda ninguna credencial de backup — no hay nada que encontrar en esa máquina, porque la máquina ni siquiera sabe dónde viven sus copias de seguridad. Es el arreglo más sólido de los tres, y es lo que construye la guía paso a paso de más abajo.

Sea honesto sobre lo que cuesta el pull, porque no es gratis. Ha movido la clave, no la ha eliminado: el host de backup ahora guarda una clave SSH hacia producción, así que un compromiso del host de backup se propaga hacia delante, hasta el sistema en producción. Es un intercambio mejor — el host de backup no ejecuta nada, no expone nada más que SSH, y es un objetivo muchísimo más pequeño que un servidor web público — pero sigue siendo un intercambio, y cierra la mayor parte de la brecha restante al forzar esa clave a un comando de solo lectura, de modo que no se pueda usar para nada más que leer archivos.

Elegir la herramienta: restic, Borg o rsync a secas

Tres herramientas cubren, en esencia, todos los casos, y elegir es menos angustioso de lo que sugieren los hilos de los foros.

restic cifra por defecto, deduplica entre snapshots, habla SFTP, S3, REST y una docena más de backends, y se distribuye como un único binario estático que puede colocar en cualquier sitio. Su formato de repositorio está direccionado por contenido, así que un snapshot sale barato y los datos idénticos se guardan una sola vez, sin importar cuántas máquinas los envíen. Los costes son reales pero modestos: necesita memoria proporcional al índice del repositorio, y una ejecución interrumpida puede dejar un bloqueo obsoleto que la siguiente ejecución se niega a pasar por alto hasta que lo libere con restic unlock. Esta es la recomendación por defecto, y lo que usan los pasos de más abajo.

Borg deduplica mejor, comprime mejor, y es notablemente más rápido en repositorios con millones de archivos pequeños. Su contrapartida es el acoplamiento: Borg debe estar instalado en ambos extremos, con versiones que coincidan de cerca, un repositorio está realmente pensado para un solo cliente, y no tiene backend nativo de almacenamiento de objetos sin una capa auxiliar. Si su origen es un buzón de correo enorme o un sistema de archivos lleno de archivos pequeños, y controla ambas máquinas, Borg usará la mitad del espacio. Su modo --append-only es también la implementación más limpia de la idea, de las dos herramientas.

rsync no es una herramienta de copias de seguridad, y hacer como si lo fuera es la forma en la que la gente acaba con una copia fielmente reflejada de un directorio corrupto. No tiene versionado, ni deduplicación, ni cifrado en reposo; rsync --delete propaga su error a la copia a la velocidad del cable. Aun así, es la herramienta correcta para mover bytes entre dos máquinas que usted controla, que es precisamente el trabajo que hace en un diseño pull, con restic aportando el versionado y el cifrado una vez que los bytes han llegado. Use cada una para lo que es.

Una cosa que no debe hacer: no se invente su propio sistema con tar y un nombre de archivo con la fecha. Funciona durante unos cuatro meses, hasta el día en que el disco se llena porque nada caducó nunca, o el día en que descubre que una copia completa cada noche de un conjunto de datos de 40 GB son 1,2 TB al mes de almacenamiento que está pagando para guardar treinta cosas casi idénticas.

Qué incluir — y las bases de datos que le van a traicionar

El instinto es hacer una copia de seguridad de todo el sistema de archivos. Resístase. Un sistema de archivos raíz es, en su mayor parte, paquetes de la distribución que puede reinstalar en noventa segundos, e incluirlos cuesta almacenamiento, tiempo de transferencia y, peor aún, atención — una copia de seguridad de 40 GB que nadie quiere probar es menos útil que una de 900 MB que se restaura cada trimestre.

Lo que de verdad no se puede reconstruir es poco: /etc (toda su configuración, y la razón por la que una reconstrucción lleva una hora en lugar de un fin de semana), /home y /root, /srv y /var/www, el estado de las aplicaciones bajo /var/lib/ y /opt/, los volúmenes de Docker con nombre, las unidades de cron y systemd que usted escribió, y los volcados de sus bases de datos. Sáltese /proc, /sys, /dev, /run, /tmp, /var/cache, los archivos de swap, los sockets y /var/lib/docker/overlay2 — este último se puede reconstruir a partir de su archivo compose, y a menudo es el directorio individual más grande del disco.

Ahora la parte que arruina las restauraciones en silencio. Copiar el directorio de datos de una base de datos mientras la base de datos está en marcha produce un conjunto de archivos que muy probablemente sea inutilizable. El motor guarda estado en memoria, escribe en varios archivos en un orden que importa, y su copia recorre ese árbol durante varios minutos, capturando archivos distintos en instantes distintos. InnoDB a veces se recuperará del fallo al arrancar y a veces no; el fallo aflora meses después, durante una restauración en un día que ya iba mal de por sí.

En vez de eso, vuelque los datos a través del motor, y luego haga una copia de seguridad del volcado:

# MariaDB / MySQL — InnoDB gets a consistent snapshot from one transaction
mariadb-dump --single-transaction --quick --routines --triggers --events \
  --all-databases | zstd -T0 > /var/backups/db/all-$(date -u +%F).sql.zst

# PostgreSQL — pg_dump is consistent by design; grab roles separately
pg_dumpall --globals-only > /var/backups/db/globals.sql
pg_dump -Fc -Z6 mydb    > /var/backups/db/mydb.dump

# SQLite — never cp a live database; WAL mode makes that a torn file
sqlite3 /var/lib/app/app.db ".backup /var/backups/db/app.db"

Vale la pena tener presentes dos notas al pie. --single-transaction le da consistencia solo para InnoDB — si alguna tabla sigue siendo MyISAM, se copia fuera de la transacción y puede quedar inconsistente con el resto, así que convierta esas tablas o bloquéelas. Y, una vez que está volcando, excluya el directorio de datos en vivo del pase de archivos. Hacer copia de seguridad de ambos significa guardar una copia grande y rota junto a la buena, y darle a una futura restauración dos candidatos en los que uno está silenciosamente mal.

Los contenedores no cambian el principio, solo la ruta: ejecute el volcado con docker compose exec -T db mariadb-dump … y haga copia de seguridad del archivo resultante, no del volumen que hay debajo.

Dónde vive la clave de cifrado

El cifrado del lado del cliente es la razón entera por la que resulta aceptable guardar sus datos en una máquina distinta de aquella de donde vinieron. Tanto restic como Borg cifran antes de que nada salga del origen, así que el host de backup guarda solo texto cifrado y puede tratarse como almacenamiento no confiable. Esa propiedad vale exactamente lo que valga su forma de gestionar la clave, y ni un poco más.

El modo de fallo es deprimentemente común. La contraseña del repositorio vive en /etc/restic/env, en el servidor de producción, lo cual está bien y es necesario para la automatización. Entonces resulta que lo que pierde es precisamente producción — destruida, incautada, o simplemente desaparecida junto con la cuenta — y se encuentra mirando varios cientos de gigabytes de bloques cifrados, mientras cae en la cuenta de que la única copia de la clave estaba dentro de la cosa contra cuya pérdida se estaba protegiendo.

Así que: la contraseña en el servidor es una copia de trabajo, nunca el registro maestro. El registro maestro vive en algún sitio que sobrevive al servidor — un gestor de contraseñas cuya bóveda tiene, a su vez, copia de seguridad en otro lugar, o escrito en papel en un cajón, o ambas cosas. Anote la ubicación del repositorio y, al lado, el comando exacto de restauración, porque una passphrase sin contexto es un rompecabezas que va a estar resolviendo bajo presión dentro de dieciocho meses. Y dedique cinco minutos a verificarlo: desde una máquina distinta, con solo lo que hay en el gestor de contraseñas, ejecute restic snapshots contra el repositorio. Si funciona, tiene una copia de seguridad. Si necesita algo que solo existe en producción, tiene una carpeta muy cara.

Las dos herramientas admiten varias claves en un mismo repositorio (restic key add), que es la forma limpia de dar acceso a la tarea de poda o a un segundo administrador sin compartir la passphrase original. Y si el disco de producción está cifrado con LUKS, mantenga los dos secretos genuinamente separados — guardar la passphrase de restic dentro del volumen LUKS, y la passphrase de LUKS dentro del repositorio de restic, es un bucle que falla cerrado por los dos lados.

Retención: la trampa de guardar solo una semana

La retención parece una cuestión de coste de almacenamiento, pero en realidad es una cuestión de latencia de detección. El número que importa no es cuánto disco quiere gastarse; es cuánto tiempo puede pasar desapercibido un problema en su sistema. Sea cual sea ese periodo, su copia de seguridad más antigua tiene que ser más vieja que él.

Siete snapshots diarios parecen generosos y en la práctica se quedan cortos. Una tabla corrupta que nadie consulta, un borrado lento causado por una tarea de cron que se comporta mal, una intrusión que se quedó quieta durante un mes antes de hacer algo visible — todo esto tarda habitualmente más de una semana en salir a la luz, y si su historial tiene siete días de profundidad, entonces todos los snapshots que guarda ya están contaminados. El tiempo de permanencia en intrusiones reales se mide con regularidad en semanas. Los snapshots mensuales baratos son la defensa específica contra eso, y la deduplicación los hace realmente muy baratos: uno mensual conservado durante un año añade solo una fracción de una copia completa, porque únicamente los bloques que de verdad cambiaron se guardan por segunda vez.

restic forget \
  --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --keep-yearly 2 \
  --prune

Esa escalera — una semana de días, un mes de semanas, un año de meses, un par de años de años — son unos veintiséis snapshots y, con datos típicos, bastante menos del doble del tamaño de una única copia completa. Es la opción por defecto que defenderíamos, a menos que tenga una razón concreta para desviarse de ella.

Dos notas operativas. forget sin --prune solo elimina las etiquetas, así que el espacio no se recupera hasta que se hace la poda — lo cual sorprende a quien está mirando un disco que no se reduce. Y --prune exige permisos de borrado en el repositorio, así que en un diseño append-only o pull no se ejecuta en el servidor de producción. Se ejecuta en el host de backup, o desde su portátil, con una clave que producción nunca ha visto. Esa separación es todo el sentido de esto; no la deshaga por comodidad en el último paso.

Automatizarlo sin el fallo silencioso

El desastre clásico de las copias de seguridad no es una tarea que se cae. Es una tarea que deja de ejecutarse y no se lo dice a nadie, descubierta once meses después por alguien que la necesitaba. Cada elemento de más abajo existe para hacer imposible ese desenlace en concreto.

Use un timer de systemd en lugar de cron. Obtiene logs de verdad en el journal, con los códigos de salida adjuntos, Persistent=true para que una ejecución perdida mientras la máquina estaba apagada ocurra en el siguiente arranque en lugar de saltarse para siempre, y RandomizedDelaySec para que una flota entera no arrolle al host de backup a las 03:00 en punto. La notificación de fallo de cron es un correo a un buzón local que, en un servidor moderno, no va a ninguna parte.

# /etc/systemd/system/backup.timer
[Unit]
Description=Nightly encrypted backup

[Timer]
OnCalendar=*-*-* 03:17:00
RandomizedDelaySec=1800
Persistent=true

[Install]
WantedBy=timers.target

Después, añada un dead man's switch, que es la línea de mayor valor de toda esta guía. Al final mismo del script — después de que la copia de seguridad haya terminado con éxito, no antes — haga una petición HTTPS a un monitor que espera saber de usted cada día y avisa cuando no lo hace. Esto invierte la lógica de notificación: en lugar de depender de un fallo para generar un mensaje, la propia ausencia se convierte en la alarma. Una tarea que lleva tres días muerta se convierte entonces en un mensaje en su bandeja de entrada, en lugar de en un descubrimiento en plena crisis. Aloje usted mismo el monitor en el host de backup si prefiere no crear otra cuenta de terceros; son unas pocas líneas y un timer propio.

Por último, los pequeños riesgos operativos, todos ellos cosas con las que nos hemos topado al menos una vez. Una ejecución interrumpida deja un bloqueo, y cada ejecución posterior falla con un mensaje que deja de leer a partir de la cuarta noche — gestione restic unlock de forma deliberada, no por reflejo. Un disco de destino lleno hace fallar todas las tareas hasta que alguien se fija; active alertas sobre el espacio libre, no solo sobre el estado de la tarea. Una clave SSH con caducidad, una clave de host rotada, una regla de nftables añadida durante un trabajo sin relación alguna — cualquiera de ellas corta el pull en silencio. Y systemctl enable --now, no solo start: un timer que nunca se habilitó funciona de maravilla hasta el primer reinicio, y después no vuelve a ejecutarse jamás.

El simulacro de restauración

Todo lo anterior es preparación. Esta es la parte que lo convierte en una copia de seguridad de verdad, y es la parte que casi todo el mundo se salta.

Una vez por trimestre, despliegue un VPS nuevo — el Starter de $5 es más que suficiente, y la facturación es por hora y prorrateada al segundo, así que todo el ejercicio cuesta un par de céntimos. Restaure en él usando únicamente lo que tendría en un desastre real: la dirección del repositorio, la passphrase de su gestor de contraseñas, y el procedimiento escrito. No use nada de producción a propósito, porque en el escenario que está ensayando, producción no existe. Levante la aplicación, apunte una entrada del archivo hosts a la nueva IP, navegue un poco por ella. Luego destrúyalo.

# on a throwaway machine, with nothing but the passphrase
export RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/prod
restic snapshots                      # can you even see the history?
restic restore latest --target /restore
restic check --read-data-subset=10%   # verify stored blocks, not just metadata

Lo que esto atrapa nunca es lo que usted espera. Es el archivo de configuración que estaba en un directorio que la lista de inclusión no cubría. El volcado de base de datos que lleva cinco semanas con cero bytes porque una contraseña cambió y el script no comprobó su código de salida. La aplicación que no arranca porque un secreto vive en una variable de entorno que gestiona el orquestador y que nunca estuvo en el sistema de archivos. El registro DNS sin documentar. El certificado que hay que reemitir antes de que nada responda en el 443. Cada una de esas cosas es un arreglo de diez minutos en una tarde tranquila, y dos horas feas a las tres de la madrugada.

Anote cuánto tardó el simulacro, de principio a fin. Ese número — no la frecuencia de las copias de seguridad — es su verdadero tiempo de recuperación, y es la única respuesta honesta cuando alguien pregunta cuánto tiempo estaría caído. Añada también restic check --read-data-subset=5% a un timer mensual: lee y verifica una muestra rotatoria de los bloques realmente almacenados, en lugar de solo el índice, que es como se encuentra la corrupción silenciosa mientras todavía hay una copia buena a la que recurrir. Si alguna vez traslada el servidor entero a otro proveedor, una restauración ya ensayada es también buena parte de la migración ya hecha.

  1. Haga inventario de lo que de verdad no se puede reconstruir

    Antes de tocar ninguna herramienta, escriba la lista. Recorra la máquina y pregúntese, de cada directorio: si esto desapareciera, ¿podría recrearlo a partir de un gestor de paquetes, un repositorio git o un archivo compose? Si la respuesta es sí, no pertenece a la copia de seguridad. Lo que queda suele ser mucho más pequeño de lo que la gente espera — configuración, datos de usuario, estado de las aplicaciones, volcados de bases de datos.

    # the fast way to find what is actually big and stateful
    du -x -h -d2 / 2>/dev/null | sort -rh | head -30
    docker volume ls    # named volumes are state; overlay2 is not

    Convierta el resultado en dos archivos explícitos, /etc/restic/include.txt y /etc/restic/exclude.txt. Las listas explícitas ganan a las expresiones ingeniosas de find porque se pueden revisar, y porque la aparición de un directorio nuevo en el servidor debería ser una decisión deliberada, y no una inclusión silenciosa.

  2. Despliegue el destino de la copia de seguridad en una jurisdicción distinta

    Contrate un segundo VPS en una región que no sea aquella en la que corre producción — si producción está en París, ponga la copia en Reikiavik o en Bucarest. La idea es que ningún evento legal o físico, por sí solo, alcance a las dos máquinas. Un Starter a $5/mes trae 80 GB de NVMe, que tras la deduplicación sostienen un historial muy largo de un servidor pequeño típico; el ciclo de facturación de 12 meses reduce eso a la mitad. Páguelo con el mismo saldo en cripto, para que el destino herede el anonimato del origen en lugar de contradecirlo.

    Déle una cuenta separada de la de producción si quiere un aislamiento total de credenciales. Después, endurézcalo exactamente igual que haría con cualquier otra cosa — SSH solo con claves, firewall de denegación por defecto — y no instale nada más en él. El valor de esta máquina está en que sea aburrida: sin servidor web, sin puertos abiertos más allá de SSH, nada que se pueda explotar desde internet.

  3. Cree una puerta de solo lectura desde el host de backup hacia producción

    Este es el paso que convierte esto en un pull. En el host de backup, genere una clave dedicada. Después, instale su mitad pública en producción con un comando forzado, de modo que la clave pueda hacer exactamente una cosa: leer archivos. No puede abrir una shell, redirigir un puerto, ni escribir nada.

    # on the backup host
    ssh-keygen -t ed25519 -a 100 -f ~/.ssh/pull_prod -C "pull@backup"
    
    # on production, in /root/.ssh/authorized_keys — one line
    command="/usr/bin/rrsync -ro /",restrict ssh-ed25519 AAAAC3Nz… pull@backup

    rrsync viene incluido con rsync (/usr/bin/rrsync en Debian 13; /usr/share/doc/rsync/scripts/rrsync en versiones más antiguas) y -ro hace que rechace cualquier cosa que no sea una lectura. restrict desactiva la redirección de puertos, la redirección del agente, la asignación de PTY y X11, todo con una sola palabra. Verifique que la jaula aguanta antes de confiar en ella — ssh -i ~/.ssh/pull_prod root@production debe fallar al intentar darle una shell.

  4. Vuelque las bases de datos en producción, con su propio calendario

    Producción conserva un único trabajo: generar volcados consistentes en un directorio de staging que el pull recogerá después. Esto no necesita ninguna credencial de backup, que es exactamente la razón por la que el diseño funciona.

    # /usr/local/sbin/dump-db.sh   (chmod 700)
    set -euo pipefail
    D=/var/backups/db; install -d -m 700 "$D"
    mariadb-dump --single-transaction --quick --routines --triggers --events \
      --all-databases | zstd -T0 > "$D/all.sql.zst.tmp"
    mv "$D/all.sql.zst.tmp" "$D/all.sql.zst"

    Fíjese en el patrón de escribir-en-temporal-y-luego-renombrar: significa que el pull nunca puede recoger un volcado a medio escribir, sea cual sea el momento en que se ejecute. set -euo pipefail no es decoración — sin ella, un mariadb-dump que falla envía un flujo vacío a zstd por la tubería, que termina con éxito, y obtiene un archivo comprimido válido que no contiene absolutamente nada. Esa es la forma más común, con diferencia, en que una copia de seguridad resulta inútil en silencio. Ejecútelo desde su propio timer, media hora antes del pull.

  5. Traiga los datos al host de backup

    En el host de backup, sincronice con rsync la lista de inclusión de producción hacia un árbol de staging. Solo los bloques que cambiaron cruzan la red, así que después de la primera ejecución esto es rápido y barato.

    # /usr/local/sbin/pull.sh   (chmod 700, runs on the BACKUP host)
    set -euo pipefail
    [email protected]
    # -r is spelled out on purpose: with --files-from, -a does NOT imply
    # recursion, and without it you silently copy empty directories.
    rsync -aHAX -r --delete --numeric-ids \
      -e "ssh -i /root/.ssh/pull_prod -o BatchMode=yes" \
      --files-from=/etc/backup/include.txt \
      --exclude-from=/etc/backup/exclude.txt \
      "$SRC:/" /srv/staging/prod/

    -aHAX conserva los hardlinks, las ACL y los atributos extendidos, y --numeric-ids mantiene la propiedad con sentido entre máquinas cuyos /etc/passwd difieren. --delete es seguro aquí precisamente porque el staging no es la copia de seguridad — el historial versionado vive en el repositorio de restic que se construye en el siguiente paso, así que un borrado que se propague hasta el staging sigue siendo recuperable a partir del snapshot de ayer.

  6. Inicialice el repositorio y guarde la clave fuera de línea

    Todavía en el host de backup, cree un repositorio de restic local y vuelque en él el árbol de staging. Local significa que no hay red en la ruta crítica, no hay ninguna credencial remota que robar, y una restauración que corre a la velocidad del disco.

    apt install -y restic
    install -d -m 700 /etc/backup
    openssl rand -base64 32 > /etc/backup/pass   # write this into your password manager NOW
    chmod 600 /etc/backup/pass
    
    export RESTIC_REPOSITORY=/srv/restic/prod
    export RESTIC_PASSWORD_FILE=/etc/backup/pass
    restic init

    Copie esa passphrase en un gestor de contraseñas, y anote al lado la ruta del repositorio y el comando de restauración. Después, demuéstrelo: desde una tercera máquina, usando solo lo que hay en el gestor de contraseñas, ejecute restic -r sftp:backup@…:/srv/restic/prod snapshots. Si eso lista snapshots, la clave es genuinamente recuperable. Si necesita algo que solo existe en alguno de los dos servidores, arréglelo ahora, en lugar de descubrirlo más tarde.

  7. Programe la tarea, y convierta el silencio en una alarma

    Envuelva el pull, la ejecución de restic y la poda en un único script, y gestiónelo desde un timer de systemd. Tenga en cuenta que forget --prune es seguro de ejecutar aquí porque el host de backup es el dueño legítimo del repositorio — producción nunca llegó a tener una credencial de borrado, en ningún momento.

    # tail of /usr/local/sbin/backup.sh
    restic backup /srv/staging/prod --tag nightly
    restic forget --keep-daily 7 --keep-weekly 5 --keep-monthly 12 \
                   --keep-yearly 2 --prune
    curl -fsS -m 10 --retry 3 https://hc.example.net/ping/<uuid>  # only on success
    systemctl daemon-reload
    systemctl enable --now backup.timer
    systemctl list-timers backup.timer     # confirm the next run is where you expect

    El curl solo se ejecuta si todos los comandos anteriores tuvieron éxito, gracias a set -e. El monitor, al otro lado, espera un ping diario y avisa ante su ausencia, lo cual convierte una tarea que dejó de funcionar en silencio en un correo, en lugar de en un hallazgo arqueológico. enable --now, no solo start — un timer que nunca se habilitó sobrevive exactamente hasta el primer reinicio.

  8. Haga el simulacro de restauración, y anote cuánto tardó

    Ponga un recordatorio periódico en lo que sea que de verdad lea, una vez por trimestre. Despliegue un Starter desechable, restaure en él sin nada más que la passphrase y el procedimiento escrito, levante la aplicación, verifique que sirve datos reales, y destruya la máquina. La facturación por horas significa que todo el simulacro cuesta un par de céntimos.

    restic restore latest --target /restore
    zstd -dc /restore/var/backups/db/all.sql.zst | mariadb
    systemctl start nginx app
    curl -H 'Host: example.com' http://127.0.0.1/health

    Anote el tiempo transcurrido y cada sorpresa con la que se tropiece, y luego arregle las sorpresas en el script de backup, no en su memoria. Ese tiempo transcurrido es su verdadero objetivo de recuperación; hasta que no lo haya medido una vez, cualquier número que dé es una suposición.

Comparativa

Dónde poner la copia

Cada destino frente a las cuatro preguntas que lo deciden todo: qué le cuesta en anonimato, qué le cuesta en dinero, con qué rapidez recupera sus datos, y qué es capaz de sobrevivir.
DestinoCoste en anonimatoDineroVelocidad de restauraciónSobrevive a
Segundo VPS no-KYC, en otra regiónNinguno — pagado con el mismo saldo en cripto, sin identidad en ningún sitio$5/mes, reducido a la mitad en un ciclo de 12 mesesRápida — de centro de datos a centro de datos, a 1–10 GbpsPérdida de la cuenta, un compromiso de seguridad, una jurisdicción, sus propios errores
Snapshot del proveedorNingunoBaratoSegundosCasi nada — misma cuenta, mismo dominio de fallo, muere junto con ambas
Almacenamiento de objetos (B2 / S3 / Wasabi)Alto — tarjeta y documento de identidad en la cuenta, y la clave de API en su servidor apunta directamente a ellaMuy barato para almacenar; las tarifas de salida duelen durante una restauraciónRápida, si acepta la factura de salida de datosCompromiso de seguridad y pérdida de cuenta, al precio de un nombre pegado a la máquina
Proveedor de almacenamiento que acepta criptoBajo, si la vía de pago es realmente libre de identidad — verifíquelo, no lo dé por hechoModeradoVaría muchísimo — revise los límites de salida antes de necesitarlosCasi todo, con más riesgo de contraparte que un VPS bajo su propio control
NAS doméstico, con pull a través de WireGuardNinguno — todo lo que sale de su propia red va cifrado, y no queda atribuido a nadieHardware que ya tieneLenta — limitada por la velocidad de subida de su conexión domésticaTodo excepto su propia casa; pobre como única copia, excelente como tercera
Nada / “está en git”NingunoGratisNuncaNada. Git guarda su código; no guarda su base de datos, sus archivos subidos ni su /etc
FAQ

Preguntas que vale la pena responder

¿No es ya una copia de seguridad un snapshot del proveedor?

No, y la distinción no es una pedantería. Un snapshot vive en la misma cuenta, con las mismas credenciales, en el mismo dominio de fallo que el servidor que copia — así que no sobrevive a la pérdida de la cuenta, y cualquiera que llegue a su panel puede borrarlo junto con el original. Además, se toma de una máquina en marcha, lo que significa que una base de datos con actividad se captura a mitad de una escritura. Use los snapshots como botón de deshacer antes de cambios arriesgados; use un repositorio cifrado y remoto como copia de seguridad.

¿restic o Borg: cuál debería usar?

restic, salvo que tenga una razón concreta para no usarlo. Cifra por defecto, no necesita nada instalado en el destino, habla todos los backends que merece la pena usar, y se distribuye como un único binario estático. Borg deduplica y comprime mejor, y es notablemente más rápido en sistemas de archivos con millones de archivos pequeños, pero debe instalarse con versiones equivalentes en ambos extremos, y está realmente pensado para un solo cliente por repositorio. Buzón de correo enorme y las dos máquinas bajo su control: Borg. Todo lo demás: restic.

¿Cuánto disco necesita el destino de la copia de seguridad?

Para un repositorio deduplicado con la escalera de retención de esta guía — 7 diarios, 5 semanales, 12 mensuales, 2 anuales — calcule aproximadamente entre dos y tres veces el tamaño de los datos que realmente está respaldando, no del servidor entero. Veintiséis snapshots no significan veintiséis copias, porque solo se vuelven a guardar los bloques que cambiaron. Un sitio pequeño con 15 GB de estado real cabe con holgura en el Starter de 80 GB, con años de historial de sobra.

¿No duplica un segundo VPS mi factura de hosting?

Solo si el destino de la copia de seguridad iguala a producción, y no debería. No ejecuta ninguna aplicación ni sirve tráfico; necesita disco, no CPU. Un Starter de $5 detrás de un servidor de producción de $30 es una sexta parte de la factura, y el ciclo de 12 meses le quita otro 50%. Comparado con el coste de perderlo todo, es la línea más barata de la factura — y el destino también sirve de máquina de ensayo para el simulacro de restauración.

¿Dónde debería vivir la contraseña del repositorio?

En un gestor de contraseñas cuya bóveda tenga, a su vez, copia de seguridad en otro sitio, o en papel, o ambas cosas — y al lado, la dirección del repositorio y el comando exacto de restauración. La copia en /etc, en el servidor, es una copia de trabajo para la automatización, nunca el registro maestro. Verifíquelo como es debido: desde una máquina que no sea ni producción ni el host de backup, usando solo lo que hay en el gestor de contraseñas, ejecute restic snapshots. Si hace falta cualquier otra cosa, todavía no tiene una copia de seguridad recuperable.

¿Con qué frecuencia deberían ejecutarse las copias de seguridad?

Pregúntese cuánto trabajo está dispuesto a rehacer. Todas las noches es lo correcto para la mayoría de los servidores: como mucho se pierde un día, y una única ejecución nocturna es fácil de razonar. Una base de datos con mucha actividad quiere más — volcados de la base de datos cada hora, mientras el pase completo de archivos se queda en nocturno, es el patrón habitual. Más allá de ese punto, la frecuencia da menos que el mismo esfuerzo invertido en una retención más larga y un simulacro de restauración real, que es donde está el riesgo de verdad.

¿Puedo hacer copia de seguridad de un servidor cuyo disco está cifrado con LUKS?

Sí, y las dos cosas son complementarias, no redundantes. LUKS protege el disco mientras la máquina está apagada; la copia de seguridad le protege del borrado, la corrupción y la pérdida completa de la máquina. Haga la copia de seguridad del sistema de archivos montado exactamente igual que haría con uno sin cifrar — restic vuelve a cifrar al salir, así que el repositorio está a salvo en un almacenamiento no confiable. Mantenga los dos secretos en sitios genuinamente separados: una passphrase de LUKS guardada solo en el repositorio de restic, o una passphrase de restic guardada solo dentro del volumen LUKS, es un bucle que falla cerrado por los dos lados.

Si mi servidor se ve comprometido, ¿están a salvo las copias de seguridad?

Eso depende por completo de una decisión que tomó meses antes. Si el servidor de producción guarda una credencial con permisos de borrado sobre el repositorio, entonces no — un atacante enumera y destruye primero las copias de seguridad, porque eso es lo que convierte un incidente en una negociación. Si el repositorio es append-only, o el host de backup hace pull y producción no guarda ninguna credencial de backup en absoluto, entonces el historial sobrevive y usted restaura a un snapshot anterior a la intrusión. Ese es todo el argumento a favor del diseño pull, y la razón para preferirlo antes de necesitarlo.

Deploy your offshore server.

Elige una región. Elige un plan. Pega una clave. Paga. Los próximos 47 segundos corren de nuestra cuenta.