n8n es una plataforma de automatización de flujos de trabajo de código abierto. Permite conectar servicios, APIs y bases de datos mediante un editor visual sin necesidad de escribir cientos de líneas de código, aunque sí permite ejecutar JavaScript o Python cuando se necesita lógica personalizada.
En esta guía vas a desplegar n8n en un servidor Ubuntu usando Docker Compose, con PostgreSQL como base de datos, Redis como gestor de colas, workers dedicados para ejecución en segundo plano, Caddy como proxy inverso con SSL automático, y buenas prácticas para un entorno de producción.
Diagrama realizado con https://savnet.co
Prerrequisitos
- Un servidor con Ubuntu 22.04 o 24.04 (1 vCPU, 2 GB RAM mínimo; 2 vCPU, 4 GB RAM recomendado)
- Acceso root para la configuración inicial
- Un dominio o subdominio apuntando (registro A) a la IP del servidor
- Puertos 80 y 443 abiertos en el firewall
- Conocimientos básicos de línea de comandos
¿Aún no tienes servidor?
Si buscas economía y buen rendimiento, DigitalOcean es una opción sólida. Puedes empezar con este enlace de referido:
https://m.do.co/c/2c579acd7121
1. Conexión inicial y actualización del sistema
Conéctate vía SSH como root y actualiza los paquetes:
ssh root@tu-servidor
apt update && apt upgrade -y
2. Crear usuario administrador dedicado
Vamos a crear un usuario n8n con permisos sudo. A partir de este punto, todo el trabajo se hará con este usuario, no con root.
# Crear el usuario
adduser --gecos "" n8n
# Agregarlo al grupo sudo
usermod -aG sudo n8n
# Verificar
id n8n
Antes de cerrar la sesión, copia tu clave pública de root al nuevo usuario para poder conectarte directamente como n8n:
# Copiar la llave autorizada para conexión SSH de root a n8n
mkdir -p /home/n8n/.ssh
cp ~/.ssh/authorized_keys /home/n8n/.ssh/authorized_keys
chown -R n8n:n8n /home/n8n/.ssh
chmod 700 /home/n8n/.ssh
chmod 600 /home/n8n/.ssh/authorized_keys
Ahora cierra sesión y reconéctate como n8n:
exit
ssh n8n@tu-servidor
¿Por qué un usuario dedicado?
Porque ejecutar servicios directamente con root es una mala práctica de seguridad. Si alguien compromete el proceso de n8n, tendría acceso total al servidor. Con un usuario dedicado, el daño queda acotado.
3. Instalar Docker y Docker Compose
# Paquetes necesarios
sudo apt install -y ca-certificates curl gnupg
# Agregar clave GPG oficial de Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Agregar repositorio
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Instalar Docker Engine y Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Agregar tu usuario al grupo docker (para no usar sudo con cada comando)
sudo usermod -aG docker $USER
# Verificar
docker --version
docker compose version
# Reingresar para hacer efectivos los cambios de grupo
sudo init 6
ssh n8n@tu-servidor
4. Crear estructura de directorios
sudo mkdir -p /opt/n8n/{data/postgres,data/redis,data/n8n,data/caddy,backups}
sudo chown -R $USER:$USER /opt/n8n/data/{postgres,redis,data/caddy,backups}
# El directorio data/n8n debe pertenecer al UID 1000 (usuario 'node' dentro del contenedor)
sudo chown -R 1000:1000 /opt/n8n/data/n8n
cd /opt/n8n
5. Configurar variables de entorno
Crea un archivo .env para almacenar la configuración sensible:
Tips antes de empezar:
- Asegúrate de que tu dominio apunte al servidor. Antes de continuar, ve a tu proveedor de DNS y agrega un registro A con la IP de tu servidor. Caddy necesita resolver el dominio para obtener el certificado SSL.
- Genera una contraseña segura para PostgreSQL y una encryption key para n8n con estos comandos:
openssl rand -base64 24 # Para POSTGRES_PASSWORD
openssl rand -hex 20 # Para N8N_ENCRYPTION_KEY
Guarda los valores para el .env.
nano /opt/n8n/.env
Contenido:
# Dominio
N8N_DOMAIN=n8n.tudominio.com
# PostgreSQL
POSTGRES_USER=n8n
POSTGRES_PASSWORD=password_seguro_postgres
POSTGRES_DB=n8n
# n8n
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=password_seguro_postgres
N8N_ENCRYPTION_KEY=encryption_key_seguro
N8N_HOST=${N8N_DOMAIN}
N8N_PROTOCOL=https
WEBHOOK_URL=https://${N8N_DOMAIN}/
N8N_PORT=5678
# Queue mode (Redis)
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
Protege el archivo:
chmod 600 /opt/n8n/.env
6. Crear el archivo docker-compose.yml
nano /opt/n8n/docker-compose.yml
services:
postgres:
image: postgres:16-alpine
container_name: n8n-postgres
restart: unless-stopped
env_file: .env
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- ./data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
networks:
- n8n-network
redis:
image: redis:7-alpine
container_name: n8n-redis
restart: unless-stopped
volumes:
- ./data/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- n8n-network
n8n:
image: n8nio/n8n:latest
container_name: n8n-app
restart: unless-stopped
env_file: .env
environment:
- DB_TYPE=${DB_TYPE}
- DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST}
- DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT}
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_HOST=${N8N_HOST}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- WEBHOOK_URL=${WEBHOOK_URL}
- N8N_PORT=${N8N_PORT}
- N8N_METRICS=true
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168
- EXECUTIONS_MODE=${EXECUTIONS_MODE}
- QUEUE_BULL_REDIS_HOST=${QUEUE_BULL_REDIS_HOST}
- QUEUE_BULL_REDIS_PORT=${QUEUE_BULL_REDIS_PORT}
volumes:
- ./data/n8n:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- n8n-network
n8n-worker:
image: n8nio/n8n:latest
container_name: n8n-worker
restart: unless-stopped
env_file: .env
environment:
- EXECUTIONS_MODE=${EXECUTIONS_MODE}
- QUEUE_BULL_REDIS_HOST=${QUEUE_BULL_REDIS_HOST}
- QUEUE_BULL_REDIS_PORT=${QUEUE_BULL_REDIS_PORT}
- DB_TYPE=${DB_TYPE}
- DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST}
- DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT}
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
command: worker
depends_on:
- postgres
- redis
networks:
- n8n-network
caddy:
image: caddy:2-alpine
container_name: n8n-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data/caddy:/data
- ./data/caddy:/config
depends_on:
- n8n
networks:
- n8n-network
networks:
n8n-network:
driver: bridge
¿Por qué usar queue mode desde el inicio?
n8n puede ejecutar workflows de dos formas:
- Modo directo (default): el contenedor principal ejecuta todo. Si un workflow tarda mucho, bloquea las ejecuciones siguientes.
- Modo queue: los trabajos se encolan en Redis y los procesan workers independientes. Puedes tener varios workers, escalarlos horizontalmente y las ejecuciones pesadas no afectan al contenedor principal.
Con el docker-compose.yml de arriba, ya tienes el modo queue activo desde el primer docker compose up.
7. Crear el Caddyfile
nano /opt/n8n/Caddyfile
n8n.tudominio.com {
reverse_proxy n8n:5678
}
Caddy obtendrá automáticamente un certificado SSL de Let's Encrypt y lo renovará sin intervención manual.
8. Configurar el firewall (UFW)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status verbose
9. Iniciar el stack
cd /opt/n8n
docker compose up -d
Verifica que todos los servicios estén funcionando:
docker compose ps
Deberías ver algo como:
Revisa los logs del worker para confirmar que está recibiendo trabajos:
docker compose logs -f n8n-worker
10. Acceder a n8n y configuración inicial
Abre tu navegador en https://n8n.tudominio.com. Verás la pantalla de registro. Crea tu cuenta de administrador:
- Email: tu correo
- Nombre: tu nombre
- Contraseña: una contraseña segura
Ya puedes empezar a crear flujos de trabajo. Todos los workflows se ejecutarán a través del worker.
11. Escalar workers
Si tus workflows crecen, escalar es tan simple como agregar más réplicas del servicio n8n-worker:
docker compose up -d --scale n8n-worker=3
Cada worker adicional toma trabajos de la misma cola en Redis. No necesitas cambiar nada más.
13. Buenas prácticas en producción
-
Usa etiqueta fija: En lugar de
n8nio/n8n:latest, usa una versión específica comon8nio/n8n:1.80.3para evitar sorpresas con actualizaciones. -
Monitoreo: n8n expone métricas Prometheus en
/metrics. Puedes integrarlas con un stack de monitoreo. -
Backups periódicos: Programa un cron para respaldar los directorios
data/postgres,data/redis,data/n8nydata/caddy. Al estar en bind mounts, puedes copiarlos directamente conrsyncotar. - Seguridad: No expongas el puerto 5678 directamente. Caddy ya se encarga del proxy. Si necesitas acceso local, usa una VPN o túneles SSH.
-
Limpieza de ejecuciones: Las variables
EXECUTIONS_DATA_PRUNE=trueyEXECUTIONS_DATA_MAX_AGE=168eliminan automáticamente ejecuciones antiguas después de 7 días.
Conclusión
Tienes n8n corriendo en producción sobre Ubuntu con PostgreSQL como base de datos persistente, Redis como gestor de colas, workers dedicados, SSL automático con Caddy y una estructura lista para escalar. Y todo ejecutándose bajo un usuario del sistema dedicado, no como root.
Este setup con modo queue es el mismo que usamos en entornos reales para automatizar procesos de clientes que requieren alta disponibilidad y rendimiento predecible, desde notificaciones y CRMs hasta integraciones complejas con APIs externas.
Si trabajas con redes o documentación visual de infraestructura, puedes usar Savnet para diseñar los diagramas de tus flujos desplegados. Y si necesitas validar o testear automatizaciones de forma continua, SavFalconEye te ayuda a mantener la confianza en cada despliegue.
¿Te quedó alguna duda? Déjala en los comentarios.





Top comments (0)