Montar n8n en un VPS con Docker es una forma muy sólida de tener tu propia plataforma de automatización con control total sobre datos, copias de seguridad y actualizaciones. La documentación oficial de n8n plantea Docker Compose en Linux como una de las rutas estándar para self-hosting, apoyándose en un subdominio propio, un archivo .env, volúmenes persistentes y un proxy inverso para TLS. Docker, además, recomienda instalar Engine y el plugin de Compose desde su repositorio oficial en Ubuntu.
Qué necesitas antes de empezar
Necesitas un VPS con Ubuntu, acceso por SSH, un dominio o subdominio apuntando a la IP pública del servidor y los puertos 80 y 443 accesibles. n8n indica que, para publicar la instancia online, conviene crear un subdominio dedicado, y su ejemplo oficial usa Traefik para exponer HTTPS y gestionar certificados automáticamente.
1. Instalar Docker y Docker Compose
En Ubuntu, una instalación limpia y actualizable pasa por el repositorio oficial de Docker:
sudo apt updatesudo apt install -y ca-certificates curlsudo install -m 0755 -d /etc/apt/keyringssudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.ascsudo chmod a+r /etc/apt/keyrings/docker.ascsudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOFTypes: debURIs: https://download.docker.com/linux/ubuntuSuites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")Components: stableArchitectures: $(dpkg --print-architecture)Signed-By: /etc/apt/keyrings/docker.ascEOFsudo apt updatesudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Después conviene verificar:
docker --versiondocker compose version
Y, si no quieres usar sudo en cada comando:
sudo usermod -aG docker $USERnewgrp docker
Docker documenta ese flujo de instalación para Ubuntu y también advierte que el grupo docker da privilegios de nivel root, así que conviene usarlo con criterio.
2. Preparar DNS y firewall
La forma más limpia es usar algo como n8n.tudominio.com apuntando a la IP del VPS. Si usas ufw, abre SSH, HTTP y HTTPS:
sudo ufw allow OpenSSHsudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw enable
n8n especifica que el subdominio debe resolver hacia el servidor antes de levantar la instancia pública, porque el proxy usará ese hostname para el enrutado y el certificado TLS.
3. Crear la carpeta del proyecto
mkdir -p ~/n8n-composecd ~/n8n-composemkdir -p local-files
n8n recomienda una carpeta de proyecto con el .env, el compose.yaml y un directorio local para compartir archivos con la instancia.
4. Crear el archivo .env
Crea ~/n8n-compose/.env con este contenido:
DOMAIN_NAME=tudominio.comSUBDOMAIN=n8nGENERIC_TIMEZONE=Europe/MadridSSL_EMAIL=tu-correo@tudominio.comN8N_ENCRYPTION_KEY=pon_aqui_una_clave_larga_y_unica
La guía oficial de n8n usa DOMAIN_NAME, SUBDOMAIN, GENERIC_TIMEZONE y SSL_EMAIL en su ejemplo de Docker Compose. Además, n8n documenta N8N_ENCRYPTION_KEY como la clave usada para cifrar credenciales; si no la defines, la genera en el primer arranque. Para una instalación seria, es mejor fijarla tú y guardarla a salvo.
Puedes generar una clave segura así:
openssl rand -hex 32
5. Crear compose.yaml
Dentro de ~/n8n-compose, crea este archivo:
services: traefik: image: traefik:v3.0 restart: always command: - "--api.insecure=false" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true" - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}" - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" volumes: - traefik_data:/letsencrypt - /var/run/docker.sock:/var/run/docker.sock:ro n8n: image: docker.n8n.io/n8nio/n8n restart: always ports: - "127.0.0.1:5678:5678" labels: - traefik.enable=true - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`) - traefik.http.routers.n8n.entrypoints=web,websecure - traefik.http.routers.n8n.tls=true - traefik.http.routers.n8n.tls.certresolver=mytlschallenge environment: - NODE_ENV=production - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME} - N8N_PORT=5678 - N8N_PROTOCOL=https - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/ - N8N_PROXY_HOPS=1 - GENERIC_TIMEZONE=${GENERIC_TIMEZONE} - TZ=${GENERIC_TIMEZONE} - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} volumes: - n8n_data:/home/node/.n8n - ./local-files:/filesvolumes: n8n_data: traefik_data:
Este enfoque sigue la estructura oficial de n8n: un contenedor para Traefik, otro para n8n, el puerto 5678 publicado solo en 127.0.0.1, y dos volúmenes persistentes, uno para los datos de n8n y otro para los certificados de Traefik. Además, n8n recomienda fijar WEBHOOK_URL y, si está detrás de un proxy inverso, establecer N8N_PROXY_HOPS=1 para que los webhooks y cabeceras funcionen correctamente.
6. Levantar la instancia
docker compose up -ddocker compose psdocker compose logs -f
Si el DNS ya resuelve bien y los puertos están abiertos, deberías poder entrar en:
https://n8n.tudominio.com
En el primer acceso, n8n te pedirá crear la cuenta propietaria de la instancia.
7. Ajustes recomendables después
Para actualizar:
docker compose pulldocker compose up -d
n8n recomienda mantener la instancia actualizada y revisar notas de versión con frecuencia. También conviene guardar copia del .env, del compose.yaml y del volumen n8n_data, porque ahí quedan la configuración, la base de datos SQLite y material sensible de la instancia.
8. SQLite ahora, PostgreSQL después
En self-hosting, n8n usa SQLite por defecto, y también soporta PostgreSQL. Para una sola instancia pequeña, SQLite es perfectamente válido. Si vas a escalar, usar queue mode o añadir workers, n8n recomienda PostgreSQL y desaconseja ese escenario con SQLite.
Problemas frecuentes
Si no se genera el certificado, casi siempre es por DNS incorrecto, puertos 80/443 bloqueados o porque otro servicio ya está ocupando esos puertos. Si los webhooks salen con URLs erróneas, normalmente faltan WEBHOOK_URL o N8N_PROXY_HOPS=1. Si se pierden credenciales o configuración, suele haber un problema de persistencia en /home/node/.n8n o un cambio de clave de cifrado. Todo eso encaja con cómo n8n documenta el almacenamiento local, el uso del proxy y la gestión de la clave de cifrado.
Conclusión
La forma más limpia de instalar n8n en un VPS con Docker es montar una instancia con Docker Compose, Traefik, HTTPS automático, volúmenes persistentes y una clave de cifrado propia. Para empezar, la combinación de instancia única + SQLite es suficiente; cuando el proyecto crezca, el siguiente paso natural es pasar a PostgreSQL.
Toni Domenech
