n8n self-hosted en producción cuesta entre 10 y 30 USD/mes en infraestructura y te da workflows ilimitados, control total de datos y libertad de inyectar código arbitrario. Comparado con n8n Cloud (a partir de 20 USD/mes con límites por ejecución), self-hosted es mejor opción para volúmenes medios y altos.
En esta guía técnica te llevamos paso a paso por la instalación productiva de n8n con Docker Compose y Traefik como reverse proxy. Stack que tenemos corriendo para clientes con miles de ejecuciones diarias.
Por qué este stack específico
Combinamos n8n + Docker Compose + Traefik + Postgres + Cloudflare por estas razones:
- Docker Compose: evita ensuciar el sistema y facilita deploy en cualquier servidor
- Traefik: reverse proxy con HTTPS automático vía Let’s Encrypt, sin configurar manualmente
- Postgres: motor de base de datos serio en lugar del SQLite que viene por default (frágil bajo carga)
- Cloudflare delante: protección DDoS, CDN para assets estáticos, oculta tu IP real
Hay alternativas (Caddy en lugar de Traefik, Nginx Proxy Manager, k3s para Kubernetes) pero este stack es el que mejor balance da entre simplicidad y robustez.
Requisitos previos
- VPS con Ubuntu 22.04 o 24.04 (recomendado: 2 vCPUs, 4 GB RAM mínimo para producción seria)
- Dominio apuntando al VPS (registro A en tu DNS)
- Cloudflare como DNS provider (opcional pero recomendado)
- Docker y Docker Compose instalados
- Puerto 80 y 443 abiertos en el firewall
Para instalar Docker en Ubuntu fresh:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
Estructura de directorios
Recomendamos esta organización:
/srv/docker/
├── traefik/
│ ├── docker-compose.yml
│ ├── .env
│ └── data/
│ ├── acme.json
│ └── traefik.yml
└── n8n/
├── docker-compose.yml
├── .env
└── data/
└── (volumen de n8n)
Paso 1: Configurar Traefik
Crea /srv/docker/traefik/data/traefik.yml:
api:
dashboard: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: "[email protected]"
storage: "/data/acme.json"
tlsChallenge: {}
Crea /srv/docker/traefik/docker-compose.yml:
services:
traefik:
image: traefik:v3.1
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/etc/traefik/traefik.yml:ro
- ./data/acme.json:/data/acme.json
networks:
- proxy
networks:
proxy:
external: true
Prepara el archivo de certificados y arranca Traefik:
cd /srv/docker/traefik
touch data/acme.json
chmod 600 data/acme.json
docker network create proxy
docker compose up -d
Paso 2: Configurar n8n
Crea /srv/docker/n8n/.env:
# Dominio
N8N_HOST=automation.tudominio.com
N8N_PROTOCOL=https
N8N_PORT=5678
WEBHOOK_URL=https://automation.tudominio.com/
# Postgres
DB_TYPE=postgresdb
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_USER=n8n_user
DB_POSTGRESDB_PASSWORD=password_seguro_largo
# Encryption key (generar único con: openssl rand -hex 32)
N8N_ENCRYPTION_KEY=tu_clave_de_32_caracteres
# Auth básico (recomendado en producción)
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=password_de_admin
# Timezone
GENERIC_TIMEZONE=America/Mexico_City
TZ=America/Mexico_City
# Email (para notificaciones de errores)
N8N_EMAIL_MODE=smtp
N8N_SMTP_HOST=smtp.mailgun.org
N8N_SMTP_PORT=587
[email protected]
N8N_SMTP_PASS=tu_password_smtp
Crea /srv/docker/n8n/docker-compose.yml:
services:
postgres:
image: postgres:16-alpine
container_name: n8n_postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_POSTGRESDB_USER}
POSTGRES_PASSWORD: ${DB_POSTGRESDB_PASSWORD}
POSTGRES_DB: ${DB_POSTGRESDB_DATABASE}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n_internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
- N8N_HOST=${N8N_HOST}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- N8N_PORT=${N8N_PORT}
- WEBHOOK_URL=${WEBHOOK_URL}
- DB_TYPE=${DB_TYPE}
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST}
- DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_BASIC_AUTH_ACTIVE=${N8N_BASIC_AUTH_ACTIVE}
- N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
- N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${TZ}
- N8N_EMAIL_MODE=${N8N_EMAIL_MODE}
- N8N_SMTP_HOST=${N8N_SMTP_HOST}
- N8N_SMTP_PORT=${N8N_SMTP_PORT}
- N8N_SMTP_USER=${N8N_SMTP_USER}
- N8N_SMTP_PASS=${N8N_SMTP_PASS}
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n_internal
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`${N8N_HOST}`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
volumes:
postgres_data:
n8n_data:
networks:
n8n_internal:
proxy:
external: true
Arranca:
cd /srv/docker/n8n
docker compose up -d
Espera 30-60 segundos a que Traefik provisione el certificado HTTPS. Después accede a https://automation.tudominio.com y entrarás al setup inicial de n8n.
Paso 3: Hardening de seguridad
Lo mínimo para producción seria:
Firewall UFW
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
Fail2ban contra brute force SSH
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
SSH solo con llave (deshabilitar password)
En /etc/ssh/sshd_config setea PasswordAuthentication no y reinicia ssh.
Updates automáticos
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Paso 4: Backups
n8n self-hosted sin backups es ruleta rusa. Esto es lo mínimo:
Backup diario de Postgres:
# /srv/scripts/backup-n8n.sh
#!/bin/bash
DATE=$(date +%Y-%m-%d_%H-%M)
BACKUP_DIR=/srv/backups/n8n
mkdir -p $BACKUP_DIR
docker exec n8n_postgres pg_dump -U n8n_user n8n | gzip > $BACKUP_DIR/n8n_$DATE.sql.gz
# Mantén solo últimos 14 días
find $BACKUP_DIR -name "n8n_*.sql.gz" -mtime +14 -delete
Programa con cron:
crontab -e
# Agregar:
0 3 * * * /srv/scripts/backup-n8n.sh
Para producción seria, también sincronizar a almacenamiento externo (S3, Backblaze B2, o segundo VPS).
Paso 5: Monitoreo
Mínimo viable:
- Uptime monitoring externo: UptimeRobot free tier checa cada 5 min
- Logs:
docker logs n8n --tail 200 --followcuando algo falla - Errors via email: n8n ya envía notificaciones cuando un workflow falla si configuras SMTP
Para escalas mayores: Grafana + Prometheus + Sentry. Pero para arranque, lo de arriba alcanza.
Performance tuning
Para n8n con muchas ejecuciones simultáneas:
Workers separados: n8n soporta modo “queue” donde main process recibe webhooks y workers paralelos procesan ejecuciones. Activa con:
# En .env
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
Y agrega un servicio Redis al compose. Después puedes escalar workers horizontalmente:
docker compose up -d --scale n8n_worker=4
Costos reales mensuales
VPS típico para n8n productivo:
- Hetzner CX22 (2 vCPU, 4 GB RAM, 40 GB SSD): 6 USD/mes
- DigitalOcean Basic Droplet (2 vCPU, 4 GB): 24 USD/mes
- Linode 4GB Shared: 24 USD/mes
- Hetzner CX32 (4 vCPU, 8 GB RAM) para volumen alto: 12 USD/mes
Hetzner gana por relación precio/performance. DigitalOcean por UX y comunidad.
Cloudflare es free para uso normal. Mailgun free tier 100 emails/día suficiente para alertas.
Total realista: 6-24 USD/mes para 10K-100K ejecuciones mensuales.
Cuándo n8n Cloud es mejor
Self-hosted no siempre gana:
- No tienes nadie con experiencia básica de DevOps en tu equipo
- Tu volumen es muy bajo (menos de 1,000 ejecuciones/mes)
- Tu data no es sensible y prefieres cero mantenimiento
- Necesitas SLA empresarial con soporte garantizado
Para todo lo demás, self-hosted es la elección correcta.
Quieres que lo instalemos por ti
Si quieres saltarte el setup y empezar a construir workflows el día 1, en DevActivo ofrecemos instalación productiva completa de n8n self-hosted (con todo lo descrito arriba: Postgres, Traefik, backups, monitoreo, Cloudflare) por 400 USD una sola vez. Incluye 30 días de soporte para ajustes y capacitación de tu equipo.
O si quieres todo el ecosistema (n8n + automatizaciones + agentes IA + integraciones), ver nuestro servicio completo de automatización con n8n e IA.
Servicios relacionados: