Skip to content

DevOps

Self-Hosting n8n on a Budget VPS: A Production-Ready Setup Guide

August 19, 202614 min readRasel Hossain
Self-Hosting n8n on a Budget VPS: A Production-Ready Setup Guide

Quick answer

Learn how to self-host n8n workflow automation on a $5 VPS using Docker, Cloudflare Tunnels, and PM2 for a production-ready setup that costs less than a coffee per week while handling thousands of automated executions monthly.

Self-Hosting n8n on a Budget VPS: A Production-Ready Setup Guide

When I first started exploring workflow automation tools back in 2021, I quickly realized that paying $20-50/month for hosted automation platforms adds up fast—especially when you're running side projects, client pipelines, and personal experiments simultaneously. That's when I discovered n8n, the fair-code workflow automation powerhouse, and decided to take the self-hosting route.

Over the past three years, I've deployed n8n on everything from a Raspberry Pi to enterprise-grade Kubernetes clusters. But the sweet spot I've found—and what I recommend to most clients—is a $5 VPS running Docker with Cloudflare Tunnels for secure access and PM2 for process management. It's the kind of setup that costs less than a coffee per week but handles production workloads reliably.

selfhosting n8n budget - Image 2

In this guide, I'll walk you through the exact n8n VPS setup I use for my own automation infrastructure, including the gotchas that aren't obvious from the official documentation.

Why Self-Host n8n Instead of Using n8n Cloud?

selfhosting n8n budget - Image 3

Before we dive into the technical setup, let's talk about why n8n self-hosted makes sense for developers and small teams:

  • Cost efficiency: $5-10/month vs $20-50/month for hosted plans with similar execution limits
  • Data sovereignty: Your workflows, credentials, and execution data never leave your server
  • Unlimited executions: Most cloud plans cap you at 1,000-10,000 executions per month
  • Custom integrations: Full access to the filesystem means you can run custom nodes and scripts
  • Learning value: You'll understand Docker, reverse proxies, and process management better

The trade-off is operational responsibility—but as a DevOps engineer, that's part of the fun.

Prerequisites: What You'll Need

Before we start the n8n production deployment, gather these essentials:

  1. A VPS provider — I recommend Hetzner, DigitalOcean, or Vultr for their $4-6/month tiers with good performance
  2. A domain name — Even a cheap $1 domain from Namecheap works fine
  3. Cloudflare account — Free tier is sufficient for tunnel access
  4. Basic Linux knowledge — Comfort with SSH and command-line editing
  5. About 45 minutes — That's realistically how long this takes the first time

For this guide, I'll assume you're using Ubuntu 22.04 LTS as your server OS. The steps are nearly identical for Debian.

Step 1: Initial VPS Hardening and Docker Installation

Once you SSH into your fresh VPS, the first thing I always do is harden the basics. Skip this step at your own risk—I've seen too many self-hosted instances compromised because of lazy initial setup.

# Update the system
sudo apt update && sudo apt upgrade -y

# Create a non-root user for running n8n
sudo adduser n8nadmin
sudo usermod -aG sudo n8nadmin

# Configure basic firewall
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable

# Install Docker and Docker Compose
sudo apt install -y ca-certificates curl gnupg
sudo mkdir -m 0755 -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-buildx-plugin docker-compose-plugin

# Add your user to docker group (logout/login required)
sudo usermod -aG docker n8nadmin

Pro tip: Set up SSH key authentication and disable password authentication in /etc/ssh/sshd_config before you close your first terminal session. Lose access to a VPS once due to a brute-force attack, and you'll never skip this step again.

Step 2: Creating the n8n Docker Compose Configuration

Now for the heart of our Docker n8n setup. I'll create a dedicated directory structure that makes backups and updates painless.

mkdir -p ~/n8n-setup/{n8n-data,postgres-data,backups}
cd ~/n8n-setup

Create a docker-compose.yml file with proper production settings:

version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    restart: always
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n:latest
    restart: always
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN}/
      - GENERIC_TIMEZONE=UTC
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
    volumes:
      - ./n8n-data:/home/node/.n8n

Then create a .env file with sensitive values:

DB_PASSWORD=your_super_secure_postgres_password
SUBDOMAIN=automation
DOMAIN=yourdomain.com

The reason I'm binding n8n to 127.0.0.1:5678 instead of exposing it directly is security. We'll front it with Cloudflare Tunnel, so there's no need for the world to see port 5678.

Step 3: Why I Use Postgres Instead of SQLite

You might wonder why I'm bothering with Postgres for a budget setup. Here's the honest answer: for production n8n, SQLite becomes a bottleneck once you hit a few hundred executions per day. Concurrent write operations can cause "database is locked" errors that silently kill your workflows.

The Postgres container adds maybe 50MB of RAM to your footprint—and on a $5 VPS with 1GB RAM, that's negligible. It also gives you proper transactional integrity for webhook processing, which matters when you're handling client billing automations or e-commerce integrations.

Step 4: Setting Up Cloudflare Tunnel (Skip the Reverse Proxy Headache)

Traditional n8n VPS setup guides insist you set up Nginx or Caddy as a reverse proxy with Let's Encrypt certificates. I've done this dozens of times, and frankly, it's overkill for most use cases.

Cloudflare Tunnels give you:

  • Automatic HTTPS with valid certificates
  • No need to open ports 80/443 publicly
  • Built-in DDoS protection
  • Free tier covers most use cases

Install cloudflared on your VPS:

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg > /dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared focal main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install -y cloudflared

Authenticate and create your tunnel:

cloudflared tunnel login
cloudflared tunnel create n8n-tunnel
cloudflared tunnel route dns n8n-tunnel automation.yourdomain.com

Create the tunnel config at ~/.cloudflared/config.yml:

tunnel: n8n-tunnel
credentials-file: /home/n8nadmin/.cloudflared/<TUNNEL_ID>.json

ingress:
  - hostname: automation.yourdomain.com
    service: http://127.0.0.1:5678
  - service: http_status:404

Install as a system service:

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared

Your n8n instance is now accessible via HTTPS at your chosen subdomain—without exposing any ports on your VPS.

Step 5: PM2 for Robust Process Management

Wait—you might be asking—if we're using Docker, why do we need PM2? This is a great question, and it's about n8n production resilience beyond just the container.

PM2 handles the orchestration layer around Docker. If Docker ever crashes or needs to restart after a reboot, PM2 ensures everything comes back online in the right order. It also provides:

  • Centralized logs (pm2 logs)
  • Memory monitoring
  • Zero-downtime restarts during updates
  • Startup script management

Install PM2 globally:

sudo npm install -g pm2

Create an ecosystem file:

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'n8n-docker',
    script: 'docker-compose',
    args: 'up -d',
    cwd: '/home/n8nadmin/n8n-setup',
    autorestart: true,
    watch: false,
    max_memory_restart: '900M',
    env: {
      NODE_ENV: 'production'
    }
  }]
}

Set up startup scripts and save the process list:

pm2 startup
pm2 start ecosystem.config.js
pm2 save

Step 6: Automated Backups (The Part People Forget)

I've had clients lose hundreds of workflows because they didn't back up their n8n-data directory. Don't be that person.

Create a backup script at ~/n8n-setup/backup.sh:

#!/bin/bash
BACKUP_DIR=/home/n8nadmin/n8n-setup/backups
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Backup n8n data
tar -czf $BACKUP_DIR/n8n-data-$TIMESTAMP.tar.gz /home/n8nadmin/n8n-setup/n8n-data

# Database dump
docker exec $(docker ps -q -f name=postgres) pg_dump -U n8n n8n | gzip > $BACKUP_DIR/n8n-db-$TIMESTAMP.sql.gz

# Keep only last 7 days of backups
find $BACKUP_DIR -type f -mtime +7 -delete

Schedule it with cron:

chmod +x ~/n8n-setup/backup.sh
crontab -e
# Add: 0 3 * * * /home/n8nadmin/n8n-setup/backup.sh

Step 7: Performance Tuning for Budget VPS Constraints

Running workflow automation on limited resources requires discipline. Here are the optimizations that matter:

Enable Execution Pruning

Already in our compose file, but worth emphasizing. Set EXECUTIONS_DATA_MAX_AGE=168 (7 days). If you need longer history, export important runs to a database instead.

Configure Swap Space

On a 1GB VPS, swap prevents OOM kills during heavy workflows:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Use the Queue Mode for Scaling

For higher throughput, switch n8n to queue mode after validating your setup. This requires Redis and a separate worker container—a great topic for a future post.

Monitoring and Maintenance Tips

Once your n8n VPS setup is running, ongoing maintenance is minimal but non-negotiable:

  • Weekly: Check docker ps and pm2 status
  • Monthly: Update n8n with docker-compose pull && docker-compose up -d
  • Quarterly: Review cleanup of old credentials and unused workflows
  • Always: Monitor disk space with df -h—execution logs fill up faster than you'd expect

For better observability, consider adding Uptime Kuma (another fantastic self-hosted tool) to alert you when your n8n instance goes down.

Cost Breakdown: The Real Numbers

Let me show you what this setup actually costs monthly:

| Component | Cost | |-----------|------| | Hetzner CX22 VPS (2GB) | $4.50 | | Domain name (annual, prorated) | $0.10 | | Cloudflare (free tier) | $0 | | Backups storage (same VPS) | $0 | | Total | ~$4.60/month |

Compare this to n8n Cloud's Starter plan at $20/month with 10,000 executions, and you're getting nearly unlimited runtime for less than the cost of a sandwich.

Common Pitfalls I've Learned to Avoid

After deploying this configuration dozens of times, here are the mistakes I see repeatedly:

1. Skipping Postgres — Yes, SQLite is "simpler," but you'll regret it during traffic spikes.

2. Using latest Docker tag in production — Pin your version (e.g., n8nio/n8n:1.50.0) for reproducible deployments.

3. Forgetting about webhook URLs — Update WEBHOOK_URL to match your actual domain, or external integrations will fail silently.

4. Not setting timezone correctlyGENERIC_TIMEZONE affects cron triggers. UTC is safest unless you have a specific need.

5. Exposing 5678 publicly — Always front it with Cloudflare Tunnel or Nginx with proper auth.

Final Thoughts on Production-Ready n8n

This setup has served me well across personal projects, client work, and even a few small SaaS products. It's not the absolute cheapest possible deployment—that would involve SQLite and direct port exposure—but it offers the reliability and security you'd expect from production infrastructure, at a fraction of typical costs.

The beauty of n8n is that once you have it running, the possibilities explode. Connect it to your CRM, automate social media, build AI-powered workflows with the OpenAI node, or orchestrate complex multi-step business processes. All without paying per execution or worrying about your data leaving your infrastructure.

If you want help with advanced configurations—queue mode with Redis, custom nodes, Kubernetes deployments, or high-availability setups—I'm available for consulting through my Fiverr profile. Otherwise, happy automating!

Frequently Asked Questions

How much RAM does n8n actually need for production workloads?

For most small-to-medium businesses running n8n production deployments, 2GB of RAM is the sweet spot. My $5 VPS setup with 2GB handles roughly 50,000 executions per month comfortably. If you're processing webhook bursts or running heavy data transformations, you'll want to monitor memory usage and consider scaling vertically before hitting limits.

Can I run n8n without Docker on a VPS?

Absolutely—n8n supports direct Node.js installation with npm install n8n -g. However, Docker n8n deployments are easier to update, isolate dependencies, and replicate across environments. The overhead is minimal (maybe 30MB extra RAM), and you get much cleaner upgrade paths.

Is self-hosting n8n actually more secure than the cloud version?

It depends on your operational maturity. Cloud-hosted n8n handles security patching and infrastructure hardening for you. Self-hosting means you're responsible for OS updates, Docker security, SSH hardening, and credential management. With proper setup (which this guide provides), self-hosting can be equally or more secure—but it requires discipline.

What's the difference between n8n's queue mode and regular mode?

Regular mode runs everything in one container—good for hundreds of executions per day. Queue mode uses Redis to distribute work across multiple worker containers, enabling horizontal scaling. For a single $5 VPS, regular mode is fine. When you outgrow it, queue mode lets you add workers without redesigning your architecture.

Do I really need Cloudflare Tunnel, or can I use Nginx directly?

You don't need Cloudflare Tunnel—Nginx with Let's Encrypt works fine. The Cloudflare approach just hides your server's IP address from the public internet, adding an extra layer of protection. If you're comfortable managing Nginx and certificate renewal, that's a perfectly valid alternative. I've used both approaches successfully across different deployments.

#Automation#n8n#DevOps#Docker#Self-Hosting

How to do it

  1. 1

    Initial VPS Setup and Docker Installation

    SSH into your VPS, update the system, create a non-root user, configure UFW firewall, and install Docker with Docker Compose. Add your user to the docker group for passwordless container management.

  2. 2

    Create Docker Compose Configuration for n8n

    Create a project directory structure with separate volumes for n8n data and Postgres data. Write a docker-compose.yml file that includes both the n8n container and a Postgres 15-alpine database, with proper health checks and restart policies.

  3. 3

    Configure Cloudflare Tunnel for Secure Access

    Install cloudflared on your VPS, authenticate with your Cloudflare account, create a tunnel, and configure routing to expose n8n at your chosen subdomain. Install cloudflared as a system service for automatic startup.

  4. 4

    Set Up PM2 for Process Management

    Install PM2 globally via npm, create an ecosystem.config.js file that manages your Docker Compose stack, and configure PM2 startup scripts to ensure n8n automatically restarts after server reboots.

  5. 5

    Configure Automated Backups and Monitoring

    Create a backup script that archives n8n data and dumps the Postgres database, schedule it with cron for daily execution, and configure cleanup of old backups. Set up disk space monitoring and consider adding Uptime Kuma for downtime alerts.

Frequently asked questions

How much RAM does n8n need for production workloads?

For most small-to-medium businesses running n8n production deployments, 2GB of RAM is the sweet spot. A $5 VPS setup with 2GB handles roughly 50,000 executions per month comfortably. If you're processing webhook bursts or running heavy data transformations, monitor memory usage closely and consider scaling vertically before hitting limits.

Can I run n8n without Docker on a VPS?

Absolutely—n8n supports direct Node.js installation with npm install n8n -g. However, Docker n8n deployments are easier to update, isolate dependencies, and replicate across environments. The overhead is minimal (around 30MB extra RAM), and you get much cleaner upgrade paths and rollback capabilities.

Is self-hosting n8n more secure than n8n Cloud?

It depends on your operational maturity. Cloud-hosted n8n handles security patching and infrastructure hardening for you. Self-hosting means you're responsible for OS updates, Docker security, SSH hardening, and credential management. With proper setup following security best practices, self-hosting can be equally or more secure—but it requires ongoing discipline.

What's the difference between n8n queue mode and regular mode?

Regular mode runs everything in one container—good for hundreds of executions per day. Queue mode uses Redis to distribute work across multiple worker containers, enabling horizontal scaling. For a single VPS, regular mode is sufficient. When you outgrow it, queue mode lets you add workers without redesigning your architecture.

Do I need Cloudflare Tunnel or can I use Nginx directly?

You don't need Cloudflare Tunnel—Nginx with Let's Encrypt certificates works perfectly fine. The Cloudflare approach hides your server's IP address from the public internet, adding an extra protection layer. If you're comfortable managing Nginx and certificate renewal, that's a valid alternative. Both approaches work well for production n8n deployments.

More articles

Related reading from the same areas — practical notes on shipping software.

View all articles

Liked the article?

Have a similar problem in your business? Let's talk about building the fix.

Start a project