How to Self-Host n8n on a VPS (2026 Guide)

Self-Host n8n on a VPS

If you’re running more than a handful of automations, you’ve probably felt it: the “API tax.” Every execution on a cloud automation platform has a price tag, and in 2026 – with AI agents chaining together dozens of steps per run, calling LLMs, querying vector databases, and looping until a task is done – that tax adds up fast. n8n Cloud pricing scales with usage, which is fine for light workloads, but painful once you’re running autonomous agents around the clock.

Self-hosting n8n on your own VPS removes that ceiling entirely. You get unlimited workflow executions, full control over your data (important if you’re in healthcare, finance, or anywhere with compliance requirements), and the ability to connect n8n directly to self-hosted AI models, private databases, and internal tools that would never touch a public cloud.

This guide walks through the entire process of self-hosting n8n on a VPS in 2026: server setup, Docker and Docker Compose, PostgreSQL, a Nginx reverse proxy, free SSL, security hardening, backups, and how to get your first AI agent workflow running. By the end, you’ll have a production-ready n8n instance that costs a fraction of n8n Cloud and that you fully own.

What Is n8n?

n8n is an open-source workflow automation platform built around a visual, node-based editor. It connects apps, APIs, databases, and – increasingly in 2026 – AI models and autonomous agents, letting you build multi-step automations without writing glue code for every integration. Unlike Zapier or Make, n8n is source-available, meaning you can run the Community edition on your own infrastructure for free, with no cap on how many workflows you run.

The project has grown well past its original “Zapier alternative” reputation. n8n’s core codebase now ships with a native AI Agent node that supports structured tool calling, multiple memory backends, and a ReAct-style reasoning mode – meaning you can build agents that search the web, query your own data, and take multi-step actions, all from a visual canvas instead of hand-written orchestration code.

Why Self-Host n8n Instead of Using n8n Cloud?

n8n Cloud is a fine starting point, but self-hosting makes sense the moment your automations become part of how your business actually runs. Here’s why:

  • No per-execution costs. Self-hosted n8n Community edition has unlimited workflow executions. As your AI agents run more steps and loops, this is the difference between a predictable hosting bill and a runaway invoice.
  • Full data sovereignty. Your workflow data, credentials, and execution history never leave your own server – a requirement for teams in regulated industries.
  • Deep customization. Self-hosted instances can install community nodes, connect to internal-only databases and APIs, and run alongside other self-hosted tools on the same VPS.
  • Connect to self-hosted AI. You can point n8n’s AI Agent node at a local model running through Ollama instead of paying per-token for a hosted LLM, keeping sensitive prompts entirely on your own infrastructure.
  • Predictable pricing. A VPS costs the same whether you run 500 or 500,000 executions a month.

The trade-off is that you’re responsible for the server: updates, backups, and security. That’s exactly what the rest of this guide covers.

What You’ll Need Before You Start

  • A VPS running Ubuntu 22.04 or 24.04, with at least 2 vCPUs and 4GB of RAM. n8n itself is lightweight, but AI agent workflows that call local models or process large payloads benefit from extra headroom – VeerHost’s n8n Hosting plans are pre-sized for exactly this.
  • SSH access to your server and basic comfort with the command line.
  • A domain or subdomain you can point at the server (for example, n8n.yourdomain.com), which you’ll need for webhooks and SSL.
  • Roughly 30-45 minutes for the initial setup.

Step 1: Set Up and Connect to Your VPS

If you’re starting from a brand-new server, walk through our Getting Started with Your VeerHost VPS guide first – it covers your first SSH login, changing the root password, and updating system packages, all of which this guide assumes are already done.

Connect over SSH:

ssh root@YOUR_VPS_IP

Then make sure your packages are current:

apt update && apt upgrade -y

Step 2: Point Your Domain to the VPS

n8n relies on a real domain for webhooks (the URLs external services call to trigger your workflows) and for SSL. Create an A record for a subdomain such as n8n.yourdomain.com pointing at your server’s IP address. Our guide on pointing a domain to your VeerHost VPS walks through this step by step, including how to verify propagation before moving on.

Step 3: Secure the Server Before Installing Anything

It’s tempting to install n8n first and lock things down later. Don’t. A freshly provisioned VPS is scanned by bots within minutes of going live, and n8n workflows often hold API keys and credentials that you really don’t want exposed. Before continuing, follow our full VPS security guide to create a non-root sudo user, switch to SSH key authentication, disable root login, and enable a firewall (UFW). At minimum, your firewall should only allow SSH, HTTP (80), and HTTPS (443).

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Notice that port 5678 (n8n’s default port) is deliberately not on that list. n8n will only be reachable through the Nginx reverse proxy we set up in Step 7 – never expose it directly to the internet.

Step 4: Install Docker and Docker Compose

n8n’s own documentation recommends Docker for self-hosting, since it isolates n8n’s dependencies from the rest of your system and makes updates a one-line command. Install Docker using the official convenience script, or follow Docker’s Ubuntu installation instructions for a more controlled setup:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
apt install -y docker-compose-plugin

Verify both are installed:

docker --version
docker compose version

Step 5: Create Your Project Directory and Environment File

Create a dedicated folder to keep everything organized:

mkdir -p ~/n8n
cd ~/n8n

Create a .env file to hold your secrets and configuration, rather than hard-coding them into the Compose file:

nano .env

Paste in and adjust the following:

# Domain and protocol
N8N_HOST=n8n.yourdomain.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com/
GENERIC_TIMEZONE=Etc/UTC

# n8n basic auth (extra login layer in front of the editor)
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=CHANGE_THIS_STRONG_PASSWORD

# Encryption key - generate once, never change after data exists
N8N_ENCRYPTION_KEY=CHANGE_THIS_TO_A_LONG_RANDOM_STRING

# PostgreSQL credentials
POSTGRES_USER=n8n
POSTGRES_PASSWORD=CHANGE_THIS_STRONG_DB_PASSWORD
POSTGRES_DB=n8n

Save the file, then lock down its permissions so only your user can read it:

chmod 600 .env

Generate a genuinely random encryption key rather than typing one yourself:

openssl rand -hex 32

Step 6: Write the Docker Compose File (n8n + PostgreSQL)

By default, n8n stores its data in SQLite, which works for testing but isn’t built for concurrent production workloads. For a real deployment, run PostgreSQL alongside n8n – this is also the configuration used in n8n’s official Docker Compose reference configurations. Create the Compose file:

nano docker-compose.yml

Paste in the following:

services:
  postgres:
    image: postgres:16
    container_name: n8n_postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: "${POSTGRES_USER}"
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
      POSTGRES_DB: "${POSTGRES_DB}"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n
    container_name: n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=${N8N_HOST}
      - N8N_PROTOCOL=${N8N_PROTOCOL}
      - WEBHOOK_URL=${WEBHOOK_URL}
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - N8N_BASIC_AUTH_ACTIVE=${N8N_BASIC_AUTH_ACTIVE}
      - N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
      - DB_POSTGRESDB_USER=${POSTGRES_USER}
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  n8n_data:

Notice that n8n is bound to 127.0.0.1:5678, not 0.0.0.0. This means the container is only reachable from the server itself – the only way in from the outside will be through Nginx, which we set up next.

Step 7: Configure Nginx as a Reverse Proxy

Install Nginx if it isn’t already on the server:

apt install -y nginx

Create a site configuration:

nano /etc/nginx/sites-available/n8n

Paste this, replacing the domain with your own. n8n uses WebSockets for live workflow execution updates, so the Upgrade and Connection headers matter here:

server {
    listen 80;
    server_name n8n.yourdomain.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;
        proxy_read_timeout 300s;
    }
}

Enable the site and reload Nginx:

ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

If you’d like a broader walkthrough of hosting any application behind Nginx on a VPS, including PHP and virtual host basics, see our guide on hosting a website on your VPS. For the full official reference, see the Nginx documentation.

Step 8: Add Free SSL With Let’s Encrypt

With DNS pointing at your server and Nginx proxying correctly over plain HTTP, install Certbot and request a free certificate:

apt install -y certbot python3-certbot-nginx
certbot --nginx -d n8n.yourdomain.com

Certbot will edit your Nginx config to serve over HTTPS and set up automatic renewal. You can find the full range of options in the official Certbot documentation. Test that renewal works before you forget about it:

certbot renew --dry-run

Step 9: Launch n8n

With everything in place, start the stack:

docker compose up -d

Check that both containers are healthy:

docker compose ps
docker compose logs -f n8n

Visit https://n8n.yourdomain.com in your browser. You should be prompted for the basic auth credentials you set in your .env file, followed by n8n’s own setup wizard, where you’ll create your first owner account inside the app itself.

Step 10: Build Your First AI Agent Workflow

Once you’re in, the fastest way to see what self-hosted n8n is capable of is to build a simple AI agent. From the canvas, add an AI Agent node and connect it to a model provider. You have two broad options:

  • A hosted model API (OpenAI, Anthropic, Google, or similar) for the strongest reasoning quality, paid per token.
  • A local model through Ollama, running on the same VPS or a separate one, for zero per-token cost and full data privacy. See Ollama’s official site for supported models and setup instructions.

Give the agent a clear system prompt, attach a tool or two (a web search node, an HTTP request node, or access to your own database), and trigger it with a webhook or a simple manual test. If you’re also experimenting with other self-hosted AI agent platforms on the same server, our guides on setting up OpenClaw on a VPS and the underlying GPT-5.4 model family are useful companion reading, since many of the same hosting and security considerations apply.

Hardening Your n8n Installation

n8n workflows frequently hold API keys, database credentials, and access tokens for other services. Treat the server accordingly:

  1. Never bind n8n to 0.0.0.0. Keep it on 127.0.0.1 behind Nginx, as configured above.
  2. Keep basic auth enabled as a second login layer in front of the editor, in addition to n8n’s own user accounts.
  3. Install Fail2ban to automatically block IPs that repeatedly fail SSH or basic auth logins. See the Fail2ban project for configuration details.
  4. Restrict webhook-only workflows where possible, and validate incoming payloads inside the workflow itself rather than trusting them blindly.
  5. Rotate the encryption key and credentials if you ever suspect a leak, and never commit your .env file to a public repository.
  6. Keep the OS patched. Run apt update && apt upgrade -y on a schedule, not just when you remember to.

For a much deeper hardening checklist that applies to any AI agent or automation platform running on a VPS – closing unused ports, securing SSH, protecting databases, and monitoring logs – see our full VPS and AI agent security guide. It’s written around a different tool, but almost every recommendation in it applies directly to an n8n deployment too. For general web application security principles, the OWASP Top 10 is worth bookmarking, and Ubuntu’s own UFW firewall guide is a good reference if you want to go beyond the basic rules above.

Backing Up Your n8n Instance

Your workflows, credentials, and execution history live in the PostgreSQL volume and the n8n data volume – if you lose the server without a backup, you lose all of it. A simple database dump, taken regularly and copied off the server, covers most of what matters:

docker exec -t n8n_postgres pg_dump -U n8n -d n8n > n8n_backup_$(date +%Y-%m-%d).sql

For a complete strategy – including full-server snapshots, automated nightly backups via cron, and how to restore from either – see our guide on backing up your VPS. As a rule of thumb, snapshot the whole server before any major change (a version upgrade, a new integration, a config rewrite), and run the lighter database dump on a daily cron job in between.

Updating n8n Safely

n8n ships new releases frequently. Before updating, take a snapshot or database backup, then pull the latest image and recreate the container:

docker compose pull
docker compose up -d

Check the release notes in the n8n GitHub repository for breaking changes before updating a production instance, particularly around major version bumps.

n8n Self-Hosted vs n8n Cloud: Which Should You Choose?

 Self-Hosted (VPS)n8n Cloud
Execution limitsUnlimitedCapped by plan, extra usage billed
Monthly costFrom $4.99/monthScales with usage
Data locationYour own servern8n’s cloud infrastructure
Setup effortYou manage Docker, SSL, backupsNone – fully managed
Custom/community nodesFully supportedLimited
Connect to local AI modelsYes, directlyNo
Best forHeavy usage, AI agents, compliance needsGetting started quickly, low maintenance

If you’re just testing n8n out, Cloud is the path of least resistance. The moment you’re running production workflows or AI agents with any real execution volume, self-hosting on a purpose-sized VPS pays for itself within the first month or two.

Common Errors and How to Fix Them

502 Bad Gateway

This almost always means Nginx can’t reach the n8n container. Confirm the container is running with docker compose ps, and double-check that the proxy_pass address and port in your Nginx config match the port n8n is actually bound to.

Webhooks Not Firing

Check that WEBHOOK_URL in your .env file exactly matches your public domain, including the trailing slash and https://. A mismatch here is the most common cause of webhooks that work in the editor’s test mode but fail once activated.

Database Connection Errors

Verify the DB_POSTGRESDB_* variables in the n8n service match the POSTGRES_* variables in the Postgres service exactly, and that the Postgres container reports as healthy before n8n starts. The depends_on healthcheck in the Compose file above should handle startup ordering, but it’s worth checking logs with docker compose logs postgres if problems persist. See the PostgreSQL documentation for deeper troubleshooting.

Can’t Connect Over SSH After Hardening

If you locked yourself out while following the security steps earlier, our guide on fixing SSH connection refused or timeout errors covers the most common causes, from firewall misconfiguration to a locked-out key.

Server Running Out of Memory During AI Workflows

Agent workflows that process large documents or run local models can spike memory usage. If you’re on a smaller VPS plan, adding a swap file is a quick way to prevent out-of-memory crashes while you evaluate whether to upgrade – see our guide on setting up a swap file on your VPS.

Frequently Asked Questions

Is self-hosting n8n free?

The n8n Community edition itself is free and open-source with no execution limits. Your only real cost is the VPS it runs on, which typically costs far less per month than the equivalent usage on n8n Cloud once you’re running any meaningful volume of workflows.

How much VPS do I need to self-host n8n?

For most workflow automation, 2 vCPUs and 4GB of RAM is a comfortable starting point. If you plan to run local AI models through Ollama on the same server, you’ll want significantly more RAM – 16GB or more, depending on model size – since the language model itself, not n8n, is what consumes the resources.

Do I need Docker to self-host n8n?

No, n8n can also be installed directly with npm, but Docker is what n8n’s own documentation recommends for production use, since it isolates dependencies and makes version upgrades a single command instead of a manual Node.js version juggling exercise.

Can self-hosted n8n run AI agents?

Yes. The AI Agent node works identically whether n8n is self-hosted or on n8n Cloud. The advantage of self-hosting is that you can connect agents to local models through Ollama, avoiding per-token API costs and keeping data off third-party servers entirely.

Is it safe to expose n8n directly to the internet without Nginx?

It’s not recommended. Running n8n behind a reverse proxy like Nginx lets you enforce HTTPS, add rate limiting, and keep the application itself bound to localhost, none of which n8n handles for you out of the box.

Should I use SQLite or PostgreSQL for self-hosted n8n?

PostgreSQL is strongly recommended for any production deployment. SQLite works for quick local testing, but it doesn’t handle concurrent writes as gracefully, which becomes a problem once you have multiple workflows executing at the same time.

How do I migrate from n8n Cloud to a self-hosted VPS?

Export your workflows as JSON from the n8n Cloud editor (or via the API), then import them into your self-hosted instance through the same interface. You’ll need to re-enter credentials for each connected service, since credentials are encrypted per-instance and don’t transfer automatically.

What happens if my VPS goes down?

Scheduled and webhook-triggered workflows simply won’t run until the server is back online. This is why regular backups and a reliable hosting provider with strong uptime matter – if you’re running business-critical automations, treat your n8n VPS with the same care you’d give a production application server.

Final Thoughts

Self-hosting n8n takes more setup than clicking sign up on n8n Cloud, but the trade is worth it the moment automation becomes core to how you work: no per-execution ceiling, full control over your data, and the ability to plug directly into self-hosted AI models without paying for every token along the way. The steps above – a secured VPS, Docker Compose with PostgreSQL, Nginx, free SSL, and a real backup routine – give you a setup that’s genuinely production-ready, not just a weekend experiment.

If you’d rather skip the server management entirely, VeerHost’s n8n Hosting plans come pre-configured with Docker, PostgreSQL, and SSL ready to go, so you can be building workflows within minutes instead of debugging Nginx configs.

Launchpad