Automatizar tareas con n8n es relativamente simple en local. El problema aparece cuando querés exponer flujos reales a Internet: webhooks, integraciones con APIs, formularios, CRMs, sistemas internos o herramientas de marketing.

Ahí ya no alcanza con ejecutar un contenedor y abrir un puerto. Necesitás una URL pública estable, HTTPS, una base de datos persistente, backups y una configuración que no deje expuestos servicios internos.

En esta guía vas a desplegar n8n self-hosted en un Cloud Server con Docker Compose, PostgreSQL, NGINX como reverse proxy y certificado TLS. El objetivo es tener una base sólida para ambientes productivos pequeños, pruebas serias o proyectos internos que necesitan automatización controlada.

¿Qué es n8n?

n8n es una herramienta de automatización de workflows. Permite conectar servicios, APIs, bases de datos y procesos internos mediante flujos visuales.

Podés usarlo para tareas como:

  • recibir un webhook y guardar datos en una base;
  • sincronizar contactos entre herramientas;
  • enviar alertas a Slack, email o Telegram;
  • procesar formularios;
  • ejecutar integraciones con APIs propias;
  • automatizar tareas de soporte, ventas o infraestructura.

La ventaja del modo self-hosted es que controlás dónde corre la instancia, cómo se almacenan las credenciales y qué reglas de red aplicás.

¿Cuándo conviene usar n8n self-hosted?

Conviene usar n8n en tu propio servidor cuando necesitás más control que el que ofrece un servicio gestionado o cuando tus flujos trabajan con datos internos.

Algunos casos claros:

  • automatizaciones internas de una empresa;
  • integraciones con sistemas propios;
  • webhooks que necesitan una URL estable;
  • pruebas de automatización antes de escalar;
  • flujos que requieren secretos, tokens o credenciales sensibles;
  • proyectos donde querés controlar backups, red y políticas de acceso.

No conviene exponer n8n sin HTTPS, sin autenticación o con puertos internos publicados directamente a Internet. n8n puede manejar credenciales sensibles, por lo que la seguridad inicial importa.

Requisitos previos

Para seguir esta guía necesitás:

  • un Cloud Server con Ubuntu 22.04 LTS o 24.04 LTS;
  • acceso SSH con un usuario con permisos sudo;
  • un dominio o subdominio, por ejemplo automatiza.ejemplo.com;
  • un registro DNS tipo A apuntando a la IP pública del servidor;
  • puertos 80 y 443 abiertos para tráfico web;
  • puerto 22 abierto solo para administración SSH;
  • Docker Engine y Docker Compose;
  • NGINX;
  • Certbot para emitir el certificado TLS.

En esta guía se usará:

  • 80: HTTP, necesario para validación inicial y redirección;
  • 443: HTTPS, tráfico público real hacia n8n;
  • 5678: puerto interno de n8n, no debe publicarse a Internet;
  • 5432: puerto interno de PostgreSQL, no debe publicarse a Internet.

Paso 1: Preparar el servidor

Actualizá los paquetes base:

sudo apt updatesudo apt upgrade -y

Instalá herramientas necesarias:

sudo apt install -y ca-certificates curl gnupg ufw nginx

Configurá reglas básicas de firewall. Si administrás el servidor desde una IP fija, lo ideal es limitar SSH a esa IP:

sudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw allow from TU_IP_PUBLICA to any port 22 proto tcpsudo ufw enablesudo ufw status

Si todavía no conocés tu IP fija o estás configurando el servidor por primera vez, podés permitir SSH temporalmente:

sudo ufw allow OpenSSH

Advertencia: antes de activar ufw, verificá que la regla de SSH esté bien configurada. Si cerrás el puerto equivocado, podés perder acceso al servidor.

[Imagen sugerida: preparación inicial del servidor con actualización, NGINX, UFW y SSH]

Paso 2: Instalar Docker Engine

Docker recomienda instalar Docker Engine desde su repositorio oficial en Ubuntu. Primero agregá la clave y el repositorio:

sudo install -m 0755 -d /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg \  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpgsudo chmod a+r /etc/apt/keyrings/docker.gpgecho \  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \  https://download.docker.com/linux/ubuntu \  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" \  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Luego instalá Docker y el plugin de Compose:

sudo apt updatesudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verificá que Docker funcione:

docker --versiondocker compose version

Opcionalmente, agregá tu usuario al grupo docker para evitar usar sudo en cada comando:

sudo usermod -aG docker $USER

Después cerrá sesión y volvé a entrar por SSH.

Paso 3: Crear la estructura del proyecto

Creá un directorio para n8n:

sudo mkdir -p /opt/n8nsudo chown -R $USER:$USER /opt/n8ncd /opt/n8n

Generá una clave fuerte para cifrar credenciales dentro de n8n:

openssl rand -base64 32

Guardá ese valor. Lo vas a usar como N8N_ENCRYPTION_KEY.

Esta clave es importante: si la perdés, podés tener problemas para recuperar credenciales guardadas en n8n después de migraciones o restauraciones.

Paso 4: Crear el archivo .env

Creá un archivo .env:

nano .env

Pegá una configuración como esta, ajustando dominio, contraseñas y zona horaria:

POSTGRES_DB=n8nPOSTGRES_USER=n8nPOSTGRES_PASSWORD=CAMBIAR_POR_UNA_PASSWORD_LARGAN8N_HOST=automatiza.ejemplo.comN8N_PROTOCOL=httpsWEBHOOK_URL=https://automatiza.ejemplo.com/N8N_PROXY_HOPS=1N8N_ENCRYPTION_KEY=PEGAR_CLAVE_GENERADA_CON_OPENSSLGENERIC_TIMEZONE=America/Argentina/Buenos_AiresTZ=America/Argentina/Buenos_AiresN8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true

No uses contraseñas débiles ni valores de ejemplo en producción. El archivo .env contiene secretos y no debería subirse a un repositorio público.

Paso 5: Crear docker-compose.yml

En /opt/n8n, creá el archivo:

nano docker-compose.yml

Pegá esta configuración:

services:  postgres:    image: postgres:16-alpine    restart: unless-stopped    environment:      POSTGRES_DB: ${POSTGRES_DB}      POSTGRES_USER: ${POSTGRES_USER}      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}    volumes:      - postgres_data:/var/lib/postgresql/data    networks:      - n8n_internal  n8n:    image: n8nio/n8n:latest    restart: unless-stopped    depends_on:      - postgres    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_HOST: ${N8N_HOST}      N8N_PROTOCOL: ${N8N_PROTOCOL}      WEBHOOK_URL: ${WEBHOOK_URL}      N8N_PROXY_HOPS: ${N8N_PROXY_HOPS}      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}      TZ: ${TZ}      N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: ${N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS}    volumes:      - n8n_data:/home/node/.n8n    ports:      - "127.0.0.1:5678:5678"    networks:      - n8n_internalvolumes:  postgres_data:  n8n_data:networks:  n8n_internal:    driver: bridge

La línea importante es esta:

ports:  - "127.0.0.1:5678:5678"

Eso hace que n8n escuche solo en localhost. Internet no llega directo al puerto 5678; el acceso público se hace por NGINX en 443.

En producción, conviene fijar una versión concreta de n8n en lugar de usar latest, por ejemplo cuando ya validaste una versión estable para tu flujo de trabajo. latest simplifica la guía, pero puede traer cambios inesperados en actualizaciones.

Paso 6: Iniciar n8n

Desde /opt/n8n, ejecutá:

docker compose up -d

Verificá el estado:

docker compose psdocker compose logs -f n8n

Probá localmente:

curl http://127.0.0.1:5678

Si responde HTML o una redirección, n8n está levantado.

Paso 7: Configurar NGINX como reverse proxy

Creá un archivo de sitio para NGINX:

sudo nano /etc/nginx/sites-available/n8n

Pegá esta configuración, cambiando el dominio:

server {    listen 80;    server_name automatiza.ejemplo.com;    location / {        proxy_pass http://127.0.0.1:5678;        proxy_http_version 1.1;        proxy_set_header Connection "";        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-Host $host;        proxy_set_header X-Forwarded-Proto $scheme;    }}

Activá el sitio:

sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/n8nsudo nginx -tsudo systemctl reload nginx

Ahora deberías poder abrir:

http://automatiza.ejemplo.com

Todavía falta HTTPS. No uses credenciales reales ni conectes servicios externos hasta completar el certificado TLS.




Paso 8: Activar HTTPS con Certbot

Instalá Certbot. En Ubuntu, una opción habitual es usar Snap:

sudo apt install -y snapdsudo snap install --classic certbotsudo ln -s /snap/bin/certbot /usr/bin/certbot

Emití el certificado para NGINX:

sudo certbot --nginx -d automatiza.ejemplo.com

Certbot puede ajustar la configuración para usar HTTPS y redirigir HTTP a HTTPS.

Verificá renovación automática:

sudo certbot renew --dry-run

A partir de este punto, la URL pública debería ser:

https://automatiza.ejemplo.com

Paso 9: Configurar correctamente los webhooks

Cuando n8n está detrás de NGINX, hay una diferencia entre el puerto interno y la URL pública.

Internamente n8n escucha en:

http://127.0.0.1:5678

Pero los servicios externos tienen que llamar a:

https://automatiza.ejemplo.com/webhook/...

Por eso son importantes estas variables:

N8N_HOST=automatiza.ejemplo.comN8N_PROTOCOL=httpsWEBHOOK_URL=https://automatiza.ejemplo.com/N8N_PROXY_HOPS=1

Si WEBHOOK_URL queda mal configurada, n8n puede mostrar URLs con localhost, http o puertos internos. Eso rompe integraciones externas aunque el editor visual cargue bien.

Después de cambiar variables, reiniciá los contenedores:

cd /opt/n8ndocker compose up -d

Paso 10: Probar que funciona

Desde el navegador, entrá a:

https://automatiza.ejemplo.com

Creá el usuario inicial de n8n y luego armá un flujo simple con un nodo Webhook.

Probá la URL pública con curl:

curl -i https://automatiza.ejemplo.com/webhook/test

La ruta exacta dependerá del webhook que hayas creado. Lo importante es que la URL empiece con https://automatiza.ejemplo.com y no con localhost.

También podés revisar logs:

docker compose logs -f n8nsudo tail -f /var/log/nginx/access.logsudo tail -f /var/log/nginx/error.log

Paso 11: Reforzar seguridad

Antes de usar n8n con datos reales, revisá estos puntos:

  • mantené públicos solo 80 y 443;
  • no publiques 5678 ni 5432;
  • usá una N8N_ENCRYPTION_KEY fuerte y persistente;
  • configurá backups de los volúmenes postgres_data y n8n_data;
  • usá contraseñas largas y únicas;
  • mantené Docker, NGINX y el sistema operativo actualizados;
  • revisá permisos del archivo .env;
  • evitá guardar tokens innecesarios en flujos de prueba;
  • ejecutá auditorías de seguridad de n8n cuando corresponda;
  • probá restaurar backups, no solo generarlos.

n8n incluye una función de auditoría de seguridad que puede ayudar a detectar riesgos comunes. Según la documentación oficial, se puede ejecutar con:

docker compose exec n8n n8n audit

Backups mínimos recomendados

Para una instalación simple, al menos necesitás respaldar:

  • la base PostgreSQL;
  • el volumen de datos de n8n;
  • el archivo .env;
  • el archivo docker-compose.yml;
  • la configuración de NGINX.

Un backup básico de PostgreSQL podría verse así:

cd /opt/n8ndocker compose exec postgres pg_dump \  -U "$POSTGRES_USER" \  "$POSTGRES_DB" > backup-n8n.sql

En algunos shells, las variables del .env no están cargadas automáticamente. Si el comando no toma los valores, podés ejecutar:

source .env

y luego repetir el backup.

Advertencia: guardá los backups fuera del servidor o en una ubicación separada. Un backup que vive únicamente en el mismo disco no te protege ante pérdida del servidor, borrado accidental o corrupción del volumen.

Problemas frecuentes

n8n muestra webhooks con localhost

Revisá estas variables:

N8N_HOST=automatiza.ejemplo.comN8N_PROTOCOL=httpsWEBHOOK_URL=https://automatiza.ejemplo.com/N8N_PROXY_HOPS=1

Después reiniciá:

docker compose up -d

El navegador muestra error 502 Bad Gateway

NGINX no puede llegar a n8n. Verificá que el contenedor esté activo:

docker compose psdocker compose logs n8n

También comprobá que n8n responda localmente:

curl http://127.0.0.1:5678

Certbot no puede emitir el certificado

Revisá que:

  • el DNS apunte a la IP correcta;
  • el puerto 80 esté abierto;
  • NGINX esté activo;
  • no haya otro servicio usando el puerto 80.

Podés probar NGINX con:

sudo nginx -tsudo systemctl status nginx

PostgreSQL no inicia

Revisá logs:

docker compose logs postgres

Verificá que no hayas cambiado POSTGRES_USER, POSTGRES_DB o POSTGRES_PASSWORD después de inicializar el volumen. En PostgreSQL, esos valores se usan al crear la base por primera vez; cambiarlos luego no modifica automáticamente la base ya creada.

El servidor queda sin acceso por SSH

Si activaste ufw sin permitir correctamente SSH, podés perder acceso remoto. Antes de activar el firewall, confirmá la regla:

sudo ufw status

Si usás el panel del proveedor cloud y tenés consola de emergencia, podrías corregirlo desde ahí. Aun así, es mejor prevenirlo.

Conclusión

n8n puede ser una pieza muy útil para automatizar procesos, pero cuando lo exponés a Internet conviene tratarlo como cualquier aplicación de producción: dominio, HTTPS, base persistente, reverse proxy, firewall, backups y revisión de seguridad.

Con Docker Compose, PostgreSQL y NGINX podés tener una instalación clara, mantenible y fácil de mover. Si necesitás un servidor para este tipo de despliegues, un Cloud Server de DonWeb te permite elegir Ubuntu, configurar tu stack y escalar recursos cuando tus automatizaciones crezcan.

Cloud Serversby Donweb

Todo el poder de la nube a tus proyectos y aplicaciones.
Alojamiento ultra rápido, escalable y con alta disponibilidad.

  • Performance que te sorprenderá
  • Rápida escalabilidad y sin limitaciones
  • Arquitectura de alta disponibilidad
  • Soporte experto y ejecutivos de cuenta
  • Pagos en tu moneda y facturación local

Descubre la mejor solución de Cloud Hosting