Saltar al contenido
deploy / · 4 min

Mover un stack a otro servidor: no copies el contenedor, copia tres cosas

Me pidieron llevar un bot de n8n a otro VPS. La imagen es la oficial, asi que copiarla no sirve de nada. Lo que hay que llevar cabe en un renglon, y una de las tres cosas son 56 bytes que si se te olvidan, arranca todo y no funciona nada.

Administrador · Desarrollador Laravel
Mover un stack a otro servidor: no copies el contenedor, copia tres cosas

«¿Podemos copiar el contenedor y montarlo en otro servidor?»

La pregunta es razonable y la respuesta es que no, pero no porque sea difícil: porque el contenedor no es donde está lo que te importa.

Por qué copiar el contenedor no sirve

La imagen de ese servicio es n8nio/n8n:2.34.6, bajada de Docker Hub sin modificar. Un docker commit o un docker save me daría un archivo de 2.11 GB idéntico a lo que cualquiera puede bajar con un docker pull.

Y el estado —los flujos, las credenciales, las conversaciones— no está dentro del contenedor. Está en un volumen y en una base de datos. Por diseño: es lo que permite reconstruir el contenedor sin perder nada, que es la mitad del sentido de usar Docker.

Así que lo que se muda son tres cosas:

Qué Dónde vive Peso
Flujos, credenciales, conversaciones la base de datos 92 MB
La clave de cifrado /home/node/.n8n/config 56 bytes
Configuración y secretos compose.yml y .env 2 KB

Los 56 bytes que arruinan la migración

Esta es la parte que hay que saber de antemano, porque falla tarde y en silencio.

n8n cifra las credenciales guardadas —contraseñas de base de datos, llaves de API— con una clave que genera la primera vez que arranca y guarda en un archivo dentro de su volumen:

$ docker exec n8n-pycos cat /home/node/.n8n/config
{
	"encryptionKey": "..."
}

Si migras la base de datos pero no llevas esa clave, el servidor nuevo arranca perfecto. Entras, ves tus flujos completos, ves las credenciales en la lista. Y al ejecutar, los nodos que usan una credencial fallan, porque la nueva instancia generó su propia clave y no puede descifrar lo que trajiste.

El síntoma no dice «clave de cifrado». Dice que la credencial no sirve. Es el clásico «migré n8n y no jala».

Lo limpio es no copiar el archivo, sino declarar la clave como variable de entorno en el destino:

N8N_ENCRYPTION_KEY=<la del servidor viejo>

Este patrón no es exclusivo de n8n. Laravel tiene su APP_KEY, y si la cambias las sesiones y todo lo cifrado con Crypt dejan de leerse. Grafana, Vaultwarden y media docena más tienen su equivalente. Cada vez que migres un servicio, la primera pregunta es cuál es su llave de cifrado y dónde vive.

El respaldo, con el servicio detenido

cd ~/apps/n8n-pycos
docker compose stop n8n
docker exec db-pycos pg_dump -U n8n -d pycos -Fc > /tmp/pycos.dump
docker compose start n8n

El stop de en medio no es paranoia. pg_dump toma una foto consistente, pero si el servicio sigue escribiendo mientras tanto, la foto es de un instante que ya pasó — y para un servicio con flujos corriendo cada minuto, eso significa ejecuciones a medias en el destino.

El formato -Fc es el comprimido de Postgres. Ocupa menos y pg_restore puede restaurar tablas sueltas si algo sale mal.

En el destino, dos ajustes antes de levantar

Quitar el directorio de inicialización. Si tu compose.yml monta un ./sql:/docker-entrypoint-initdb.d, ese script crea tablas en el primer arranque — y tu respaldo ya las trae. Chocan.

Cambiar el dominio. En n8n son N8N_HOST y WEBHOOK_URL; en Laravel, APP_URL y SESSION_DOMAIN. Si se te olvidan, el servicio funciona pero genera enlaces que apuntan al servidor viejo.

Y después de restaurar:

docker compose up -d db
docker exec -i db-pycos pg_restore -U n8n -d pycos --clean --if-exists < pycos.dump
docker compose up -d n8n

Lo último, que no está en ninguna guía

Desactivar y volver a activar los flujos desde la interfaz. n8n registra los webhooks en una tabla al activar un flujo, no al arrancar. Restauras la base, ves los flujos marcados como activos, y sus URLs devuelven 404 porque el registro apunta al host viejo.

Y apagar el origen. Si los dos servidores comparten un número de WhatsApp, una cuenta de API o una cola, dos instancias vivas se pelean los mensajes. La migración no termina cuando el destino funciona: termina cuando el origen está apagado.

#n8n #despliegue #docker #respaldos
Comentarios 0

Nadie ha comentado todavía. Estrena la sección.

Deja tu comentario
Tu correo no se publica. Reviso los comentarios antes de publicarlos.

Seguir leyendo