Material de referencia

Deploy y
self-hosting

La versión ampliada de "correr n8n vos mismo": Docker, docker-compose con Postgres, la tabla completa de variables de entorno, la clave de cifrado, reverse proxy, modo cola y backups. Volvé acá cuando estés armando o mantiniendo una instancia real.

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 CloudPikaPodsDocker en VPSnpm / npx
Quién administran8nPikaPodsVosVos
Requiere DockerNoNoNo
Control de variables de entornoNingunoParcialTotalTotal
Ideal paraCero adminProducción barata sin servidorProducción con requisitos propiosProbar local, desarrollo
Si buscás el paso a paso narrado

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
Por qué el volumen es imprescindible

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.

VariablePara quéDefault
DB_TYPEMotor de base de datos: sqlite o postgresdb.sqlite
DB_POSTGRESDB_HOSTHost del servidor Postgres.localhost
DB_POSTGRESDB_PORTPuerto de Postgres.5432
DB_POSTGRESDB_DATABASENombre de la base.n8n
DB_POSTGRESDB_USERUsuario de conexión.postgres
DB_POSTGRESDB_PASSWORDContraseña del usuario.sin default
DB_POSTGRESDB_SCHEMASchema 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

VariablePara quéEjemplo / default
N8N_HOSTHost name en el que corre n8n.localhost
N8N_PORTPuerto HTTP.5678
N8N_PROTOCOLProtocolo para construir URLs: http o https.http
N8N_PATHPath base donde se sirve n8n./
N8N_LISTEN_ADDRESSDirección IP en la que escucha el proceso.::
N8N_WEBHOOK_URLURL pública a usar en los webhooks. Reemplaza a la variable deprecada WEBHOOK_URL.https://n8n.tudominio.com/
N8N_EDITOR_BASE_URLURL pública donde los usuarios acceden al editor.sin default
N8N_PROXY_HOPSCantidad de reverse proxies delante de n8n.0

Seguridad

VariablePara quéEjemplo / default
N8N_ENCRYPTION_KEYClave con la que n8n cifra las credenciales antes de guardarlas. Ver sección dedicada abajo.se autogenera
N8N_SECURE_COOKIEFuerza que la cookie de sesión solo viaje por HTTPS.true
N8N_BLOCK_ENV_ACCESS_IN_NODESi es true, bloquea el acceso a variables de entorno del servidor desde expresiones y el nodo Code.false
NODES_EXCLUDEArray 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_INCLUDEArray de nodos permitidos (whitelist).sin default

Zona horaria

VariablePara quéEjemplo / default
GENERIC_TIMEZONEZona horaria de la instancia; la usan los nodos Schedule/Cron.America/New_York
TZZona horaria del sistema y de los logs. Se recomienda igual que la anterior.America/Argentina/Buenos_Aires

Ejecuciones

VariablePara quéEjemplo / default
EXECUTIONS_DATA_PRUNESi borra automáticamente el historial de ejecuciones viejas.true
EXECUTIONS_DATA_MAX_AGEAntigüedad en horas antes de borrar una ejecución (con prune activo).336 (14 días)
EXECUTIONS_DATA_SAVE_ON_SUCCESSSi guarda la data de ejecuciones exitosas.all
EXECUTIONS_TIMEOUTTimeout por defecto (en segundos) que corta cualquier workflow.-1 (sin límite)

Nodo Code

VariablePara quéEjemplo / default
NODE_FUNCTION_ALLOW_EXTERNALMódulos externos (de node_modules) permitidos en el nodo Code. Sin esta variable, no se permite ninguno.moment,lodash
NODE_FUNCTION_ALLOW_BUILTINMódulos nativos de Node permitidos en el nodo Code.crypto,fs

Task runners

VariablePara quéEjemplo / default
N8N_RUNNERS_ENABLEDDeprecada 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

VariablePara quéEjemplo / default
N8N_DIAGNOSTICS_ENABLEDTelemetría anónima hacia n8n.true
N8N_PERSONALIZATION_ENABLEDEncuesta de personalización en el primer arranque.true
N8N_TEMPLATES_ENABLEDHabilita la galería de templates dentro del editor.true
N8N_DEFAULT_LOCALEIdioma de la interfaz. n8n no soporta variantes regionales (ej. de-AT).en

La clave de cifrado: lo más crítico de todo

N8N_ENCRYPTION_KEY — leé esto antes de deployar en serio

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:

Por qué WEBHOOK_URL / N8N_WEBHOOK_URL es imprescindible

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.

VariablePara quéDefault
EXECUTIONS_MODEActiva el modo cola con el valor queue (por defecto es regular).regular
QUEUE_BULL_REDIS_HOSTHost del servidor Redis.localhost
QUEUE_BULL_REDIS_PORTPuerto de Redis.6379
QUEUE_BULL_REDIS_PASSWORDPassword de Redis, si tiene.sin default
¿Hace falta esto para empezar?

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.

Qué respaldar

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.

Para seguir

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.