Instalar n8n Paso a Paso: Guía Completa de Despliegue Self-Hosted
📋 Introducción
n8n es una plataforma open source de automatización de flujos de trabajo (workflow automation) que permite construir procesos complejos mediante una interfaz visual low-code/no-code, complementada con la capacidad de inyectar código personalizado (JavaScript/Python). Su característica más destacada es su enfoque nativo en AI Agents, permitiendo orquestar sistemas RAG y manejar el razonamiento de IA de forma controlada.
Esta guía está basada en la documentación oficial de n8n y cubre instalación con Docker Compose, configuración de persistencia, HTTPS, backup, actualización y troubleshooting.
⚙️ Prerrequisitos Verificados
- Docker Engine instalado y funcionando
- Docker Compose v2 (verificar con:
docker compose version) - Mínimo 4 GB de RAM y 2 vCPUs
- Para sandbox AI: Docker-in-Docker necesita más recursos
- Windows: Usar WSL con Docker Desktop (WSL2 backend) o Docker Engine en Linux
- Mantener el proyecto dentro del filesystem de WSL (
~/n8n), no bajo/mnt/c/...
📁 Paso 1: Crear Carpeta del Proyecto
mkdir n8n && cd n8n
🔐 Paso 2: Crear Archivo .env con Secretos
Crea un archivo .env con tus propios valores (nunca en control de versiones):
# n8n version - get latest stable from https://github.com/n8n-io/n8n/releases
N8N_VERSION=change-me-version-number
# Sandbox service version
N8N_SANDBOX_VERSION=change-me-sandbox-version-number
# n8n task runner authentication (generate random secret)
N8N_RUNNERS_AUTH_TOKEN=change-me-runner-auth-token
# Sandbox service secrets — pick your own values
SANDBOX_API_KEYS=change-me-api-key
SANDBOX_API_RUNNER_REGISTRATION_TOKEN=change-me-registration-token
SANDBOX_API_RUNNER_API_KEY=change-me-runner-key
# Must match a value in SANDBOX_API_KEYS above
N8N_SANDBOX_SERVICE_API_KEY=change-me-api-key
# Web search: secret for bundled SearXNG instance
SEARXNG_SECRET=change-me-searxng-secret
# n8n AI assistant URL (bundled SearXNG)
N8N_INSTANCE_AI_SEARXNG_URL=http://searxng:8080
Importante: Genera valores únicos para todos los tokens de autenticación. Nunca uses change-me-... en producción.
🔍 Paso 3: Crear searxng-settings.yml
El stock SearXNG image solo sirve HTML; n8n necesita su JSON API:
# Archivo: searxng-settings.yml
format: json
api_enabled: true
🐳 Paso 4: Crear compose.yml
Define todos los servicios (n8n, sandbox stack, SearXNG):
# Archivo: compose.yml
version: '3.8'
services:
n8n:
image: n8nio/n8n:${N8N_VERSION}
container_name: n8n
ports:
- "5678:5678"
environment:
- N8N_HOST=0.0.0.0
- N8N_PORT=5678
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.local/share/n8n
restart: unless-stopped
sandbox-certs:
image: n8nio/sandbox-certs:${N8N_SANDBOX_VERSION}
container_name: sandbox-certs
environment:
- SANDBOX_API_KEYS=${SANDBOX_API_KEYS}
- SANDBOX_RUNNER_REGISTRATION_TOKEN=${SANDBOX_RUNNER_REGISTRATION_TOKEN}
- N8N_SANDBOX_SERVICE_API_KEY=${N8N_SANDBOX_SERVICE_API_KEY}
volumes:
- sandbox-tls:/etc/sandbox-tls
entrypoint: /bin/sh -c "./generate-certs.sh && exit 0"
sandbox-api:
image: n8nio/sandbox-api:${N8N_SANDBOX_VERSION}
container_name: sandbox-api
depends_on:
- sandbox-certs
environment:
- SANDBOX_API_KEYS=${SANDBOX_API_KEYS}
- SANDBOX_RUNNER_REGISTRATION_TOKEN=${SANDBOX_RUNNER_REGISTRATION_TOKEN}
- N8N_SANDBOX_SERVICE_API_KEY=${N8N_SANDBOX_SERVICE_API_KEY}
volumes:
- sandbox-tls:/etc/sandbox-tls
- n8n_data:/home/node/.local/share/n8n
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
sandbox-runner-1:
image: n8nio/sandbox-runner:${N8N_SANDBOX_VERSION}
container_name: sandbox-runner-1
privileged: true
depends_on:
- sandbox-api
- sandbox-certs
environment:
- SANDBOX_RUNNER_API_KEYS=${SANDBOX_API_KEYS}
- SANDBOX_RUNNER_REGISTRATION_TOKEN=${SANDBOX_RUNNER_REGISTRATION_TOKEN}
- N8N_SANDBOX_SERVICE_API_KEY=${N8N_SANDBOX_SERVICE_API_KEY}
volumes:
- sandbox-tls:/etc/sandbox-tls
- n8n_data:/home/node/.local/share/n8n
searxng:
image: docker.io/searxng/searxng:latest
container_name: searxng
ports:
- "8080:8080"
volumes:
- ./searxng-settings.yml:/etc/searxng/settings.yml
environment:
- SEARXNG_SECRET=${SEARXNG_SECRET}
volumes:
n8n_data:
sandbox-tls:
▶️ Paso 5: Iniciar Todo
docker compose up -d --wait
Espera hasta que sandbox-api muestre healthy; sandbox-runner-1 y n8n iniciarán automáticamente.
✅ Paso 6: Verificar que Funciona
docker compose ps
Lanza n8n apuntando tu navegador a: http://localhost:5678
🗄️ Opcional: Usar PostgreSQL en vez de SQLite
SQLite es bien para probar, pero para producción usa Postgres:
# Añadir a .env
POSTGRES_USER=n8n
POSTGRES_PASSWORD=change-me-postgres-password
POSTGRES_DB=n8n
# Añadir a compose.yml:
postgres:
image: postgres:18-alpine
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
# Añadir a n8n service:
environment:
- N8N_DATABASE_TYPE=postgres
- N8N_DATABASE_HOST=postgres
- N8N_DATABASE_PORT=5432
- N8N_DATABASE_USER=${POSTGRES_USER}
- N8N_DATABASE_PASSWORD=${POSTGRES_PASSWORD}
- N8N_DATABASE_NAME=${POSTGRES_DB}
- N8N_WAIT_FOR_DB=true
Importante: Para Postgres 18, establecer PGDATA mantiene los datos en la misma carpeta.
🔒 Opcional: Configurar HTTPS con Nginx Reverse Proxy
# Añadir a compose.yml:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl/certs:/etc/nginx/ssl:ro
depends_on:
- n8n
# Archivo: nginx/nginx.conf
server {
listen 443 ssl http2;
server_name tu-dominio.com;
ssl_certificate /etc/nginx/ssl/tu-dominio.crt;
ssl_certificate_key /etc/nginx/ssl/tu-dominio.key;
location / {
proxy_pass http://n8n:5678;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
💾 Backup y Actualización
Backup de Datos
Los volúmenes Docker contienen los flujos, credenciales y logs:
# Backup completo
docker compose stop
docker compose run --rm n8n tar -czf backup-n8n-$(date +%Y%m%d).tar.gz /home/node/.local/share/n8n
docker compose start
Actualización de n8n
# Backup primero
docker compose stop
docker run --rm -v n8n_data:/data n8nio/n8n:latest tar -czf /tmp/backup.tar.gz /data
# Actualizar imagen
docker compose pull
docker compose up -d
🔧 Troubleshooting Común
| Síntoma | Causa Probable | Solución |
|---|---|---|
| sandbox-api o sandbox-runner-1 fallan al iniciar | cert errors / sandbox-certs no completó | docker compose logs sandbox-certs |
| sandbox-api nunca se vuelve healthy | wget no existe en la imagen | Verificar logs del contenedor |
| sandbox-runner-1 crash-loops con "must be set" | Faltan variables de entorno requeridas | Comprobar SANDBOX_RUNNER_API_KEYS, SANDBOX_RUNNER_REGISTRATION_TOKEN |
| Runner nunca se registra con la API | Tokens no coinciden o GRPC_ADDR incorrecto | Verificar SANDBOX_RUNNER_REGISTRATION_TOKEN y SANDBOX_API_KEYS |
| Falla en Linux, funciona en WSL | Problema de bind-mount path | Mantener proyecto dentro del filesystem de WSL |
🛡️ Checklist de Seguridad
sandbox-runner-1(privileged: true) nunca expuesto a internet público- Todos los tokens generados con valores únicos, no
change-me-... - Rotación periódica de
SANDBOX_API_KEYS, tokens y claves sandbox-apiysandbox-runner-1no usanenv_file; reciben variables explícitamente- Claves mTLS bajo
sandbox-tlsbloqueadas a 0600 - Ninguna clave es world-readable
❓ FAQ (Preguntas Frecuentes)
¿Puedo usar n8n con mis propios datos en la nube?
Sí. Al ser self-hostable, tienes control total sobre los datos y puedes desplegarlo en cualquier infraestructura cloud (AWS, GCP, Azure) o incluso en un entorno air-gapped.
¿Qué es el concepto de 'Human-in-the-Loop' en n8n?
Es una característica avanzada que permite integrar aprobaciones humanas o validaciones manuales dentro del flujo automatizado. Crucial para contener acciones de IA o transacciones financieras.
¿Cómo actualizo n8n sin perder datos?
Siempre haz backup primero con los volúmenes Docker, luego actualiza la imagen y restaura si es necesario. Los flujos versionados dentro del sistema ayudan a mitigar pérdida de lógica.
¿Puedo migrar de SQLite a PostgreSQL?
Sí, pero no es una migración in-place. Necesitas backup con pg_dumpall, seguir la guía oficial de upgrade de PostgreSQL y configurar n8n para usar Postgres.