Por qué alojar n8n en su VPS
La versión cloud de n8n factura por ejecución más allá del plan y limita el número de workflows activos. En su VPS, el único coste es el del servidor, con independencia del número de automatizaciones o de llamadas API. Conserva además el control total sobre los credentials, las cargas útiles de los webhooks y el historial de ejecuciones — ningún dato transita por una infraestructura de terceros.
Las ventajas concretas de un n8n autoalojado
- Ejecuciones sin límite: ningún tope mensual, ningún sobrecoste al escalar.
- Credentials y payloads de webhooks confinados en su servidor, sin tránsito externo.
- Acceso a los nodes comunitarios y a la ejecución de código personalizado sin restricción.
- Webhooks en su propio dominio, configurables para cada integración entrante.
- Coste previsible: un precio de VPS fijo, independiente del volumen de automatizaciones.
- Persistencia controlada de los workflows y del historial en volúmenes de los que usted hace copia de seguridad.
- Compatibilidad con Ollama, Flowise o cualquier otro servicio Docker en la misma red interna.
Requisitos previos con cifras
Antes de empezar, compruebe que su VPS cumple los requisitos siguientes. Para un uso moderado, 1 vCPU y 1 GB de RAM bastan; prevea 2 vCPU y 2 GB en cuanto ejecute workflows pesados o concurrentes, y 4 GB si conecta una base PostgreSQL dedicada o integra un modelo de IA local. Cuente con 10 GB de disco como mínimo para Docker, los volúmenes y los logs. El puerto 5678 no debe exponerse directamente — n8n solo escucha en 127.0.0.1:5678 y todas las peticiones pasan por el reverse proxy en el puerto 443. Se requiere un subdominio (por ejemplo n8n.su-dominio.com) que apunte a la IP del VPS para HTTPS y los webhooks entrantes. Son necesarios Docker Engine 24+ y Docker Compose v2.
Instalación paso a paso
Actualizar el VPS e instalar Docker
Conéctese por SSH y actualice los paquetes:
apt update && apt upgrade -y. Instale después Docker con el script oficial:curl -fsSL https://get.docker.com | sh. Compruebe la instalación:docker --version && docker compose version. Cree el directorio de trabajo:mkdir -p /opt/n8n && cd /opt/n8n.Crear el archivo docker-compose.yaml
Cree
docker-compose.yamlcon el servicio n8n, un volumen con nombre para la persistencia y las variables de entorno esenciales. Declareimage: n8nio/n8n:latest,restart: unless-stopped, y monten8n_data:/home/node/.n8n. Exponga únicamente en127.0.0.1:5678:5678para evitar cualquier exposición pública directa del puerto.Fijar las variables de entorno críticas
En la sección
environmentdel servicio, declare como mínimo:N8N_HOST=n8n.su-dominio.com,N8N_WEBHOOK_URL=https://n8n.su-dominio.com/,N8N_PROXY_HOPS=1,N8N_BASIC_AUTH_ACTIVE=true,N8N_BASIC_AUTH_USER=<su-login>yN8N_BASIC_AUTH_PASSWORD=<contraseña-fuerte>. Para producción, guarde estos valores en un archivo.envadyacente y refiéralo conenv_file: .env.Arrancar el contenedor
Lance:
docker compose up -d. Compruebe que el contenedor funciona:docker compose ps. Consulte los logs:docker compose logs -f n8n. n8n está listo cuando aparece en los logs la líneaEditor is now accessible via: http://localhost:5678/.Configurar el reverse proxy con Caddy (recomendado)
Caddy es el reverse proxy más sencillo para n8n: gestiona el certificado Let's Encrypt y su renovación sin configuración adicional. Instale Caddy (
apt install caddy) y edite/etc/caddy/Caddyfilepara añadir:n8n.su-dominio.com { reverse_proxy localhost:5678 }. Recargue:systemctl reload caddy. Con nginx, añada en su bloquelocation:proxy_set_header X-Forwarded-Host $host;,proxy_set_header X-Forwarded-Proto $scheme;yproxy_set_header X-Real-IP $remote_addr;.Comprobar los webhooks entrantes
En el editor de n8n, cree un workflow de prueba con un node Webhook. La URL mostrada en modo producción debe ser exactamente
https://n8n.su-dominio.com/webhook/<su-ruta>. Dispare la llamada desde su máquina local:curl -X POST https://n8n.su-dominio.com/webhook/test -d '{}'. Si la URL mostrada contienelocalhosto el puerto5678, la variableN8N_WEBHOOK_URLno se tiene en cuenta.Conectar PostgreSQL para producción
SQLite sirve para probar; en producción, prefiera PostgreSQL. Añada un servicio
postgres:15al mismodocker-compose.yaml, con un volumen dedicadopg_data. En el servicio n8n, añada:DB_TYPE=postgresdb,DB_POSTGRESDB_HOST=postgres,DB_POSTGRESDB_DATABASE=n8n,DB_POSTGRESDB_USER=n8n,DB_POSTGRESDB_PASSWORD=<contraseña>. Reinicie el conjunto:docker compose up -d.
Endurecimiento y modo queue
Tres reflejos de producción: (1) No exponer nunca el puerto 5678 en la interfaz pública — mantenga el enlace 127.0.0.1:5678. (2) Active la autenticación: en v1.x, N8N_BASIC_AUTH_ACTIVE=true; en v1.27+, prefiera la autenticación nativa desde la interfaz (Ajustes → Seguridad). (3) Para workflows de IA o de larga duración, pase al modo queue con una instancia worker separada y una cola Redis.
Asegurar las ejecuciones persistidas (advisory GHSA-vrv8-j27g-g7cr)
En agosto de 2026, el advisory GHSA-vrv8-j27g-g7cr reveló que tres nodes vuelcan los credentials descifrados en los datos de ejecución persistidos en caso de error: el node Strapi (tokens OAuth escritos en claro en execution_data), el node SeaTable (claves API inscritas en los logs de ejecución de error) y el node Mailcheck (credenciales SMTP persistidas en execution_data). Estos secretos quedan legibles para cualquier usuario con acceso a los logs de ejecución en la interfaz de n8n. En una instancia sin pruning, se acumulan indefinidamente.
Cuatro gestos para corregir y prevenir
Actualizar a la versión que corrige el advisory
La actualización es la única corrección completa para los tres nodes. Compruebe su versión actual:
docker exec n8n n8n --version. Descargue la última imagen y relance:docker compose pull && docker compose up -d. Para la rama estable, la corrección está disponible a partir de la versión 2.35.4; para la rama v1, a partir de la versión 1.123.73.Activar el pruning de las ejecuciones
Añada dos variables en la sección
environmentdel servicio n8n:EXECUTIONS_DATA_PRUNE=trueyEXECUTIONS_DATA_MAX_AGE=168(7 días, expresado en horas). Reinicie el contenedor:docker compose restart n8n.Restringir el acceso a los logs de ejecución
En modo multiusuario, compruebe en Ajustes → Usuarios que solo los administradores pueden consultar los logs de ejecución.
Medida cautelar antes de la actualización
En una instancia todavía sin actualizar: desactive o retire los workflows que utilizan los nodes Strapi, SeaTable o Mailcheck.
Crash V8 fatal con más de 30 workflows activos
Síntoma. La instancia n8n se detiene bruscamente con el error FATAL ERROR: invalid-mark-compact are transition en los logs de Docker. El contenedor se reinicia si restart: unless-stopped está configurado, pero el crash se reproduce en cuanto la carga vuelve a pasar el mismo umbral.
Causa. Este error es un pánico del motor V8 durante un ciclo de garbage collection. Se desencadena cuando el heap de V8 está saturado — típicamente a partir de 30 workflows ejecutándose simultáneamente en un VPS con menos de 2 GB de RAM.
Corrección inmediata. Añada NODE_OPTIONS=--max-old-space-size=2048 en el entorno. Reinicie el contenedor: docker compose restart n8n.
Corrección estructural. Asigne al menos 2 GB de RAM a la VM por encima de 30 workflows activos. Para más de 50 workflows, prefiera el modo queue con Redis. Fuente: community.n8n.io thread #308425.
502 Bad Gateway persistente detrás de nginx
Síntoma. Las peticiones cortas tienen éxito pero ciertos workflows devuelven 502 Bad Gateway desde nginx exactamente 60 segundos después del inicio de la ejecución.
Causa. nginx espera por defecto 60 segundos una respuesta del backend (proxy_read_timeout = 60 s). Si la ejecución tarda más, nginx corta la conexión.
Corrección. Añada en el bloque location de nginx:
proxy_read_timeout 300;proxy_send_timeout 300;
Recargue nginx: nginx -t && systemctl reload nginx. Fuente: community.n8n.io thread #274581.
Breaking changes que conviene conocer (v1.27–v1.31)
Tres cambios de las versiones recientes pueden romper silenciosamente una instancia existente.
Renombrado del parámetro OAuth 2.0 en HTTP Request. Las peticiones autenticadas con OAuth 2.0 pueden dejar de funcionar sin mensaje de error explícito.
Formato de la URL de webhook. Si ha copiado URL de webhook fijas en servicios de terceros, vuelva a comprobarlas tras la actualización.
Obsolescencia de $item(). Su reemplazo es $input.item o $('Nombre del node').item.
La lista completa está disponible en la documentación oficial de n8n.
Resolución de los errores frecuentes
El puerto 5678 es inaccesible. Compruebe que el contenedor funciona y que escucha en 127.0.0.1:5678.
Los webhooks muestran localhost. La variable N8N_WEBHOOK_URL está ausente — añádala con la barra final y reinicie.
Error de permisos en el volumen. chown -R 1000:1000 /opt/n8n/data y reinicie el contenedor.
La base PostgreSQL rechaza la conexión. Compruebe la red Docker y las variables de entorno.
Crash V8 brutal. Añada NODE_OPTIONS=--max-old-space-size=2048. Vea la sección dedicada.
502 Bad Gateway persistente. Lleve proxy_read_timeout a 300 s. Vea la sección dedicada.
Credentials visibles en los logs. Actualice n8n y active el pruning. Vea la sección dedicada.
Rollback silencioso de SQLite bajo carga. Síntoma: ejecuciones desaparecidas o resultados inconsistentes sin error visible bajo alta concurrencia. Causa: SQLite no soporta escrituras concurrentes (issue GitHub n8n #32284). Solución única: migrar a PostgreSQL.
SQLite o PostgreSQL: la elección que lo cambia todo en producción
SQLite es un motor de pruebas, no un motor de producción. Es perfectamente adecuado para descubrir n8n en local o validar un workflow antes de desplegarlo. En cuanto su instancia recibe tráfico real — múltiples workflows lanzados en paralelo, webhooks entrantes, ejecuciones planificadas simultáneas — SQLite se convierte en un riesgo. El issue GitHub n8n #32284 documenta rollbacks silenciosos bajo carga concurrente: las ejecuciones desaparecen del historial sin mensajes de error, y los resultados intermedios se escriben de forma parcial.
Migrar a PostgreSQL. El procedimiento en tres pasos:
1. Exporte los workflows existentes: n8n export:workflow --all --output=/opt/n8n/workflows-backup.json
2. Modifique el .env para cambiar el motor: DB_TYPE=postgresdb con las variables correspondientes.
3. Reinicie todo (docker compose up -d) e importe: n8n import:workflow --input=/opt/n8n/workflows-backup.json.
Almacenamiento persistente independiente. El volumen PostgreSQL (pg_data) debe montarse en un almacenamiento persistente independiente del host. Verifique siempre con docker volume ls que el volumen existe.
Dimensionamiento. PostgreSQL consume entre 50 y 100 MB de RAM adicional en carga ligera. Planifique al menos 2 GB de RAM para n8n + PostgreSQL en el mismo VPS; 4 GB si ejecuta regularmente workflows de IA o importaciones voluminosas.
Cuatro configuraciones críticas para una producción estable
Estos cuatro puntos concentran la mayor parte de los incidentes reportados en community.n8n.io y DEV Community en 2026. Cada uno es independiente y puede aplicarse a una instancia existente sin redespliegue completo.
1. N8N_WEBHOOK_URL es obligatorio en el .env. Sin esta variable, n8n reconstruye la URL de webhook combinando el hostname interno del contenedor y el puerto 5678. El resultado es una URL inutilizable desde cualquier servicio externo. Además, la URL cambia en cada recreación del contenedor. Establezca N8N_WEBHOOK_URL=https://n8n.su-dominio.com/ (con barra final) y no la omita nunca.
2. RAM mínima 2 GB, recomendada de 4 a 8 GB. Un VPS con 1 GB de RAM es insuficiente en cuanto n8n ejecuta varios workflows simultáneamente. El OOM killer de Linux termina el proceso Node.js sin log explícito en n8n, creando un ciclo de crashes difícil de diagnosticar. El mínimo documentado por n8n para producción es 2 GB; 4 a 8 GB se recomiendan para instancias con workflows de IA o más de 20 workflows activos.
3. Headers WebSocket de nginx son obligatorios para el editor. La interfaz de n8n se comunica con el backend vía WebSocket para la ejecución en tiempo real. Sin estos dos headers en el bloque location de nginx, la conexión WebSocket es rechazada y el editor queda inaccesible o se congela:
proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
Caddy los gestiona automáticamente; con nginx deben añadirse explícitamente.
4. Purga automática del historial de ejecución. Sin purga, la tabla de ejecuciones crece indefinidamente. En una instancia activa durante meses puede llegar a varios gigabytes y degradar significativamente el rendimiento. Active la purga con:
EXECUTIONS_DATA_PRUNE=trueEXECUTIONS_DATA_MAX_AGE=168
El valor 168 corresponde a 7 días expresados en horas. Ajuste según su necesidad de retención.
Mantener y hacer evolucionar la instancia
Para las actualizaciones, dos enfoques: Watchtower o una tarea cron manual (docker pull n8nio/n8n:latest && docker compose up -d). En ambos casos, lea las notas de versión antes de una actualización mayor. Mantenga sus exportaciones de workflows al día en un repositorio git.
Para los advisories de seguridad, siga la página GitHub Security Advisories del repositorio n8n.