Back to Blog
Uncategorized

How to Self-Host n8n on Ubuntu 22.04: Step-by-Step Deployment with Docker Compose

November 11, 2025·6 min read·Amit El
How to Self-Host n8n on Ubuntu 22.04: Step-by-Step Deployment with Docker Compose

Introduction

If you want full control over your automation, self-hosting n8n on a server you manage is a solid path. It gives you predictable costs, data residency you control, and the ability to tailor resources to your workflows. The catch is that you’re responsible for everything from the initial setup to ongoing maintenance and security. This guide walks you through a production-ready self-hosted n8n deployment on Ubuntu 22.04 using Docker Compose, a PostgreSQL database, and Redis for queueing. You’ll also learn how to front it with a reverse proxy and TLS, how to back up data, and how to handle common pitfalls. By the end, you’ll have a robust baseline you can scale or customize as your needs grow.

We’ll start with prerequisites, move through the concrete steps, and finish with practical tips for security and reliability. If you’re weighing self-hosting against managed options, I’ll highlight where self-hosting shines and where managed hosting (including FlowEngine and other providers) might be more convenient.

Prerequisites

  • A fresh Ubuntu 22.04 server with root or sudo access
  • A domain weblike name you control (for TLS and a friendly URL)
  • Ports 80 and 443 open to the world (for HTTP/S)
  • Basic knowledge of Linux commands and Docker concepts

Why Docker Compose for n8n

n8n provides an official Docker image that works well in multi-container setups. Docker Compose makes it straightforward to coordinate the n8n process with a database (PostgreSQL) and a cache/queue (Redis). That combination is stable, portable, and easier to back up or migrate than a single monolithic container.

Step 1: Prepare the server

Start with a clean Ubuntu 22.04 installation. Update the system, install essential tools, and create a non-root user you’ll use for administration. Running with a non-root user that has sudo rights is a standard best practice.

sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential curl ufw

# Optional: create a dedicated user for n8n management
sudo adduser --disabled-password --gecos "n8n" n8n
sudo usermod -aG sudo n8n

Step 2: Install Docker and Docker Compose

Docker provides the container runtime for both n8n and its dependencies. Docker Compose coordinates the services in a single file.

# Install Docker
sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl enable --now docker

# Add your user to the docker group (log out/in to take effect)
sudo usermod -aG docker $USER

# Install Docker Compose (v2+)
sudo mkdir -p /usr/local/bin
sudo curl -L "https://github.com/docker/compose/releases/download/v2.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Verify
docker --version
docker-compose --version

Step 3: Set up PostgreSQL and Redis

n8n stores its data in PostgreSQL and can use Redis for better performance under load. You can run these as separate containers, but for production it’s cleaner to keep them on the same server and managed by Compose.

# Create a directory for persistent data
sudo mkdir -p /opt/n8n/db /opt/n8n/redis /opt/n8n/data
sudo chown -R $USER:$USER /opt/n8n

# We'll reference these in docker-compose.yml with credentials below

Step 4: Create the Docker Compose file

Place this docker-compose.yml in /opt/n8n/docker-compose.yml. It defines three services: postgres, redis, and n8n. The n8n service exposes port 5678 internally; we’ll put a reverse proxy in front of it later to handle TLS and a friendly domain.

version: '3.8'
services:
  postgres:
    image: postgres:14
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: yourStrongPassword
      POSTGRES_DB: n8n
    volumes:
      - /opt/n8n/db:/var/lib/postgresql/data
    restart: always

  redis:
    image: redis:7
    volumes:
      - /opt/n8n/redis:/data
    restart: always

  n8n:
    image: n8nio/n8n:0.214.0
    depends_on:
      - postgres
      - redis
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=yourStrongPassword
      - N8N_HOST=n8n.example.com
      - N8N_PORT=5678
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=changeMe123
      - TZ=UTC
      - GENERIC_TIMEZONE=UTC
    ports:
      - "5678:5678"
    volumes:
      - /opt/n8n/data:/home/node/.n8n
    restart: always

Notes: - Replace yourStrongPassword with a strong, unique password. - Use a dedicated user for the database and rotate credentials periodically. - N8N_HOST should reflect your public domain once you set up the reverse proxy.

Step 5: Configure a reverse proxy and TLS

Running n8n behind TLS is important for security, especially if you expose webhooks or credentials to the internet. You can use Nginx with Let's Encrypt, Caddy, Traefik, or a dedicated reverse proxy container. The following example uses Nginx with Let’s Encrypt via certbot. Adapt to your domain name.

# Install Nginx
sudo apt-get install -y nginx

# Create an Nginx site config for n8n
sudo tee /etc/nginx/sites-available/n8n << 'NGINX'
server {
  listen 80;
  server_name n8n.example.com;

  location / {
    proxy_pass http://localhost:5678;
    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;
  }
}
NGINX

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

# Obtain TLS certs with certbot
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d n8n.example.com --non-interactive --agree-tos -m [email protected]

# After certs are installed, ensure a redirect from http to https exists

Alternative: If you prefer a containerized reverse proxy, consider Traefik or Nginx in Docker with automatic cert renewal.

Step 6: Start the stack

Bring the stack up and verify that the containers are healthy. Docker Compose makes it straightforward to bring services up or down as a unit.

cd /opt/n8n
docker-compose up -d

docker-compose ps

Step 7: Verify and first login

Open https://n8n.example.com in your browser. You should see the n8n login screen with HTTP Basic Auth enabled. Log in with the credentials you configured in the environment variables. If you don’t see the login screen, check the container logs for the n8n service to ensure the database connection succeeded.

Step 8: Backups and maintenance

Backups are essential. You’re persisting data in PostgreSQL and in a local n8n data directory. Use regular PostgreSQL dumps and rotate credentials. A simple backup plan: keep a daily dump of the database and weekly full server backups. For example:

# PostgreSQL backup (on the host or another management server)
docker exec -t $(docker ps -qf "name=postgres") pg_dump -U n8n n8n > /backups/n8n_$(date +%F).sql

# N8N data backup (if your workflow data lives in /opt/n8n/data)
rsync -avz /opt/n8n/data/ /backup/n8n_data/$(date +%F)/

Security and best practices

Self-hosting means you’re responsible for security. Here are practical practices to reduce risk:

  • Use a strong, unique password for the database and rotate it regularly.
  • Enable TLS so credentials aren’t transmitted in plain text.
  • Restrict DB access to the local host or to a private network if you’re running a multi-node setup.
  • Limit API exposure: enable basic auth for the n8n instance and consider IP whitelisting for admin access.
  • Keep Docker images up to date and apply security patches promptly.

Scaling and performance tips

As your usage grows, you may need to adjust resources and topology. A few practical tips:

  • Move the database to a dedicated server or a managed PostgreSQL service if you expect high concurrent writes.
  • Enable Redis caching and tune its memory limits to prevent eviction during peaks.
  • Consider running multiple n8n instances behind a load balancer for high availability.
  • Monitor CPU, memory, and disk I/O; watch for large backlog on the queue and adjust workers or instance size accordingly.

When to consider FlowEngine or other managed hosting options

Self-hosting is not for everyone. If you prefer a managed path, there are options like n8n Cloud, FlowEngine, and other hosting providers. Managed hosting can simplify upgrades, backups, and security patches, but typically comes with a predictable ongoing cost and less control over the underlying stack. If your team prioritizes hands-off operation and rapid deployment, a managed option may be worth the trade-off. FlowEngine, for example, advertises easy onboarding and built-in automation features; evaluate it against your security, compliance, and data residency requirements before deciding.

Common pitfalls and quick fixes

These issues come up frequently when self-hosting n8n. Quick checks can save you hours:

  • DB connection errors: verify DB_HOST, DB_POSTGRESDB_PASSWORD, and ensure the PostgreSQL container is healthy.
  • n8n cannot reach Redis: confirm the Redis service is running and that the correct host/port are configured if you’re not using the default Docker network.
  • TLS misconfiguration: ensure the TLS certs are valid and that your reverse proxy forwards headers properly.
  • Memory pressure: allocate more RAM or reduce the number of workflows running in parallel.

Documentation and references

Official sources and best-practice references help you keep the stack secure and maintainable:

Conclusion

Self-hosting n8n on Ubuntu 22.04 with Docker Compose gives you control, flexibility, and potentially lower ongoing costs once you’re past the initial setup. It requires careful attention to security, backups, and monitoring, but the payoff is a system you can tailor to your exact workflows and data needs. If you’re weighing it against managed hosting, consider your team’s capacity for maintenance and your data residency requirements. Regardless of the path you choose, the graph of your automation grows with you as you add more workflows and integrations.