“Deploying and Securing N8N on a Dedicated VPS: A Step‑by‑Step Guide”
Learn how to deploy n8n on a dedicated VPS using Docker Compose, PostgreSQL, and Nginx for a secure, scalable, and self-hosted workflow automation solution. This guide covers essential server hardening, configuration, and maintenance strategies to ensure robust performance and data security.
In today’s fast‑paced digital landscape, automating repetitive tasks isn’t a luxury—it’s a competitive necessity. n8n (pronounced “n‑eight‑n”) is an open‑source workflow automation platform that offers the flexibility of Zapier or Make while giving you full control over your data and infrastructure. Deploying n8n on a dedicated Virtual Private Server (VPS) lets you scale, customise, and secure your automations without sharing resources with strangers.
1. Preparing Your VPS Environment
1.1 Choose the Right Provider and Specs
- CPU & RAM: 2 vCPU + 4 GB RAM is sufficient for modest workloads; upgrade to 4 vCPU + 8 GB RAM for heavier integrations.
- Storage: SSD ≥ 30 GB ensures fast reads/writes for logs and temporary files.
- OS: Ubuntu 22.04 LTS is the most widely supported distribution for Docker and n8n.
- Network: Open ports 22 (SSH), 443 (HTTPS), and optionally 5678 (local n8n UI) in the firewall.
1.2 Secure the Server from Day One
- Create a non‑root user:
adduser n8nadminand add it to thesudogroup. - Set up SSH keys:
ssh-keygen -t ed25519on your workstation, then copy the public key to~/.ssh/authorized_keyson the VPS. - Disable password authentication: edit
/etc/ssh/sshd_config, setPasswordAuthentication no, then runsystemctl restart sshd. - Configure a basic firewall:
sudo ufw allow OpenSSH,sudo ufw allow 443/tcp,sudo ufw enable.
1.3 Install Core Dependencies
n8n runs most reliably inside Docker, so install Docker Engine and Docker Compose:
sudo apt update && sudo apt install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker n8nadmin
newgrp docker
2. Deploying n8n with Docker Compose
2.1 Create a Dedicated Directory
Keep all related files under /opt/n8n (or any path you prefer):
sudo mkdir -p /opt/n8n
sudo chown $USER:$USER /opt/n8n
cd /opt/n8n
2.2 Define the docker-compose.yml File
The following production‑ready compose file includes a PostgreSQL database (recommended over SQLite for reliability) and an Nginx reverse‑proxy for TLS termination:
version: "3.8"
services:
postgres:
image: postgres:15-alpine
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: YOUR_STRONG_PASSWORD
POSTGRES_DB: n8n
volumes:
- postgres_data:/var/lib/postgresql/data
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=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=${N8N_ADMIN_PASSWORD}
- N8N_HOST=your.domain.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- VUE_APP_URL_BASE_API=/api
- NODE_OPTIONS=--max-old-space-size=1024
ports:
- "5678:5678"
volumes:
- n8n_data:/home/node/.n8n
nginx:
image: nginx:alpine
restart: unless-stopped
depends_on:
- n8n
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/ssl/certs:ro
environment:
- N8N_HOST=your.domain.com
volumes:
postgres_data:
n8n_data:
2.3 Configure Nginx for HTTPS
Create nginx/conf.d and add n8n.conf:
server {
listen 80;
server_name your.domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name your.domain.com;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/certs/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
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_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Obtain a TLS certificate with Certbot (or any Let’s Encrypt method) and place fullchain.pem and privkey.pem in the certs folder.
2.4 Launch the Stack
docker compose up -d
Docker will pull the images, create the volumes, and start PostgreSQL, n8n, and Nginx. Verify everything is running:
docker compose ps
3. Securing Your n8n Installation
3.1 Enforce Strong Authentication
- Basic auth is already enabled in the compose file—choose a complex password for
N8N_BASIC_AUTH_PASSWORD. - For larger teams, integrate OAuth2 or SSO (Google, Microsoft, generic OpenID Connect) to centralise credential management.
3.2 Harden the Network Layer
- Limit inbound traffic: Only ports 80 and 443 should be publicly open. Block port 5678 at the firewall (
sudo ufw deny 5678) so the UI is reachable only through Nginx. - Enable Fail2Ban:
sudo apt install fail2banand configure a jail for SSH to mitigate brute‑force attacks. - Consider a VPN: For internal teams, restrict VPS access via WireGuard or OpenVPN and keep the public endpoint locked down.
3.3 Keep the Stack Updated
Regularly pull newer Docker images and restart the containers:
docker compose pull
docker compose up -d --remove-orphans
Automate this with a weekly cron job or a CI/CD pipeline.
3.4 Backup Strategy
- Database backup: Dump PostgreSQL nightly:
pg_dump -U n8n -h localhost n8n > /backups/n8n_$(date +%F).sql - Workflow export: Use n8n’s “Export All Workflows” feature; schedule a cron‑triggered script that stores the JSON files in a remote object store (e.g., S3).
- Docker volume snapshot:
docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine tar czf /backup/n8n_data_$(date +%F).tar.gz -C /data .
4. Optimising Performance & Monitoring
4.1 Resource Tuning
If you encounter memory pressure, adjust the Node.js heap size with the NODE_OPTIONS flag (as shown in the compose file).
4.2 Logging and Alerting
- Redirect container logs to
journaldor a centralised system such as Loki/Promtail. - Expose Prometheus metrics via the
n8n-prometheus-exporterand visualise them in Grafana. - Set alerts for CPU > 80 %, memory > 75 %, or database connection errors.
4.3 Scaling Out
When workloads grow, consider moving PostgreSQL to a managed service (e.g., Amazon RDS) and running multiple n8n replicas behind a load balancer. Because workflow state lives in PostgreSQL, horizontal scaling is straightforward.
Conclusion
Deploying n8n on a dedicated VPS gives you the best of both worlds: the flexibility of open‑source automation and the control required for enterprise‑grade security. By following the step‑by‑step guide above—hardening the server, using Docker Compose with PostgreSQL and Nginx, tightening authentication, and implementing backups and monitoring—you’ll have a robust, scalable automation hub ready to handle anything from simple email notifications to complex, multi‑system orchestrations.
Remember, security is an ongoing process. Regularly audit your workflows, rotate secrets, and keep the underlying software up to date. With a solid foundation in place, you can focus on what truly matters: building smarter processes that drive efficiency and innovation across your organisation.
More in Technology
Boost WooCommerce Performance: Step‑by‑Step Guide to Setting Up Read‑Replicas on Separate DB VPS Nodes
High-traffic WooCommerce stores often face severe database bottlenecks during traffic spikes and flash sales. Offloading read-heavy queries to dedicated database read replicas on separate VPS nodes dramatically improves performance, reduces latency, and enhances site reliability. This comprehensive guide walks you through the step-by-step architecture, setup, and best practices for integrating database replicas into your WordPress stack.
Mastering Point-In-Time Recovery in PostgreSQL: A Step‑by‑Step Guide with WAL Archives and pgBackRest
Recovering a PostgreSQL database to an exact moment—Point‑In‑Time Recovery (PITR)—is vital for preventing data loss from accidental deletions, rogue updates, or hardware failures. By combining continuous WAL archiving with the powerful pgBackRest tool, you can create a reliable, automated backup strategy that enables fast, production‑ready restores to any chosen timestamp.
Step-by-Step Guide: Installing Node‑RED and MQTT on Unmanaged Ubuntu for Seamless IoT Data Ingestion
Learn how to build a reliable, self-hosted IoT data pipeline by combining Node-RED and a Mosquitto MQTT broker on an unmanaged Ubuntu server. This step-by-step guide covers everything from initial server hardening and credential security to constructing visual flows for parsing sensor data. Gain complete control over your telemetry, reduce network latency, and eliminate cloud licensing overhead with a fully custom on-premises deployment.
