Panorama: las formas de correr n8n
Ya viste el resumen narrado en 04 · n8n desde cero. Acá está la versión de consulta rápida, con foco en self-hosting: qué elegir según cuánto control necesitás y cuánto querés administrar vos.
| n8n Cloud | PikaPods | Docker en VPS | npm / npx | |
|---|---|---|---|---|
| Quién administra | n8n | PikaPods | Vos | Vos |
| Requiere Docker | No | No | Sí | No |
| Control de variables de entorno | Ninguno | Parcial | Total | Total |
| Ideal para | Cero admin | Producción barata sin servidor | Producción con requisitos propios | Probar local, desarrollo |
Esta página asume que ya elegiste self-hosting (Docker en un VPS) y querés la referencia técnica completa. Para el recorrido guiado de las tres opciones —incluyendo PikaPods paso a paso— anda a 04 · n8n desde cero.
Instalación con Docker
La imagen oficial es docker.n8n.io/n8nio/n8n. El comando mínimo para levantar una instancia con datos persistentes:
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e GENERIC_TIMEZONE="America/Argentina/Buenos_Aires" \
-e TZ="America/Argentina/Buenos_Aires" \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
Sin -v n8n_data:/home/node/.n8n, todo lo que n8n guarda ahí adentro —la base de datos SQLite por defecto, la clave de cifrado autogenerada y los archivos de configuración— vive dentro del contenedor. El día que ese contenedor se borra o se recrea (un docker rm, una actualización mal hecha), perdés workflows, credenciales y todo lo demás. El volumen nombrado persiste esos datos por fuera del ciclo de vida del contenedor.
Para correr un comando único sin quedar pegado a la terminal, usá -d (detached) en vez de -it --rm, y agregá --restart unless-stopped para que vuelva a levantarse solo si el servidor reinicia.
Docker Compose: n8n + Postgres
Para producción conviene separar n8n de la base de datos desde el principio. Un compose.yml realista, con Postgres y un .env aparte para los secretos:
# compose.yml
volumes:
n8n_data:
db_storage:
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- db_storage:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
ports:
- "5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: n8n.tudominio.com
N8N_PROTOCOL: https
N8N_PORT: 5678
N8N_WEBHOOK_URL: https://n8n.tudominio.com/
GENERIC_TIMEZONE: America/Argentina/Buenos_Aires
TZ: America/Argentina/Buenos_Aires
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
Y el .env con los secretos, que nunca se sube al repo:
# .env
POSTGRES_USER=n8n
POSTGRES_PASSWORD=cambiar-esta-clave
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=generar-una-clave-larga-y-guardarla-aparte
Arriba con docker compose up -d. Nota: si ya tenías una instancia corriendo con SQLite, los datos no migran solos a Postgres — este setup es para arrancar limpio o para migrar a mano.
Base de datos: SQLite vs. PostgreSQL
n8n usa SQLite por defecto (DB_TYPE=sqlite): un archivo dentro del volumen, cero configuración, perfecto para arrancar o para instancias personales. Para producción con volumen real de ejecuciones, PostgreSQL es lo recomendado: soporta mejor la concurrencia y es el motor que usa n8n Cloud internamente.
| Variable | Para qué | Default |
|---|---|---|
DB_TYPE | Motor de base de datos: sqlite o postgresdb. | sqlite |
DB_POSTGRESDB_HOST | Host del servidor Postgres. | localhost |
DB_POSTGRESDB_PORT | Puerto de Postgres. | 5432 |
DB_POSTGRESDB_DATABASE | Nombre de la base. | n8n |
DB_POSTGRESDB_USER | Usuario de conexión. | postgres |
DB_POSTGRESDB_PASSWORD | Contraseña del usuario. | sin default |
DB_POSTGRESDB_SCHEMA | Schema de Postgres a usar. | public |
Variables de entorno: la tabla completa
n8n se configura enteramente por variables de entorno. Están agrupadas por familia; nombres verificados contra la documentación oficial de n8n.
Host / URL
| Variable | Para qué | Ejemplo / default |
|---|---|---|
N8N_HOST | Host name en el que corre n8n. | localhost |
N8N_PORT | Puerto HTTP. | 5678 |
N8N_PROTOCOL | Protocolo para construir URLs: http o https. | http |
N8N_PATH | Path base donde se sirve n8n. | / |
N8N_LISTEN_ADDRESS | Dirección IP en la que escucha el proceso. | :: |
N8N_WEBHOOK_URL | URL pública a usar en los webhooks. Reemplaza a la variable deprecada WEBHOOK_URL. | https://n8n.tudominio.com/ |
N8N_EDITOR_BASE_URL | URL pública donde los usuarios acceden al editor. | sin default |
N8N_PROXY_HOPS | Cantidad de reverse proxies delante de n8n. | 0 |
Seguridad
| Variable | Para qué | Ejemplo / default |
|---|---|---|
N8N_ENCRYPTION_KEY | Clave con la que n8n cifra las credenciales antes de guardarlas. Ver sección dedicada abajo. | se autogenera |
N8N_SECURE_COOKIE | Fuerza que la cookie de sesión solo viaje por HTTPS. | true |
N8N_BLOCK_ENV_ACCESS_IN_NODE | Si es true, bloquea el acceso a variables de entorno del servidor desde expresiones y el nodo Code. | false |
NODES_EXCLUDE | Array de nodos que no se cargan. Útil para bloquear nodos riesgosos si los usuarios no son de confianza. | ["n8n-nodes-base.executeCommand", "n8n-nodes-base.localFileTrigger"] |
NODES_INCLUDE | Array de nodos permitidos (whitelist). | sin default |
Zona horaria
| Variable | Para qué | Ejemplo / default |
|---|---|---|
GENERIC_TIMEZONE | Zona horaria de la instancia; la usan los nodos Schedule/Cron. | America/New_York |
TZ | Zona horaria del sistema y de los logs. Se recomienda igual que la anterior. | America/Argentina/Buenos_Aires |
Ejecuciones
| Variable | Para qué | Ejemplo / default |
|---|---|---|
EXECUTIONS_DATA_PRUNE | Si borra automáticamente el historial de ejecuciones viejas. | true |
EXECUTIONS_DATA_MAX_AGE | Antigüedad en horas antes de borrar una ejecución (con prune activo). | 336 (14 días) |
EXECUTIONS_DATA_SAVE_ON_SUCCESS | Si guarda la data de ejecuciones exitosas. | all |
EXECUTIONS_TIMEOUT | Timeout por defecto (en segundos) que corta cualquier workflow. | -1 (sin límite) |
Nodo Code
| Variable | Para qué | Ejemplo / default |
|---|---|---|
NODE_FUNCTION_ALLOW_EXTERNAL | Módulos externos (de node_modules) permitidos en el nodo Code. Sin esta variable, no se permite ninguno. | moment,lodash |
NODE_FUNCTION_ALLOW_BUILTIN | Módulos nativos de Node permitidos en el nodo Code. | crypto,fs |
Task runners
| Variable | Para qué | Ejemplo / default |
|---|---|---|
N8N_RUNNERS_ENABLED | Deprecada desde n8n 2.0 — los task runners ya corren por defecto y no hace falta activarlos a mano. Solo aplica si todavía estás en una versión 1.x. | false |
Otros
| Variable | Para qué | Ejemplo / default |
|---|---|---|
N8N_DIAGNOSTICS_ENABLED | Telemetría anónima hacia n8n. | true |
N8N_PERSONALIZATION_ENABLED | Encuesta de personalización en el primer arranque. | true |
N8N_TEMPLATES_ENABLED | Habilita la galería de templates dentro del editor. | true |
N8N_DEFAULT_LOCALE | Idioma de la interfaz. n8n no soporta variantes regionales (ej. de-AT). | en |
La clave de cifrado: lo más crítico de todo
La primera vez que arranca, n8n genera solo una clave aleatoria y la guarda en ~/.n8n (dentro del volumen). Con esa clave cifra todas las credenciales antes de guardarlas en la base de datos. El problema: si esa clave se pierde o cambia —un volumen mal migrado, un contenedor recreado sin persistencia—, las credenciales guardadas quedan indescifrables para siempre y hay que volver a cargar cada una a mano.
La solución es fijarla vos mismo antes del primer arranque con la variable N8N_ENCRYPTION_KEY, y guardarla aparte —en un gestor de contraseñas, no solo en el volumen. Así podés recrear la instancia en otro servidor sin perder nada, siempre que migres la base de datos y esta clave juntas.
Reverse proxy y HTTPS
Si ponés n8n detrás de un reverse proxy (Nginx, Caddy, Traefik) para servirlo con HTTPS en un dominio propio, dos variables son las que evitan el dolor de cabeza más común:
n8n construye la URL pública de los webhooks combinando N8N_PROTOCOL, N8N_HOST y N8N_PORT. Pero n8n corre puertas adentro en el puerto 5678, mientras el proxy lo expone afuera en el 443 con otro dominio — esa combinación automática se rompe. Sin fijar N8N_WEBHOOK_URL a mano, los webhooks se generan con localhost:5678 en vez de tu dominio real, y cualquier servicio externo que intente llamarlos falla.
N8N_PROXY_HOPS le dice a n8n cuántos proxies hay delante suyo, para que interprete correctamente headers como X-Forwarded-For (necesario, por ejemplo, para que el rate-limiting y los logs vean la IP real del cliente y no la del proxy).
Escalar: modo cola (queue mode)
Para volumen alto de ejecuciones, una sola instancia de n8n deja de alcanzar. El modo cola separa el problema en dos roles: una instancia main que recibe triggers y encola el trabajo, y uno o más workers que lo van tomando de la cola y ejecutando en paralelo. La cola vive en Redis.
Levantá un Redis
Cualquier instancia de Redis accesible por red desde el main y los workers.
Activá el modo cola en todas las instancias
Seteá EXECUTIONS_MODE=queue tanto en la instancia main como en cada worker. Configurá también QUEUE_BULL_REDIS_HOST (y opcionalmente QUEUE_BULL_REDIS_PORT, QUEUE_BULL_REDIS_PASSWORD) apuntando al mismo Redis en todas.
Arrancá los workers
Con Docker: docker run docker.n8n.io/n8nio/n8n worker. Desde el binario: n8n worker. Podés levantar varios workers en paralelo para más throughput.
Replicá TODAS las variables relevantes
La clave N8N_ENCRYPTION_KEY tiene que ser idéntica en el main y en cada worker: sin ella, los workers no pueden descifrar las credenciales para ejecutar los nodos. Lo mismo aplica a la configuración de base de datos y cualquier otra variable que afecte cómo se ejecuta un workflow.
| Variable | Para qué | Default |
|---|---|---|
EXECUTIONS_MODE | Activa el modo cola con el valor queue (por defecto es regular). | regular |
QUEUE_BULL_REDIS_HOST | Host del servidor Redis. | localhost |
QUEUE_BULL_REDIS_PORT | Puerto de Redis. | 6379 |
QUEUE_BULL_REDIS_PASSWORD | Password de Redis, si tiene. | sin default |
No. El modo cola es para cuando el volumen de ejecuciones realmente lo justifica —muchos workflows corriendo en simultáneo, picos de tráfico. Una instancia regular con Postgres aguanta perfectamente el uso normal de un equipo chico o mediano.
Actualizar y hacer backups
Actualizar una instancia con Docker es simple: bajar la imagen nueva y recrear el contenedor (no reconstruirlo desde cero, solo apuntarlo a la imagen nueva):
docker pull docker.n8n.io/n8nio/n8n
docker compose up -d
Como los datos viven en el volumen y en Postgres (no en el contenedor), recrearlo no pierde nada. Igual conviene revisar el changelog antes de saltar versiones grandes.
Dos cosas, y las dos juntas —una sin la otra no sirve: la base de datos (el volumen .n8n completo si usás SQLite, o un dump de Postgres si migraste) y la clave de cifrado N8N_ENCRYPTION_KEY. Sin la clave, el backup de la base de datos es un archivo de credenciales cifradas que nadie puede volver a leer.
Si preferís no administrar nada de esto vos, 04 · n8n desde cero tiene el paso a paso de PikaPods, el punto medio gestionado. Y la fuente de verdad para todo lo de esta página es la documentación oficial de hosting de n8n.