La copia es la parte fácil — lo que provoca en realidad el tiempo de inactividad
Pregúntale a alguien cuánto va a tardar su migración y te va a calcular el tiempo de transferencia. Doscientos gigabytes por un enlace de un gigabit, digamos cuarenta minutos, más una hora de margen. Ese número suele ser correcto y casi nunca es el número que importa, porque la transferencia ocurre mientras el servidor antiguo sigue respondiendo peticiones. Nadie está caído durante la copia. Están caídos durante el intervalo entre que la máquina nueva es correcta y que internet se entera, y la duración de ese intervalo la fijan cachés que tú no controlas.
Cuatro modos de fallo explican la mayoría de las caídas reales de una migración, y ninguno tiene que ver con el ancho de banda. Un registro DNS cuyo tiempo de vida todavía era de un día cuando lo cambiaste, así que una parte considerable del mundo sigue conectándose a una máquina que ya apagaste. Una base de datos que aceptó escrituras después de que la volcaste, así que el host nuevo empieza su vida con una copia obsoleta sin que nadie lo sepa, y descubres qué veinte minutos faltan por la reclamación de un cliente. Un certificado TLS y su clave de cuenta ACME que solo existían en el disco antiguo, así que el host nuevo le sirve a cada navegador un nombre que no coincide. Y una integración saliente — una pasarela de pago, una carpeta SFTP de un banco, la API de un socio, una base de datos en un tercer proveedor — que estaba en una lista blanca por dirección IP, lo cual falla en silencio en el punto más alejado posible del cambio que lo provocó.
Merece la pena ser directos con la frase que usa todo el mundo. «Migración sin tiempo de inactividad» casi siempre significa unos segundos de conexiones rechazadas que ningún humano llegó a notar, y ese es un objetivo perfectamente razonable. Que sea de verdad cero exige que las dos máquinas sirvan correctamente al mismo tiempo, lo cual exige una aplicación que tolere ser dos máquinas: sin estado de sesión local, sin un directorio de subidas local que solo tenga un lado, y una base de datos que replique o que viva enteramente en otro sitio. La mayoría de los stacks autoalojados no llegan a ese nivel, y el plan honesto es una congelación corta, controlada y ensayada, no un proyecto de arquitectura que no pensabas empezar.
Así que la forma de una buena migración no tiene ningún truco. Construye la máquina nueva pronto y demuestra que funciona mientras la antigua carga con el trabajo. Reduce la parte irreversible a unos minutos de comandos preparados de antemano. Cambia una cosa cada vez. Y conserva la capacidad de volver atrás, con una fecha a partir de la cual dejas de pagar por ella.
Inventario: las partes de un servidor que no están en tu repositorio
Tu repositorio de despliegue describe la aplicación. No describe la máquina. En algún punto entre el primer apt install y hoy, un servidor acumula una capa que ningún control de versiones ha visto jamás: paquetes instalados a mano para arreglar un problema puntual, una unidad de systemd que alguien escribió con prisa, una tarea cron bajo una cuenta de servicio, reglas de cortafuegos, ajustes de sysctl, un locale, una zona horaria, un archivo de swap, certificados TLS, claves de host SSH, roles y permisos de base de datos, y un directorio de contenido multimedia que no está en el repositorio precisamente porque lo pusieron ahí los usuarios. Migrar significa reproducir esa capa de forma deliberada, y la única manera de hacerlo deliberadamente es escribirla primero.
Cinco comandos capturan casi todo. dpkg --get-selections en Debian y Ubuntu, o dnf repoquery --userinstalled en Rocky y Alma, te da el conjunto de paquetes. systemctl list-unit-files --state=enabled te da todo lo configurado para arrancar al iniciar, que es una pregunta mejor que «qué está en ejecución» porque incluye lo que en este momento está caído. crontab -l -u para cada cuenta en /etc/passwd, más el contenido de /etc/cron.d y cada unidad .timer, te da el trabajo programado. nft list ruleset o ufw status numbered te da el cortafuegos. Y ss -tulpn te da lo que realmente está escuchando, que es como descubres el servicio que se te había olvidado que existía. Escribe los cinco a archivos y cópialos fuera de la máquina, no hacia ella.
Luego está el inventario que nadie apunta, que es el que muerde semanas más tarde: todo, en cualquier sitio, que confía en tu dirección IP actual. Pasarelas de pago con listas blancas por IP. Una base de datos gestionada en otro proveedor cuyas reglas de acceso nombran la dirección antigua. Un relay SMTP que autentica por red. Un servicio de monitorización, un emisor de webhooks que solo publica hacia direcciones conocidas, el cortafuegos de un colega. Haz grep en tu propia configuración y en tu documentación buscando la dirección antigua, y luego revisa el panel de cada servicio de terceros que pagas. Estas cosas se rompen después del corte, de forma asíncrona, en el momento en que le toque volver a ejecutarse a cada integración — que es por lo que tan a menudo se diagnostican como «salió mal otra cosa al mismo tiempo».
Por último, captura la zona DNS en sí. Expórtala, o como mínimo apunta cada tipo de registro, su valor y su TTL, porque una migración es exactamente el momento en que alguien se fija en un registro que llevaba dos años mal y, muy servicial, lo arregla en medio de todo lo demás.
| Qué inventariar | Dónde vive | Qué se rompe si lo olvidas |
|---|---|---|
| Paquetes instalados a mano | Base de datos de paquetes | Un servicio se niega a arrancar en el host nuevo por una biblioteca que falta y que nadie recuerda haber añadido. |
| Unidades y timers activados | systemd | El trabajo en segundo plano se detiene en silencio: sin copias de seguridad, sin renovación de certificados, sin worker de colas. |
| Tareas cron por usuario | Crontabs de cada cuenta | Las tareas nocturnas desaparecen y se notan a fin de mes. |
| Conjunto de reglas del cortafuegos | nftables o ufw | O un puerto se queda cerrado y la app parece rota, o queda todo abierto. |
| Certificados TLS y clave de cuenta ACME | Directorio de certificados | Los navegadores muestran un nombre que no coincide, y las renovaciones arrancan una cuenta nueva. |
| Roles y permisos de base de datos | Globales del servidor, no el volcado | Los datos se restauran bien y la aplicación no puede iniciar sesión en ellos. |
| Listas blancas de IP de terceros | Paneles de otras personas | Pagos, webhooks y APIs de socios fallan horas o días después. |
| Zona DNS con sus TTL | Tu proveedor de DNS | No puedes saber qué registros todavía necesitan moverse, ni cuánto tiempo quedan en caché. |
Baja primero el TTL del DNS — y entiende por qué tiene que ser con días de antelación
Un resolutor recursivo guarda en caché una respuesta durante el tiempo de vida que le dieron, y no tiene ninguna obligación de volver a preguntar antes de que expire. Esto tiene una consecuencia que pilla a casi todo el mundo la primera vez: bajar el TTL de un registro de 86400 a 300 no le hace absolutamente nada a un resolutor que cacheó la respuesta antigua hace diez minutos. Ese resolutor conserva la respuesta de un día durante otras veintitrés horas y cincuenta minutos más, y solo entonces se entera de tu nuevo TTL de cinco minutos. Por eso el TTL bajo tiene que publicarse al menos un TTL antiguo completo antes de que pienses mover nada. Si tus registros tienen un TTL de un día, la primera acción de la migración ocurre dos días antes del corte, y es un cambio de una sola línea.
Hazlo con todos los registros que apunten a la máquina, no solo con el que tienes en mente. El registro A y el registro AAAA — una dirección IPv6 que se queda apuntando al host antiguo es un error preciosamente confuso, porque los clientes de doble pila la van a preferir en silencio y solo una parte de tus usuarios se van a ver afectados. Los registros MX. Cualquier CNAME que tengan delante, recordando que un cliente que sigue una cadena queda sujeto al TTL de cada eslabón, así que un registro A de cinco minutos detrás de un CNAME de un día sigue siendo, en la práctica, un día. Y si además estás cambiando de proveedor de DNS, no lo hagas la misma semana: la delegación de servidores de nombres y los registros glue los cachea la zona padre según su propio calendario, y combinar los dos cambios significa que, cuando algo se rompa, no vas a saber cuál de los dos lo rompió.
Verifica, no des nada por hecho. dig +noall +answer example.com A te muestra lo que un resolutor tiene guardado ahora mismo y la cuenta atrás que le queda; consultar directamente a tu servidor autoritativo con dig @ns1.example.net example.com A te muestra lo que de verdad publicaste. Si los dos no coinciden, estás mirando la caché, y el número junto al registro es exactamente cuánto te queda por esperar.
Merece la pena presupuestar tiempo para dos matices. Algunos resolutores recortan: una parte de los forwarders de ISP y de empresa imponen un TTL mínimo sin importar lo que publiques, algo técnicamente desaconsejado pero completamente real. Y según la RFC 8767, un resolutor puede servir deliberadamente una respuesta obsoleta cuando no puede alcanzar tus servidores autoritativos — un comportamiento excelente para la resiliencia, incómodo el día en que quieres que un cambio se propague. Entre ambos efectos, cuenta con una cola larga medida en horas, a veces un día, después de que se haya movido el grueso del tráfico. Esa cola no es un problema mientras la máquina antigua siga respondiendo correctamente, que es precisamente la razón por la que se mantiene encendida. La RFC 2181 es la referencia sobre cómo se supone que se comportan los TTL cuando las implementaciones no están de acuerdo.
| Cuándo | Acción | Por qué entonces |
|---|---|---|
| T menos 7 días | Inventaría el servidor antiguo; escribe el runbook | Todo lo que encuentres aquí cambia el plan, así que tiene que pasar antes de fijarlo. |
| T menos 3 días | Aprovisiona el VPS nuevo; primera restauración; ensayo | Deja tiempo para reconstruir la máquina una segunda vez si el ensayo encuentra huecos. |
| T menos 2 días | Baja los TTL de A, AAAA y MX a 300 | Tiene que pasar un TTL antiguo completo antes de que el valor bajo esté en todas las cachés. |
| T menos 1 día | Primera pasada de rsync; arranca la replicación de la base de datos | Larga y desatendida, con el servidor antiguo todavía cargando tráfico de producción. |
| T cero | Congela escrituras, sincronización final, verifica, cambia el DNS | La única ventana irreversible; es corta porque todo lo anterior ya ha pasado. |
| T más 1 hora | Vigila los dos access logs | La caída del tráfico en el host antiguo es tu medida real de cuándo expira la caché. |
| T más 7 días | Retira el host antiguo; sube los TTL de nuevo | La reversión ha caducado; un TTL permanente de 300 segundos cuesta latencia sin ningún beneficio. |
Ensaya en la máquina nueva mientras la antigua todavía sirve
El hábito de mayor valor en todo este proceso es que la máquina nueva exista y funcione días antes de que importe de verdad. Un VPS es, en la práctica, un alquiler por horas: en nuestros planes, un servidor está activo unos sesenta segundos después de que se confirme el pago, sin cuota de alta y sin contrato, así que un ensayo de tres días en el plan de $8.50 cuesta alrededor de un dólar. Es una forma extraordinariamente barata de convertir cada incógnita de tu migración en algo conocido antes de que el reloj empiece a correr.
Pruébalo por nombre de host, no por IP. Navegar hasta la dirección del servidor nuevo te da el virtual host por defecto, ningún SNI coincidente, un aviso de certificado y un conjunto de rutas que puede no parecerse en nada a producción — y te va a convencer alegremente de que algo funciona cuando no es así. La herramienta correcta es una anulación de resolución. curl --resolve fija un nombre de host a una dirección para un único comando, así que curl --resolve example.com:443:203.0.113.10 https://example.com/ pone a prueba el nombre real, el handshake TLS real y el virtual host real contra la máquina nueva mientras el resto del mundo todavía llega a la antigua. Para pruebas interactivas, una línea en el archivo hosts de tu equipo hace el mismo trabajo para un navegador.
Lo que el ensayo detecta de forma fiable es la capa acumulada y no documentada de la sección anterior. Un daemon que lleva en ejecución desde antes del último reinicio y que en realidad no está activado. Una tarea cron que depende de un transporte de correo local para reportar fallos. Una propiedad de archivos que sobrevivió a la copia como números, pero que significa otra cosa en una máquina con un /etc/passwd distinto. Una dirección escrita a fuego en un archivo de configuración. Una base de datos creada con un juego de caracteres en una versión que tenía otro por defecto. Una versión menor de Python o PHP que dejó obsoleto algo que usas. Cada uno de estos casos cuesta diez minutos de arreglar durante un ensayo y una hora de diagnosticar durante un corte.
Una prueba vale más que todas las demás: construye la máquina nueva dos veces. Reconstrúyela desde cero usando solo tu inventario y tu copia de seguridad, sin mirar el servidor antiguo. Si la segunda vez arranca correcta, tu inventario es real y tu runbook se puede ejecutar. Si no, acabas de encontrar el hueco en una situación en la que encontrarlo no cuesta nada. Toma una instantánea en cuanto esté bien — las instantáneas por hora con siete días de retención están incluidas en todos los planes, y una restauración tarda unos treinta segundos — para que cualquier experimento posterior en la máquina nueva también sea reversible.
rsync dos veces: una pasada larga mientras sigue en marcha, una corta en la ventana
El patrón de dos pasadas es lo que mantiene corta la ventana de mantenimiento. La primera pasada se ejecuta con el servicio totalmente activo y puede tardar lo que tenga que tardar — horas, toda la noche, todo un fin de semana. La segunda pasada se ejecuta durante la congelación y transfiere solo lo que cambió desde la primera, que en una carga de trabajo normal es una fracción pequeña de los datos y un número predecible de minutos. Estás cambiando una copia larga y desatendida por una corta y atendida, y casi siempre merece la pena el cambio.
Los flags importan más de lo que la gente espera. rsync -aHAX --numeric-ids es la base: -a para el modo archive, -H para conservar los hardlinks — algo que importa muchísimo en los almacenes Maildir y en los árboles de copia de seguridad deduplicados, donde perderlos puede multiplicar tu uso de disco — -A para las ACL POSIX, -X para atributos extendidos como las etiquetas de SELinux y las capabilities de archivo, y --numeric-ids para que un ID de usuario se copie como número en lugar de resolverse a través de la base de datos de usuarios del origen y volver a resolverse a través de otra distinta en el destino. Añade --info=progress2 para tener una única línea de progreso sensata, y --partial para que una transferencia interrumpida se reanude en vez de reiniciarse. Deja -z desactivado a menos que el enlace sea genuinamente lento: comprimir contenido multimedia ya comprimido y archivos cifrados solo traslada el cuello de botella a la CPU.
Usa --delete solo en la segunda pasada. En la primera pasada es un tiro en el pie sin ninguna ventaja, porque no hay nada en el destino que haga falta quitar. En la segunda pasada es imprescindible: sin él, un archivo que borraste en el servidor antiguo entre las dos pasadas sobrevive para siempre en el nuevo, que es como una migración termina sirviendo contenido que se había retirado a propósito.
Lo que no deberías hacer es pasar rsync sobre todo el sistema de archivos raíz. Es un atajo popular y produce una máquina que nadie es capaz de entender. Incluso excluyendo /proc, /sys, /dev, /run y /tmp, terminas con un sistema cuyo kernel y cuyo initramfs vinieron de un host distinto, cuyo nombrado de interfaces de red se derivó de un hardware diferente, cuyo /etc/machine-id está ahora duplicado en dos máquinas vivas, y cuyos cinco años acumulados de desviación de configuración acabas de pagar por conservar. Migra los datos y la configuración que inventariaste; instala el sistema operativo desde cero a partir de una plantilla. Cuesta una hora extra, te da una base moderna y limpia, y significa que el servidor nuevo es una máquina que entiendes, en lugar de una copia de otra que no entendías.
Verifica la copia en lugar de fiarte del código de salida. Después de las dos pasadas, ejecuta el mismo comando otra vez con -n --checksum --itemize-changes: una simulación que compara contenido en lugar de marcas de tiempo e imprime una línea por cada diferencia. El silencio es el resultado que quieres, y dice mucho más que ver coincidir du -s en los dos lados.
La base de datos es la parte con la que rsync no te puede ayudar
Copiar a nivel de archivo el directorio de una base de datos en marcha te da una copia inconsistente: unas páginas escritas, otras no, sin ninguna garantía de que nada de eso forme un límite de transacción coherente. Es posible que InnoDB se recupere de ello y parezca estar bien, lo cual es peor que fallar directamente, porque solo te vas a enterar el día en que la recuperación no funcione. Hay exactamente dos estrategias honestas — hacer un volcado transaccionalmente consistente, o replicar — y elegir entre ellas es elegir cuánto tiempo de inactividad estás comprando.
Para la vía del volcado en MySQL y MariaDB, mysqldump --single-transaction --routines --triggers --events te da una instantánea consistente sin bloquear todo el servidor, con dos matices que conviene saber: solo es consistente para tablas transaccionales, así que una sola tabla MyISAM heredada rompe la garantía en silencio, y cualquier sentencia DDL ejecutada durante el volcado también la rompe. En PostgreSQL, pg_dump -Fc se encarga de cada base de datos, y pg_dumpall --globals-only se encarga de la mitad que la gente olvida — los roles, las contraseñas, los permisos y los tablespaces viven a nivel de clúster, no dentro de ninguna base de datos concreta, así que una restauración sin ellos produce datos perfectos a los que la aplicación no puede autenticarse.
El número que decide tu ventana no es el tamaño del volcado, es volcado más transferencia más restauración más reconstrucción de índices, y ese último suele ser el más grande. Mídelo durante el ensayo con el conjunto de datos real, en lugar de estimarlo. Unos pocos gigabytes son minutos; cien gigabytes con indexación considerable pueden ser horas, y en ese punto la vía del volcado deja de ser viable para un servicio en producción, y la replicación pasa de ser una optimización a ser la respuesta.
La vía de la replicación invierte el coste: haces el trabajo por adelantado y el corte se vuelve trivial. Monta una réplica en el host nuevo con días de antelación — replicación basada en GTID para MySQL y MariaDB, pg_basebackup y un standby en streaming para PostgreSQL, o replicación lógica cuando además estás cruzando una versión mayor. Déjala ponerse al día y que se mantenga al día. El corte entonces es: parar las escrituras en la primaria, esperar a que la réplica reporte cero retraso, promoverla, apuntar la aplicación hacia ella. Eso son segundos, y es el único enfoque que de verdad merece la frase «tiempo de inactividad casi cero».
No te olvides del estado que no está en la base de datos. Redis, Valkey y Memcached guardan sesiones, contadores de límite de tasa y colas; un índice de búsqueda en Elasticsearch, OpenSearch o Meilisearch guarda una copia derivada de tus datos. Para cada uno, decide explícitamente si lo migras o lo reconstruyes. Una instancia de Redis que guarda sesiones merece la pena moverla con un BGSAVE y una copia del archivo resultante, a menos que te dé igual desconectar a todo el mundo. Un índice de búsqueda casi siempre es más rápido reindexarlo en el host nuevo que transferirlo — pero reindexar lleva tiempo, así que empiézalo durante el ensayo y no durante la congelación.
| Estrategia | Inactividad en el corte | Trabajo antes de la ventana | Cuándo es la opción correcta |
|---|---|---|---|
| Copia de archivos de un directorio de datos en marcha | Ninguna, y los datos pueden estar corruptos | Ninguno | Nunca. Se incluye aquí porque es lo primero que prueba la gente. |
| Volcado y restauración consistentes | Volcado más transferencia más restauración más reindexado | Mídelo una vez durante el ensayo | Conjuntos de datos lo bastante pequeños como para que el total medido entre dentro de tu tolerancia. |
| Volcado, restauración y luego repetición del delta | Minutos | Retención de binlog o WAL configurada de antemano | Conjuntos de datos medianos donde una réplica completa es más montaje del que quieres. |
| Réplica promovida en el corte | Segundos | Replicación en marcha y sin retraso durante días | Cualquier cosa grande, y cualquier caso en el que una congelación larga sea inaceptable. |
| Parar la base de datos, copiar los archivos en frío | Duración de la copia | Ninguno | Servicios internos pequeños donde una hora fuera de línea de verdad no cuesta nada. |
Certificados TLS, claves de host SSH y las identidades que no puedes simplemente reemitir
La emisión de certificados tiene un problema del huevo y la gallina justo en el peor momento. El desafío HTTP-01 demuestra el control de un nombre descargando un archivo a través de ese nombre, lo cual exige que el nombre ya resuelva hacia la máquina que se está validando — y antes del corte, no lo hace. Hay tres salidas y deberías elegir una a propósito. Copiar el directorio de certificados de un lado a otro, que funciona de inmediato y es completamente legítimo porque es tu propia clave. Usar en su lugar el desafío DNS-01, que valida publicando un registro TXT y por tanto funciona en una máquina a la que todavía nada apunta, y que además es la única opción para un certificado comodín. O aceptar una ventana corta después del cambio de DNS durante la cual el host nuevo solicita su propio certificado, lo cual está bien para un sitio personal y no está nada bien para cualquier cosa con usuarios.
Si copias, copia todo. Los certificados y las claves privadas son la parte obvia; la clave de cuenta de ACME es la parte que se queda atrás, y sin ella el cliente del host nuevo registra una cuenta completamente nueva en la primera renovación. Todo parece funcionar, y has perdido en silencio el historial de la cuenta y cualquier estado asociado a ella. Conserva también la propiedad y los permisos — las claves privadas en 600, el directorio de archivo en 700 — porque una copia que amplía los permisos de una clave es un resultado peor que la migración que te preocupaba.
No planees reemitir una y otra vez a ver qué pasa. Los límites de tasa de Let's Encrypt tienen un tope de certificados duplicados por semana para un mismo conjunto de nombres de host, y dos ensayos fallidos más una emisión real es una forma sorprendentemente fácil de llegar al tope justo el día en que no te puedes permitir esperar. Apunta los ensayos al entorno de staging; guárdate el endpoint de producción para el momento real.
Las claves de host SSH son la otra identidad en juego, y aquí la respuesta correcta depende de verdad de por qué te estás mudando. Copiar /etc/ssh/ssh_host_* hace que la migración sea invisible: el known_hosts de cada cliente sigue coincidiendo, y ninguna automatización se detiene con un aviso de huella digital. Eso es cómodo, y es la opción correcta para una mudanza rutinaria entre proveedores en los que confías. Es la opción equivocada si el motivo por el que te vas es que ya no confías en el host antiguo ni en el proveedor antiguo — cualquiera con acceso a ese disco ha tenido tu clave privada de host, y llevarla al servidor nuevo se lleva el problema con ella. En ese caso, genera claves nuevas, publica la huella nueva por un canal que no sea el servidor, y haz que los clientes ejecuten ssh-keygen -R contra la entrada antigua. Consulta el manual de sshd de OpenSSH para ver dónde viven las claves y cómo se seleccionan.
Hay una regla que es absoluta en cualquiera de los dos casos: nunca tengas las dos máquinas funcionando a la vez con la misma clave de host y el mismo nombre de host resolviendo hacia ambas. Esa es una configuración en la que un cliente no puede distinguir a qué servidor ha llegado, que es exactamente la propiedad que las claves de host existen para impedir. Durante la ventana de solapamiento, el host antiguo conserva su identidad y el nuevo tiene la suya propia, o el nombre del host antiguo se retira en el momento en que el nuevo adopta su clave.
El corte: los diez minutos que necesitan un orden por escrito
Todo lo anterior era reversible y sin prisa. El corte no es ninguna de las dos cosas, que es todo el argumento para escribirlo de antemano: la improvisación bajo presión de tiempo es lo que convierte una ventana de cinco minutos en un incidente de dos horas. El runbook debería ser comandos literales en orden, con la salida esperada junto a cada uno, de modo que ejecutarlo exija leer en lugar de pensar.
El orden que funciona. Primero, para las escrituras en el host antiguo — una página de mantenimiento, una bandera de solo lectura, o simplemente detener la aplicación mientras el servidor web sigue respondiendo con una página de espera. Segundo, ejecuta la pasada final de rsync con --delete. Tercero, termina el paso de la base de datos: o bien el volcado-transferencia-restauración que mediste, o parar las escrituras en la primaria, confirmar cero retraso de replicación y promover la réplica. Cuarto, arranca los servicios en el host nuevo y dales un momento para asentarse — los pools de conexiones, los workers de las colas y la carga de certificados tardan todos más en un arranque en frío de lo que recuerdas. Quinto, verifica. Sexto, y solo después de que la verificación pase, cambia los registros DNS. Séptimo, deja el host antiguo en marcha.
La verificación tiene que significar algo. Descargar la página de inicio demuestra que el servidor web está activo y nada más. Usa curl --resolve contra el nombre de host real, sobre una ruta que toque la base de datos y devuelva algo que puedas comprobar — solo por esto ya merece la pena escribir un endpoint de salud que revise la conectividad con la base de datos, la conectividad con la caché y el espacio libre en disco. Luego lee el access log del host nuevo y confirma que tu petición está en él. Ese último paso suena pedante, y es el paso que detecta el caso en el que tu anulación de resolución no surtió efecto y acabas de verificar cuidadosamente el servidor antiguo.
Después del cambio de DNS, vigila los dos access logs uno junto al otro. El tráfico en el host nuevo sube; el tráfico en el host antiguo decae a medida que las cachés expiran, y esa curva de caída es la única medida honesta de cuánto dura de verdad la cola. Cuando el log del host antiguo se aplana cerca de cero, la migración ha terminado. Hasta que eso pase, la máquina antigua tiene que seguir comportándose correctamente para los usuarios que todavía la alcanzan — por eso se queda encendida y en modo de solo lectura, en lugar de apagarla en un momento de entusiasmo. Si la aplicación no se puede poner en solo lectura, que el host antiguo sirva datos desactualizados durante unas horas suele ser un daño menor que el host antiguo rechazando la conexión, pero esa es una decisión que hay que tomar de antemano y no sobre la marcha.
Cambia una sola cosa. No la versión mayor del sistema operativo y el host a la vez. No el proveedor de DNS y los registros a la vez. No la versión de PHP y la máquina a la vez. Cada cambio simultáneo multiplica las hipótesis que vas a tener que probar cuando algo se comporte mal a las tres de la madrugada, y la actualización que tenías la tentación de colar seguirá ahí la semana que viene, en una máquina a la que ahora puedes volver.
El correo, el rDNS y la reputación que no viaja contigo
Si el servidor envía correo, la migración tiene una segunda mitad que no tiene nada que ver con la migración en sí. Una dirección IP lleva consigo una reputación de envío, esa reputación se construye a lo largo de semanas, y no viaja contigo. Esta es la forma más habitual con diferencia en la que una migración técnicamente impecable produce una semana de quejas de usuarios, y todas las mitigaciones tienen que empezar antes del corte, no después.
El primer registro que se rompe es el SPF. Una política que contenga un mecanismo ip4: con la dirección antigua empieza a fallar en el instante en que envías desde la nueva, y como las políticas de la RFC 7208 son registros DNS, tienen su propio TTL que hay que tener en cuenta. Añade la dirección nueva al SPF antes del corte, mantén las dos en la lista durante el solapamiento, y quita la antigua cuando la retires. El DKIM viaja bien mientras copies la clave privada junto con el resto de la configuración, ya que la mitad pública ya está publicada. El DMARC no necesita ningún cambio, pero merece la pena confirmar que la dirección de reporte todavía existe en una máquina que está a punto de destruirse.
El DNS inverso no es opcional para un host que envía correo. El registro PTR de la dirección nueva tiene que existir y tiene que coincidir con el nombre que el servidor anuncia en su HELO o EHLO, o una parte considerable de los receptores va a rechazar solo por eso. En nuestros planes el PTR se edita desde el panel, así que es una casilla que marcar y no un ticket — configúralo durante el ensayo, verifica que resuelve, y confirma que el registro directo coincide de vuelta. Después comprueba la dirección nueva contra las principales listas negras antes de enviar nada en absoluto: las direcciones recicladas a veces llegan ya listadas, y descubrirlo con tu propio mensaje de prueba no cuesta nada, mientras que descubrirlo por un cliente cuesta mucho. Spamhaus es la que más importa.
Para la recepción, mantén los dos hosts alcanzables. Añade el servidor nuevo como MX de prioridad 10 y deja el antiguo en prioridad 20 durante una semana en lugar de borrarlo: los remitentes reintentan, algunos de ellos tenían tu registro MX en caché, y un servidor de correo que acepta silenciosamente en el host antiguo es muchísimo mejor que un rebote. Después, antes de destruir la máquina antigua, vacía y drena su cola — postqueue -f para forzar un intento de entrega y mailq para confirmar que el resultado está vacío. Los mensajes que se quedan en una cola en un servidor que estás a punto de borrar no están retrasados. Han desaparecido. La guía del servidor de correo autoalojado cubre a fondo el lado de la entregabilidad.
Cuando el proveedor anterior ya ha apagado la máquina
No todas las migraciones son planeadas. Una suspensión tras una denuncia por abuso, una tarjeta que caducó, una cuenta bloqueada por un motivo que nadie te va a explicar — el hilo común es que ahora estás migrando desde una máquina en la que no puedes iniciar sesión, y el cómodo orden de operaciones de arriba ya no aplica. Merece la pena saber de antemano qué suele seguir siendo posible, porque la ventana en la que es posible suele ser corta.
Mientras una instancia está suspendida pero todavía no borrada, suelen quedar tres vías, en orden decreciente de utilidad. El panel de control puede seguir ofreciendo una instantánea o una descarga de copia de seguridad, lo cual resuelve todo el problema de un solo golpe. Un modo de rescate o recuperación puede seguir arrancando una imagen viva con tu disco conectado, dejándote montar el sistema de archivos y copiar por red lo que importa. Y la consola de emergencia puede seguir conectando incluso con la red desactivada, lo cual basta para leer archivos de configuración, recuperar una clave, o apuntar qué estaba instalado — pero no es una vía para una base de datos, así que no cuentes con ella para eso. Pruébalas en ese orden, e inténtalo de inmediato: la retención después de una suspensión es una política, no un derecho, y a menudo se mide en días.
Hay un límite que ningún ticket de soporte resuelve, y merece la pena decirlo con claridad porque es una consecuencia directa del modelo que vende este sitio. En un proveedor que nunca recopiló una identidad — incluido este — no hay forma de demostrar que eres el titular de la cuenta más que teniendo las credenciales de la cuenta. Ese es el sentido del alojamiento sin KYC, y también es su factura: nadie puede restaurarte el acceso a partir de la foto de un pasaporte, porque nunca hubo ningún pasaporte asociado a nada. La guía sobre alojamiento sin KYC cubre el compromiso a fondo; la consecuencia operativa es sencillamente que tu plan de recuperación no puede depender de la buena voluntad de nadie más.
La secuencia de emergencia es la planeada, pero sin el solapamiento. Levanta el host nuevo a partir de tu copia de seguridad que vive fuera de la máquina. Verifícalo bien por nombre de host, porque la tentación de saltarte la verificación es más fuerte precisamente cuando ya estás caído. Después mueve el DNS de inmediato — la disciplina del TTL sigue aplicando, salvo que ahora pagas la cola de la caché como caída en vez de gastarla como solapamiento, que es el argumento más claro de todos para mantener los TTL modestos como política permanente y no como un paso de la migración. Espera que el correo vaya degradado durante un tiempo, y avisa a la gente pronto en lugar de explicarlo después.
La lección se generaliza más allá de este mal día en concreto. Una copia de seguridad que vive en el servidor no es una copia de seguridad; es una segunda copia de lo que estás a punto de perder. Lo que importa es que la copia esté en otro sitio, cifrada antes de salir, de solo-anexado para que un host comprometido o suspendido no pueda borrar su propio historial, y — la parte que todo el mundo se salta — restaurada de verdad una vez, en una instancia desechable, para que sepas que la restauración funciona. La checklist de bastionado cubre cómo montar eso en una máquina nueva; si estás leyendo esta sección porque ya es demasiado tarde, móntalo en la máquina a la que estás migrando, hoy mismo, antes que cualquier otra cosa.
Reversión: define el detonante, y ponle una fecha de caducidad
Casi todo el mundo dice que tiene un plan de reversión, y casi nadie ha escrito qué lo activaría. Sin un detonante, la decisión se toma en el peor momento posible, por quien esté más cansado, y el resultado habitual es que nadie revierte nada porque siempre parece que al problema actual le faltan cinco minutos para arreglarse. Decide de antemano: una tasa de errores por encima de cierto umbral durante cierto tiempo, una función concreta rota, o sencillamente una hora límite a partir de la cual dejas de depurar y vuelves atrás.
La restricción que determina qué significa siquiera «reversión» son las escrituras. Desde el momento en que el host nuevo acepta su primera escritura, volver atrás significa o bien descartar esas escrituras o bien reproducirlas en la máquina antigua. Así que en realidad estás eligiendo entre dos productos distintos. Una reversión hecha antes de la primera escritura es un cambio de DNS y tarda minutos. Una reversión hecha después de un día de tráfico de producción es una migración en la dirección contraria, con todos los mismos pasos, y tarda lo mismo que describe esta guía. Averigua cuál de las dos tienes en cada momento, y ten en cuenta que la segunda es mucho más fácil si dejaste la base de datos de la máquina antigua en condiciones de recibir una restauración, en lugar de reutilizar la caja para otra cosa.
Mantén el servidor antiguo durante alrededor de una semana: encendido, en solo lectura, con el TTL del DNS todavía bajo, y la monitorización todavía apuntando hacia él. En el plan más pequeño, ese seguro cuesta unos dos dólares, que no es un número que deba pesar en la decisión. Lo que sí debería pesar es que una semana es tiempo suficiente para que las tareas cron semanales, los informes más o menos mensuales y la integración que solo se dispara los viernes hayan corrido al menos una vez en el host nuevo — esos son justo los fallos que una ventana de dos días se salta por completo.
Después, retira la máquina de forma deliberada. Confirma que el access log del host antiguo lleva un día plano. Hazle una última copia de seguridad y consérvala más tiempo del que crees que vas a necesitar. Revoca todo lo que tenía: claves de API, claves de despliegue, usuarios de base de datos, sus entradas en las listas blancas de IP de otras personas, sus comprobaciones de monitorización, su entrada SPF, su registro MX. Destruye la instancia. Y por último, devuelve los TTL del DNS a algo razonable — un TTL permanente de 300 segundos significa que los resolutores revalidan veinte veces por hora durante el resto de la vida del sitio, lo cual no te compra nada una vez terminada la migración y cuesta un poco de latencia en cada consulta en frío. Una hora es un valor permanente razonable; un día está bien para registros que nunca esperas que cambien deprisa.
La migración, en el orden en que hay que ejecutarla
Con una semana de antelación, inventaría la máquina antigua y escribe el runbook: paquetes, unidades activadas, crontabs, cortafuegos, sockets a la escucha, roles de base de datos, y cada tercero que tuviera en su lista blanca la dirección antigua. Con tres días de antelación, aprovisiona el VPS nuevo, restaura sobre él, y ensaya todo el proceso por nombre de host con una anulación de resolución — luego reconstrúyelo una vez a partir solo del inventario, para demostrar que el inventario es real. Con dos días de antelación, baja los TTL de A, AAAA y MX a 300, para que pase un TTL antiguo completo antes de que los necesites bajos.
Con un día de antelación, ejecuta la primera pasada de rsync con -aHAX --numeric-ids mientras producción sigue funcionando, y levanta la replicación de la base de datos o mide la ventana del volcado con el conjunto de datos real. Resuelve los certificados en la misma pasada — copia el directorio de certificados incluyendo la clave de cuenta ACME, o cambia a DNS-01 — y configura el registro PTR y la nueva entrada SPF en la dirección nueva antes de que se envíe ningún correo desde ella.
En la ventana: congela las escrituras, rsync final con --delete, termina la base de datos, arranca los servicios, verifica contra el nombre de host real en una ruta que toque la base de datos, confirma que la petición aterrizó en el log del host nuevo, y solo entonces cambia el DNS. Deja el host antiguo encendido y en solo lectura. Vigila los dos access logs hasta que el antiguo se aplane.
Una semana después: confirma que las tareas semanales han corrido en el host nuevo, hazle una última copia de seguridad al antiguo, revócale las claves y las entradas de listas blancas en todas partes, destrúyelo, y sube los TTL de nuevo. Si quieres que la máquina nueva sea mejor que la que dejaste, y no solo más nueva, los primeros quince minutos de bastionado son el siguiente paso natural, y es mucho más fácil hacerlo en un servidor que todavía no ha acumulado su propia capa sin documentar. Si todavía estás eligiendo dónde aterrizar, la guía de jurisdicciones cubre qué es lo que de verdad cambia entre Islandia, los Países Bajos, Rumanía y Suiza — y puedes tener la máquina de destino en marcha en aproximadamente un minuto para empezar el ensayo hoy mismo.