Self Hosting (Updated: ) 8 min read

Self-Host n8n 2026: Complete Docker Compose & PostgreSQL Setup

Suresh S Suresh S
Self-Host n8n 2026: Complete Docker Compose & PostgreSQL Setup

A few years ago, I hit a massive wall trying to automate a simple data pipeline for a client. We were using Zapier, and everything was fine until our payload sizes grew and the API began triggering 10,000 times a day. Overnight, our monthly automation bill skyrocketed. Cloud automation platforms are amazing until you actually scale.

I realized I needed an automation engine that I could run myself, with unlimited executions and total data privacy. Enter n8n (nodemation).

As one of the best open-source software alternatives on the market, n8n is a node-based workflow editor that connects to over 400+ services (like Slack, Postgres, OpenAI, and custom webhooks). Best of all, because you run it on your own server, your sensitive business logic stays strictly internal, mimicking the data processing layers you might see in high-end Open Source Intelligence (OSINT) pipelines.

In this tutorial, I’ll show you exactly how I deploy production-grade n8n instances. We will skip the toy SQLite setups and dive straight into a robust Docker Compose stack backed by PostgreSQL, running on a cheap VPS. Grab your favorite text editor (I personally use Micro instead of Nano), and let’s start automating.


1. Why Self-Host n8n?

If you currently rely on SaaS automation, you are fundamentally renting your infrastructure. This is fine for simple prototypes, but when automation becomes a critical part of your software development lifecycle (SDLC), you need control.

When you self-host n8n using Docker, you leverage the exact same containerization benefits I discuss in my Docker vs Podman benchmark. You get absolute environment consistency. More importantly, running n8n on a private server ensures that API tokens and customer data never leave your network, granting you a level of privacy approaching full End-to-End Encryption.

If you are new to the concept of renting a server instead of paying for a SaaS subscription, read up on exactly what cloud computing is. To follow this guide, you just need a server with Docker installed. Check out my guide on installing Docker on Ubuntu if you need a clean slate.


2. Architecture: Why PostgreSQL is Mandatory

When you run n8n, it needs a place to store its workflow definitions, credentials, and execution logs.

By default, n8n uses a local SQLite file. This is great for a laptop, but terrible for a production server receiving concurrent webhooks. SQLite locks the entire database file when writing. If three webhooks hit your server simultaneously, two of them might drop because the database is locked.

This is why we pair n8n with PostgreSQL. If you’ve read my PostgreSQL vs MySQL comparison, you know Postgres excels at handling high-concurrency row locks. It allows n8n to process multiple triggers simultaneously without crashing.

Because we’ll be spinning up multiple containers, we need to make sure our disk I/O can keep up. If you’re building a dedicated server, you might want to look at a BTRFS vs Ext4 filesystem comparison to optimize database write speeds. Furthermore, managing these databases means you need a solid grasp of Linux file permissions. Don’t guess your chmod flags; use my Linux Permission Calculator to get them right. Lastly, always keep an eye on active ports using the top 20 Linux security commands to ensure your database isn’t publicly exposed.


3. Preparing the Server Environment

Before we write the Docker Compose file, ensure your server is ready. I recommend running this stack on Ubuntu 24.04 LTS (one of the best Linux distros for beginners).

If writing raw YAML files isn’t your thing, you can deploy n8n using a graphical PaaS like Coolify or Dokploy. However, deploying it manually via Docker Compose gives you a deeper understanding of the underlying systemd processes and networking layers.

Create a dedicated directory for our configuration:

mkdir -p ~/n8n-docker
cd ~/n8n-docker

4. The .env and Docker Compose Configuration

Never hardcode database passwords inside your docker-compose.yml file. Instead, we use an environment (.env) file to store secrets.

Create the .env file:

nano .env

Paste the following variables:

# Database Credentials
POSTGRES_USER=n8n_user
POSTGRES_PASSWORD=YourSecureDatabasePassword
POSTGRES_DB=n8n_db

# n8n General Configuration
N8N_HOST=n8n.yourdomain.com
N8N_PORT=5678
N8N_PROTOCOL=https
NODE_ENV=production

# Public Webhook URL (Crucial for external webhooks)
WEBHOOK_URL=https://n8n.yourdomain.com/

# Encryption Key for n8n Stored Credentials (DO NOT LOSE THIS KEY!)
N8N_ENCRYPTION_KEY=your_generated_random_encryption_key
GENERIC_TIMEZONE=UTC

You need extremely strong values for POSTGRES_PASSWORD and N8N_ENCRYPTION_KEY. Use my Password Generator to create them, and verify their entropy with the Password Strength Checker. For the encryption key, a 64-character string from a UUID Generator works perfectly. I also recommend checking out my .env Generator for future projects. Most importantly, store these keys safely in one of the best password managers.

Next, create the docker-compose.yml file:

nano docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:16-alpine
    container_name: n8n_postgres
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - postgres_storage:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    container_name: n8n_app
    restart: always
    ports:
      - "5678:5678"
    environment:
      - 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}
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=${N8N_PORT}
      - N8N_PROTOCOL=${N8N_PROTOCOL}
      - NODE_ENV=${NODE_ENV}
      - WEBHOOK_URL=${WEBHOOK_URL}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - n8n_storage:/home/node/.n8n

volumes:
  postgres_storage:
  n8n_storage:

5. System Firewall & Security Best Practices

Before you bring this stack online, lock down your host firewall. By default, n8n will bind to port 5678.

Follow my comprehensive UFW firewall guide to explicitly allow web traffic, but block everything else:

sudo ufw allow 5678/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload

Because n8n will hold API keys to your Google, Slack, and AWS accounts, security is non-negotiable. I strongly advise installing Fail2ban and CrowdSec to block automated brute-force attacks at the network layer. Furthermore, disable password logins for your server and strictly follow my tutorial on how to secure SSH on Ubuntu. For ultimate paranoia, don’t expose n8n to the public internet at all—put it behind a VPN tunnel like WireGuard.


6. Reverse Proxy & HTTPS

If you want to receive webhooks from services like Stripe or GitHub, n8n must be accessible via a public HTTPS URL.

To achieve this, you need a reverse proxy. My favorite tool for this is Nginx Proxy Manager (NPM) because of its beautiful GUI.

  1. First, understand how DNS works and point an A record (e.g., n8n.yourdomain.com) to your server’s IP.
  2. In NPM, create a proxy host pointing n8n.yourdomain.com to localhost:5678.
  3. Enable “Websockets Support”.
  4. Go to the SSL tab and click the button to enable HTTPS with Let’s Encrypt.

If you prefer writing raw configuration files, you can use my Nginx Config Generator to generate the block, or explore the extremely popular Caddy web server as a minimal alternative.

Once your proxy is up, start the container stack:

docker compose up -d

Navigate to https://n8n.yourdomain.com to create your owner account!


7. Building AI Workflows in n8n

One of the most powerful reasons to self-host n8n in 2026 is its native LangChain integration. You can build advanced AI agents directly in the workflow canvas.

For complete privacy, you can connect n8n’s AI nodes to a local Ollama server. This allows you to process documents, extract structured JSON payloads, and generate email responses entirely on your own hardware without paying OpenAI API fees.

I frequently pair n8n with Open WebUI to orchestrate data between my other self-hosted apps. For example, you can write an n8n workflow that automatically routes scanned PDFs into Paperless-ngx, sends newly downloaded photos directly to Immich, and zips client invoices into Nextcloud. The possibilities are literally endless.


8. Backups & Disaster Recovery

If you lose your n8n_storage volume or your PostgreSQL database, your workflows are gone. If you lose your N8N_ENCRYPTION_KEY from your .env file, all your API credentials become permanently unreadable.

You must implement a solid disaster recovery plan. Follow my master guide on backup strategies for self-hosted servers to set up automated nightly cron jobs. I use pg_dump to export the PostgreSQL database, compress it into an archive, and then use SFTP transfers or Syncthing to automatically pull those archives offsite to a backup NAS.

Lastly, you should know immediately if your automation server goes down. Check out my guide on deploying Uptime Kuma to monitor your https://n8n.yourdomain.com endpoint so you get a Telegram ping the second it drops offline.


Frequently Asked Questions (FAQ)

What are the minimum system requirements for self-hosting n8n?

n8n requires a minimum of 1GB RAM and 1 vCPU for light workflows. For production environments running complex automations, webhooks, and AI pipelines, 2GB to 4GB RAM and a PostgreSQL backend database are highly recommended.

Should I use SQLite or PostgreSQL for n8n’s database?

SQLite is fine for local testing, but PostgreSQL is strongly recommended for production self-hosting. PostgreSQL provides robust concurrent execution handling, prevents database locking under heavy webhook traffic, and is a prerequisite if you plan to use n8n’s Queue Mode.

How do I configure external webhooks in self-hosted n8n?

You must set the WEBHOOK_URL environment variable in your .env file to your public HTTPS domain (e.g., WEBHOOK_URL=https://n8n.yourdomain.com/). Without this, n8n will generate useless localhost URLs when configuring triggers.

What is n8n Queue Mode and when should I enable it?

Queue Mode splits n8n into separate web editor, main process, and worker containers connected via a Redis broker. It enables horizontal scaling, allowing you to process thousands of parallel executions without slowing down the web interface. You only need this if you are processing massive enterprise loads.

How do I update self-hosted n8n to the latest release?

Navigate to your project directory and run docker compose pull, followed by docker compose up -d. Docker will pull the updated container image and seamlessly recreate the service while preserving your database and configuration volumes.

Why do my workflows fail with Out-Of-Memory (OOM) errors?

Processing incredibly large JSON datasets or massive binary file attachments can exceed your container’s memory limit. You can fix this by increasing your server’s RAM, or by setting EXECUTIONS_DATA_SAVE_ON_ERROR=all and EXECUTIONS_DATA_PRUNE=true in your environment variables to aggressively clean up execution history.

Is self-hosted n8n completely free?

Yes. n8n operates under a “Faircode” (Sustainable Use) license. You can self-host it and use all of its features for internal company use or personal projects completely free of charge. You only need an enterprise license if you are building a commercial product that resells n8n as a service.

Can I run Python or JavaScript directly inside an n8n workflow?

Absolutely. n8n has dedicated Code nodes that allow you to write custom JavaScript or Python scripts directly in the canvas. This is perfect for parsing weird data structures or performing complex math that standard nodes don’t support.

Does n8n support two-factor authentication (2FA)?

Yes. While the community edition doesn’t have advanced SAML/SSO baked in, you can configure standard Time-based One-Time Password (TOTP) two-factor authentication directly within your user settings profile to secure your account.

How do I share an n8n workflow with someone else?

n8n workflows are essentially large JSON objects. You can simply highlight all the nodes on your canvas, press Ctrl+C to copy, and paste the raw JSON text to a friend. When they paste it into their own n8n canvas, the nodes will automatically appear.

Suresh S

Written by Suresh S

Systems Engineer & Tech Educator with 8+ years of experience in Linux Administration, Cloud Computing, and Cybersecurity. Founder of FreeTechLearner, dedicated to creating practical tutorials that help students and professionals build real-world skills.

Share this post:

Discussion

Loading comments...