Why self-host n8n on a VPS
n8n workflows often handle sensitive secrets: API tokens, database credentials, business webhook payloads. In the cloud version billed per execution, this data passes through infrastructure you do not control, and the bill climbs with volume. On a dedicated VPS, the engine, the internal database and the credentials stay with you, with no execution limit, and you choose when each update happens.
The concrete benefits of a self-hosted n8n
- Unlimited executions: no monthly cap or extra cost per triggered workflow.
- Confidentiality of credentials and webhook payloads, which stay on your server.
- Full access to community nodes and to running custom code.
- Controlled persistence of workflows and history in volumes that you back up.
- Webhooks on your own domain, handy for inbound integrations.
- Predictable cost: a single VPS price, independent of the number of automations.
Hardware and software requirements
n8n is reasonably lightweight. Plan for 1 to 2 vCPU and 2 GB of RAM to start, and 2 to 4 GB if you run heavy or concurrent workflows, or if you connect a dedicated PostgreSQL database instead of SQLite. Allow 5 to 10 GB of disk. On the software side: Docker and Docker Compose, a subdomain (e.g. n8n.your-domain.com) pointing to the VPS IP, and port 443 open for HTTPS and inbound webhooks.
Deploy n8n with Docker and HTTPS
Prepare the VPS and Docker
Over SSH, update the system then install Docker via curl -fsSL https://get.docker.com | sh. Create a dedicated folder: mkdir -p /opt/n8n && cd /opt/n8n.
Write the docker-compose.yml
Use the n8nio/n8n image, a ~/.n8n volume for persistence, and set N8N_HOST, WEBHOOK_URL=https://n8n.your-domain.com/ as well as N8N_BASIC_AUTH_ACTIVE=true with a strong username and password.
Connect a PostgreSQL database (optional)
For production use, add a postgres service to the compose file and point n8n at it via the DB_TYPE=postgresdb and DB_POSTGRESDB_* variables, more robust than SQLite under load.
Launch the container
Run docker compose up -d then docker compose logs -f. n8n listens locally on 127.0.0.1:5678, not exposed directly, which is deliberate.
Configure the reverse proxy
With Caddy, a single line is enough: n8n.your-domain.com { reverse_proxy localhost:5678 }. Caddy obtains and renews the Let's Encrypt certificate automatically.
Check the webhooks
Create a test workflow with a Webhook node, trigger it from outside and confirm that the URL https://n8n.your-domain.com/webhook/... responds correctly through the proxy.
For AI automations with no external API cost, have n8n talk to an Ollama container on the same VPS through the internal Docker network. You combine orchestration and generation locally, and no data leaves your server.
The official documentation
For advanced configuration and tool-specific options, refer to the official n8n documentation. This guide covers going live on a VPS; the vendor documentation remains the reference for fine-tuning, major updates and specific use cases.