How to Install n8n as a Service: Local Docker, VPS with Nginx, and Coolify (Beginner Developer Guide)
A deep, step-by-step guide to running n8n as a reliable service locally with Docker, on a VPS with Docker + manual Nginx reverse proxy, and deploying via Coolify—plus requirements, examples, and official documentation links.
n8n is easiest to try in minutes, but it’s also the kind of tool you quickly want to run as a service: stable restarts, persistent data, a real domain, HTTPS, and predictable upgrades. This guide walks you through three common setups that cover most developer needs:
- Local: run n8n with Docker (best for development and learning).
- VPS: run n8n with Docker behind manual Nginx + HTTPS (best for production-ish self-hosting).
- Coolify: deploy n8n using a PaaS-style workflow (best when you want simpler ops and repeatable deployments).
Where possible, I’ll link to official documentation so you can verify details and keep up with changes.
Before you start: what “as a service” means for n8n
Running n8n “as a service” typically implies:
- It restarts automatically if it crashes or your server reboots.
- Data persists across container rebuilds (volumes for the database and config).
- It’s reachable at a stable URL (domain, or at least a stable port).
- If exposed to the internet, it uses HTTPS, and you configure n8n’s
N8N_HOST/N8N_PROTOCOL/WEBHOOK_URLso webhook callbacks work correctly. - You have a plan for upgrades, backups, and security.
Official docs you’ll likely reference throughout:
- n8n Docs (main): https://docs.n8n.io/
- n8n Docker docs: https://docs.n8n.io/hosting/installation/docker/
- n8n environment variables: https://docs.n8n.io/hosting/configuration/environment-variables/
- n8n security / user management (varies by version): https://docs.n8n.io/
- Docker docs: https://docs.docker.com/
- Docker Compose docs: https://docs.docker.com/compose/
- Nginx docs: https://nginx.org/en/docs/
- Certbot (Let’s Encrypt) docs: https://certbot.eff.org/
- Coolify docs: https://coolify.io/docs
Note: n8n docs evolve. If a setting looks different in your installed version, always trust the official n8n environment variable reference first.
Requirements (don’t skip this)
Local (Docker)
- Docker Engine installed (Docker Desktop on macOS/Windows, Docker Engine on Linux)
- Docker Compose support
- Newer Docker includes
docker composeas a plugin: https://docs.docker.com/compose/
- Newer Docker includes
VPS (Docker + Nginx)
- A VPS with a supported Linux distro (commonly Ubuntu/Debian)
- SSH access + a sudo-capable user
- A domain name you control, with DNS A/AAAA records pointing to your VPS
- Open ports:
80/tcp(for HTTP and Let’s Encrypt challenges)443/tcp(for HTTPS)
- Docker Engine installed on the VPS:
- Optional but recommended: UFW firewall configured to allow 22/80/443
Coolify
- A server where Coolify is installed (or a hosted Coolify instance)
- Ability to deploy Docker-based apps from a repository or template
- Domain and DNS records, if you want HTTPS and webhooks from the public internet
- Coolify documentation for installation and reverse proxy/SSL handling:
Architecture overview (so the steps make sense)
There are two popular patterns:
- n8n + SQLite (simple, fine for local/dev; can work for small setups)
- n8n + Postgres (recommended for serious self-hosting, better concurrency and durability)
On a VPS, you’ll usually run:
n8ncontainerpostgrescontainer (recommended)nginxon the host (or in a container) as a reverse proxy- TLS via Let’s Encrypt (Certbot) or via your platform (Coolify can manage this)
1) Install n8n locally with Docker (beginner-friendly)
If you’re learning n8n or building workflows locally, this is the fastest and safest setup. You can choose between a quick single-container run or a more “service-like” docker compose with persistent storage.
Option A: Quick run (good for first launch)
Official Docker guidance: https://docs.n8n.io/hosting/installation/docker/
A typical quick run looks like:
docker run -it --rm \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
-p 5678:5678exposes n8n at http://localhost:5678-v n8n_data:/home/node/.n8npersists n8n config and data in a Docker volume--rmremoves the container when it exits (your data remains in the volume)
This is great to verify Docker works and n8n boots, but for “run it like a service,” Compose is cleaner.
Option B: Local docker compose (recommended)
Create a folder, for example:
mkdir n8n-local && cd n8n-local
Create a compose.yml:
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
ports:
- "5678:5678"
volumes:
- n8n_data:/home/node/.n8n
environment:
- N8N_HOST=localhost
- N8N_PORT=5678
- N8N_PROTOCOL=http
# If you use webhooks from outside localhost, you'll need a public URL.
# For local testing with external callbacks, consider ngrok or a reverse tunnel.
restart: unless-stopped
volumes:
n8n_data:
Start it:
docker compose up -d
docker compose logs -f
Open:
Stop:
docker compose down
Local webhooks (important beginner gotcha)
If you use nodes that require incoming webhooks (Stripe, GitHub, etc.), localhost usually won’t work from the internet. Typical solutions:
- Use an HTTPS tunnel like ngrok or Cloudflare Tunnel
- Or deploy on a VPS / Coolify (next sections)
n8n has settings like WEBHOOK_URL (see env vars doc) to force webhook URLs to match your public endpoint:
2) Install n8n on a VPS with Docker + manual Nginx (production-style)
This is the “classic” self-hosting setup: Docker for app + database, Nginx as reverse proxy, Let’s Encrypt for TLS.
Step 1: Prepare your VPS
1.1 DNS
Create a DNS record:
Arecord:n8n.example.com→ your VPS IPv4- (Optional)
AAAArecord for IPv6
Wait for propagation.
1.2 Install Docker on the VPS
Use the official Docker Engine install docs for your distro:
Verify:
docker --version
docker compose version
1.3 Open firewall ports
If using UFW (Ubuntu):
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Step 2: Create a Docker Compose stack (n8n + Postgres)
n8n’s Docker documentation includes examples and notes about persistence:
Create a directory:
sudo mkdir -p /opt/n8n && cd /opt/n8n
Create compose.yml (example with Postgres):
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=CHANGE_ME_STRONG
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
depends_on:
- postgres
environment:
# Database config (n8n supports Postgres; see n8n docs)
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=CHANGE_ME_STRONG
# Basic URL settings (match your public URL)
- N8N_HOST=n8n.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
# This is commonly required so n8n generates correct external webhook URLs
- WEBHOOK_URL=https://n8n.example.com/
# Optional: set timezone
- TZ=UTC
# Behind a reverse proxy, tell n8n to trust proxy headers when needed.
# See n8n docs for the correct variable name and usage in your version.
# - N8N_PROXY_HOPS=1
ports:
# Bind only to localhost so it's not publicly exposed without Nginx
- "127.0.0.1:5678:5678"
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
postgres_data:
Why bind
127.0.0.1:5678:5678? So n8n is only reachable locally, and the only public entry is via Nginx on 80/443.
Start:
sudo docker compose up -d
sudo docker compose logs -f
At this point, n8n should be listening on 127.0.0.1:5678.
Test from the VPS:
curl -I http://127.0.0.1:5678
Step 3: Install and configure Nginx as reverse proxy
Install Nginx (Ubuntu/Debian):
sudo apt update
sudo apt install -y nginx
Create an Nginx site config:
sudo nano /etc/nginx/sites-available/n8n.conf
Example configuration (HTTP first; TLS comes next):
server {
listen 80;
server_name n8n.example.com;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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-Proto $scheme;
}
}
Enable it:
sudo ln -s /etc/nginx/sites-available/n8n.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Now visit:
If this works, move to HTTPS.
Step 4: Add HTTPS with Let’s Encrypt (Certbot)
Follow Certbot’s official instructions for Nginx:
On Ubuntu with snap (commonly recommended by Certbot):
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Request a certificate and auto-configure Nginx:
sudo certbot --nginx -d n8n.example.com
Certbot should:
- Obtain a certificate
- Modify the Nginx server block to redirect HTTP → HTTPS
- Add TLS configuration
Test renewal:
sudo certbot renew --dry-run
Step 5: Verify n8n URL settings (webhooks must match)
If you see webhook URLs that still point to http://127.0.0.1:5678 or http://localhost, your environment variables are wrong (or you didn’t restart after changing them).
Key variables to review in the official doc:
N8N_HOST,N8N_PROTOCOL, andWEBHOOK_URLare commonly used in reverse-proxy setups- Environment variables reference: https://docs.n8n.io/hosting/configuration/environment-variables/
After editing compose.yml, restart:
cd /opt/n8n
sudo docker compose up -d
Step 6: Run it reliably (service behaviors)
You already set:
restart: unless-stopped
That’s the Docker-native “service” behavior most people want. If the VPS reboots, Docker will start the containers again.
Upgrading n8n safely
A typical pattern:
cd /opt/n8n
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune -f
If you want extra safety, take backups first.
Backups (beginner-simple approach)
At minimum, back up:
- Postgres volume (or the database dump)
- n8n config volume
A straightforward DB dump example:
sudo docker compose exec postgres pg_dump -U n8n n8n > n8n_backup.sql
(Exact command may vary depending on container user/permissions; the concept is: dump Postgres and store it off-server.)
3) Install n8n with Coolify (simpler ops, still Docker)
Coolify can be a big step up for beginners because it provides:
- A UI to deploy and update apps
- Built-in reverse proxy and SSL handling (depending on your configuration)
- Environment variable management
- Git-based deployments
Official Coolify docs:
Because Coolify evolves quickly, the exact clicks can differ by version, but the successful mental model stays the same: deploy the n8n container, attach persistent storage, set environment variables, and ensure you have a public URL with HTTPS.
Step 1: Install / access Coolify
Follow Coolify’s installation guide for your server:
Once installed, confirm:
- The Coolify reverse proxy is running (Coolify often uses a proxy like Traefik under the hood, depending on version/config).
- You can create a new “Application” (Docker-based).
Step 2: Create a new n8n application
You generally have two routes:
Route A: Deploy from a Docker image
Use the official n8n Docker image:
docker.n8n.io/n8nio/n8n:latest(or a pinned version tag)
In Coolify, create an app that runs that image and exposes port 5678.
Route B: Deploy from a Git repository containing a compose file
If Coolify supports “Docker Compose” apps in your version, you can store a compose.yml similar to the VPS one in a repo and let Coolify manage it.
This is useful when you want n8n + Postgres as a single stack.
Step 3: Configure persistent storage
n8n needs persistence. In Docker terms, n8n stores data in:
/home/node/.n8n
So in Coolify, add a persistent volume / storage mapping for that path.
If you deploy Postgres too, persist:
/var/lib/postgresql/data
Step 4: Configure environment variables (must match your domain)
In Coolify’s UI, set the same core environment variables you would in Compose. Refer to n8n’s official env var docs:
Common baseline for a public instance:
N8N_HOST=n8n.example.comN8N_PROTOCOL=httpsN8N_PORT=5678WEBHOOK_URL=https://n8n.example.com/
If you’re using Postgres, add the DB variables according to n8n documentation for Postgres configuration (via env vars).
Step 5: Attach a domain and enable HTTPS
In Coolify:
- Add the domain
n8n.example.comto the application - Enable HTTPS/SSL (Coolify can often request and renew Let’s Encrypt certificates automatically)
After that, confirm:
- You can access
https://n8n.example.com - Webhooks show as
https://n8n.example.com/webhook/...
Step 6: Updates and rollbacks
One of Coolify’s strengths is simplifying updates:
- You can redeploy with a click
- If using Git-based deploys, updates can be tied to pushes/tags
- If using an image tag, you can change the tag and redeploy
For n8n, it’s often better to pin versions rather than always running latest, especially in production. The official Docker docs cover image usage and tags:
Common troubleshooting (across all installs)
“My webhook test works locally but not from the internet”
Most often:
- You are not using a public URL (local only)
- Your
WEBHOOK_URLis missing or incorrect - Your reverse proxy is not forwarding headers correctly
- HTTPS is missing or mixed (HTTP outside, HTTPS inside, etc.)
Start by checking what URL n8n believes it’s running on in the UI (and compare to your env vars).
“I can load the UI, but OAuth callbacks fail”
OAuth providers require exact redirect URLs. Ensure:
- Your public URL is stable and HTTPS
- The provider redirect URI matches n8n’s callback URL exactly
N8N_HOST,N8N_PROTOCOL, andWEBHOOK_URLare correct
“502 Bad Gateway from Nginx”
Usually:
- n8n container isn’t running
- n8n is bound to the wrong interface/port
- Nginx is proxying to the wrong upstream (
127.0.0.1:5678must match your Docker port binding) - Check logs:
sudo docker compose logs -f n8nsudo tail -f /var/log/nginx/error.log
“Data disappeared after recreating the container”
That means persistence wasn’t configured correctly:
- Ensure your volume mapping includes
/home/node/.n8n - On VPS, ensure named volumes exist and are referenced in the Compose file
- On Coolify, ensure storage is configured and attached to the correct path
Which method should you choose?
If you’re a beginner developer, a practical progression is:
- Local Docker Compose for learning and building workflows quickly.
- VPS + Docker + Nginx when you need real webhooks, HTTPS, and full control (and you want to learn how production reverse proxies work).
- Coolify when you want “deploy like a platform,” reduce manual Nginx/SSL work, and manage apps in a UI—without giving up Docker.
Official docs reference list (bookmark these)
- n8n Docker installation: https://docs.n8n.io/hosting/installation/docker/
- n8n environment variables: https://docs.n8n.io/hosting/configuration/environment-variables/
- Docker Engine install: https://docs.docker.com/engine/install/
- Docker Compose overview: https://docs.docker.com/compose/
- Nginx documentation: https://nginx.org/en/docs/
- Certbot (Let’s Encrypt): https://certbot.eff.org/
- Coolify documentation: https://coolify.io/docs