n8n is an open-source, source-available workflow automation platform that gives developers and system administrators complete control over data flows and integrations. Unlike proprietary SaaS alternatives like Zapier, n8n can be self-hosted on your own infrastructure, such as an ENGINYRING VPS. This unlocks unparalleled flexibility, enhances data privacy, and provides predictable, scalable performance without per-task pricing. This comprehensive tutorial provides a definitive, step-by-step walkthrough for installing and configuring n8n on a self-hosted Ubuntu 24.04 server using Docker Compose. You will learn how to secure your instance with an Nginx reverse proxy and Let's Encrypt SSL, implement a robust backup and upgrade strategy, and build a real-world monitoring workflow to automate incident response.

Why self-host n8n on a VPS?

While n8n offers a cloud version, self-hosting on a virtual private server (VPS) is the superior choice for developers who demand control, security, and cost-efficiency. The primary advantage of VPS hosting is the allocation of dedicated resources within an isolated environment, which is fundamental for running a stable automation engine. The Docker-based approach provides the perfect balance of simplicity and power, allowing you to manage your n8n instance as a scalable, containerized application.

OptionProsConsRecommended For
n8n CloudZero setup, managed infrastructure, automatic scaling.Monthly cost per user/execution, limited backend control, potential data privacy concerns.Non-technical users, teams needing a quick start without infrastructure overhead.
Self-Hosted (Docker on a VPS)Full data control, one-time infrastructure cost, unlimited users/workflows, complete privacy and security.Requires initial setup, server maintenance, and manual backups.Developers, DevOps teams, and businesses prioritizing data sovereignty and predictable costs.
Bare-metal (Node.js)Maximum configuration flexibility, no container overhead.Complex manual configuration, dependency management, and difficult upgrades.Advanced users with highly specific, non-standard use cases.
Comparison of n8n deployment options.

Prerequisites

Before beginning this guide, you must have a server running Ubuntu 24.04 and ensure the following are in place:

  • A non-root user with sudo privileges: Following Linux security best practices is essential. Our guide to securing a vanilla VPS covers creating a non-root user.
  • Docker and Docker Compose: The containerization engine and orchestration tool must be installed.
  • A registered domain name: A domain (e.g., `n8n.yourdomain.com`) with its DNS 'A' record pointing to your server's public IP address. This is mandatory for securing your instance with SSL.

Step 1: Install Docker and Docker Compose

First, update your server's package repository and install Docker and Docker Compose. These tools will be used to download and manage the n8n and PostgreSQL containers.

sudo apt update
sudo apt install docker.io docker-compose -y

Add your user to the `docker` group to run Docker commands without `sudo`. You will need to log out and log back in for this change to take effect.

sudo usermod -aG docker ${USER}

Step 2: Create the Docker Compose Configuration

Create a dedicated directory for your n8n configuration to keep your project organized.

mkdir ~/n8n && cd ~/n8n

Inside this directory, create a `docker-compose.yml` file. This file defines the services, networks, and volumes for your application stack.

nano docker-compose.yml

Paste the following configuration into the file. This setup defines two services: `n8n` and a `postgres` database. Using a persistent PostgreSQL database is critical for production, as the default SQLite database is not suitable for concurrent workflows.

version: '3.7'

services:
  db:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=your_secure_db_password
      - POSTGRES_DB=n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n
    restart: always
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=db
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=your_secure_db_password
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=your_secure_auth_password
      - N8N_HOST=n8n.yourdomain.com
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - NODE_OPTIONS=--max-old-space-size=2048
    depends_on:
      db:
        condition: service_healthy
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  postgres_data:
    driver: local
  n8n_data:
    driver: local

Configuration Breakdown:

  • `restart: always`: Ensures that the containers automatically restart if they crash or after a server reboot.
  • `ports: - "127.0.0.1:5678:5678"`: Exposes the n8n container on port 5678, but binds it only to the localhost interface. This is a critical security measure that prevents direct public access to n8n, forcing all traffic through our secure Nginx reverse proxy.
  • `N8N_BASIC_AUTH_*`: Sets up initial basic authentication. You must change `your_secure_auth_password`. This will be replaced by the owner account you create in the UI.
  • `N8N_HOST` & `WEBHOOK_URL`: Tells n8n its public-facing URL. This is essential for generating correct webhook URLs. Replace `n8n.yourdomain.com` with your actual domain.
  • `NODE_OPTIONS=--max-old-space-size=2048`: Allocates 2GB of memory to the Node.js process, preventing "heap out of memory" errors on complex workflows. Adjust based on your VPS resources.
  • `depends_on`: The `service_healthy` condition ensures that the n8n container will not start until the PostgreSQL database is fully running and ready to accept connections.
  • `volumes`: Creates persistent Docker volumes (`postgres_data` and `n8n_data`) to store your database data and n8n user data (workflows, credentials), ensuring that your data survives container restarts and updates.

With the configuration file saved, start the containers in detached mode:

docker-compose up -d

Step 3: Set Up Nginx as a Reverse Proxy

We will now configure Nginx to act as a reverse proxy. This will accept public traffic on ports 80 and 443 (HTTPS) and forward it to the n8n container, which is safely listening on `localhost:5678`.

First, install Nginx and Certbot (the tool for Let's Encrypt SSL certificates).

sudo apt install nginx certbot python3-certbot-nginx -y

Create a new Nginx server block configuration file for n8n.

sudo nano /etc/nginx/sites-available/n8n

Paste the following configuration. This initial setup is for HTTP only; Certbot will upgrade it to HTTPS later.

server {
    listen 80;
    server_name n8n.yourdomain.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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
}

The `proxy_set_header` directives ensure that information about the original request (like the hostname and protocol) is passed to the n8n container. The `Upgrade` and `Connection` headers are essential for enabling WebSocket support, which n8n uses for real-time UI updates.

Enable the site, test the Nginx configuration, and reload the service.

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

Step 4: Secure Your n8n Instance with SSL

With Nginx configured, use Certbot to obtain and install a free Let's Encrypt SSL certificate. This command will automatically detect your `server_name` from the Nginx config, obtain a certificate, and update the config file to enable HTTPS.

sudo certbot --nginx -d n8n.yourdomain.com

Follow the on-screen prompts. When asked, choose the option to redirect all HTTP traffic to HTTPS. This enforces encryption for all users. Certbot will also set up a scheduled task to automatically renew the certificate before it expires, ensuring your site remains secure without manual intervention.

Step 5: Initial n8n Setup and Configuration

Navigate to `https://n8n.yourdomain.com` in your web browser. You will be guided through a one-time setup process to create your admin account and configure the instance.

Create an Owner Account

The first screen prompts you to create an owner account. This account will have the highest level of administrative privileges for your n8n instance, replacing the basic auth credentials you set in the `docker-compose.yml` file. Use a strong, unique password.

Personalization Questions

Next, n8n will ask a few optional questions about your role and use case. Answering these helps the n8n team understand their user base, but you can skip them if you prefer.

Activate Community License

You will be offered a chance to unlock paid features (such as execution history and advanced debugging) for free by registering your community instance. Provide your email address to receive a free lifetime license key. Once you receive the key, navigate to **Settings → Usage and Plan → Enter Activation Key** to activate it. This step is highly recommended as it unlocks functionality that is extremely useful for production environments.

Real-World Example: Automated Server Downtime Alerts

To demonstrate n8n's power, let's create a workflow that monitors a server and automates incident response. This workflow will check a website's status, restart Nginx if it's down, and send alerts to Slack and Discord.

Workflow Nodes Breakdown

  • Schedule Trigger: Starts the workflow every 5 minutes.
  • HTTP Request: Pings your website to check its status.
  • IF Node: Checks if the HTTP status code is not 200 (i.e., the site is down).
  • Execute Command: If the site is down, it runs `sudo systemctl restart nginx` on the server via SSH.
  • Slack & Discord Nodes: Sends a notification to your team channels with the incident details.

This simple example showcases how n8n can serve as a powerful, self-hosted monitoring and incident automation tool. It can be extended to integrate with tools like UptimeRobot, update DNS records on Cloudflare, or create tickets in a project management system. For more advanced concepts, explore our guide on building autonomous systems with agentic AI.

Advanced Management: Backups, Upgrades, and Troubleshooting

A production deployment is not "set it and forget it." Proper management is essential for long-term stability and security.

Implementing a Robust Backup Strategy

Your n8n instance contains critical data: your workflows and your credentials. Losing this data would be catastrophic. As detailed in our ultimate guide to VPS backups, a reliable backup strategy is non-negotiable. You must back up both the `postgres_data` and `n8n_data` volumes.

You can automate this process with a simple shell script and a cron job. Create a script named `backup_n8n.sh`:

#!/bin/bash
set -e

BACKUP_DIR="/opt/n8n_backups"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
N8N_DIR="/home/your_user/n8n" # CHANGE THIS to your n8n directory

# Create backup directory if it doesn't exist
mkdir -p $BACKUP_DIR

# Stop n8n to ensure data consistency
cd $N8N_DIR
docker-compose stop n8n

# Backup the PostgreSQL database
docker-compose exec -T db pg_dumpall -U n8n | gzip > $BACKUP_DIR/n8n_db_backup_$DATE.sql.gz

# Backup the n8n data volume
sudo tar -czf $BACKUP_DIR/n8n_data_backup_$DATE.tar.gz -C /var/lib/docker/volumes/n8n_n8n_data/_data .

# Restart n8n
docker-compose start n8n

# Prune old backups (keep the last 7)
find $BACKUP_DIR -type f -name "*.gz" -mtime +7 -delete

Make the script executable (`chmod +x backup_n8n.sh`) and schedule it to run nightly with a cron job (`sudo crontab -e`). For true disaster recovery, you should sync these backups to an off-site location like an S3-compatible object storage service.

Safely Upgrading Your n8n Instance

Thanks to Docker, the upgrade process is straightforward. Before you begin, always create a manual backup and check the n8n release notes for any breaking changes.

# Navigate to your n8n directory
cd ~/n8n

# Pull the latest Docker images for all services
docker-compose pull

# Recreate the containers with the new images
docker-compose up -d

This process will stop the old containers and start new ones using the updated images. Because your data is stored in persistent volumes, your workflows and settings will be preserved.

Advanced Troubleshooting

When workflows fail, your first step should always be to check the logs. Following our guide on detecting intruders and issues can help you become proficient at log analysis.

# View live logs for the n8n container
docker-compose logs -f n8n

Here are some common advanced errors and their solutions:

  • `JavaScript heap out of memory`: Your workflow is too complex for the default memory limit. Increase the memory allocated in the `NODE_OPTIONS` environment variable in your `docker-compose.yml`.
  • Webhook Timeouts: If you have long-running webhooks, Nginx may be timing out. Add `proxy_read_timeout 300s;` to your Nginx location block to increase the timeout to 5 minutes.
  • Permission Denied on Volume Mount: If the container fails to start with permission errors, it's because the user inside the Docker container (UID 1000) cannot write to the host-mounted volume directory. Running `sudo chown -R 1000:1000 ./n8n_data` on the host can fix this.

Frequently Asked Questions (FAQ)

Q1: What are the prerequisites for installing n8n on an ENGINYRING VPS?
You will need an Ubuntu 24.04 server with `sudo` privileges, a registered domain name pointed to your server’s IP, and Docker with Docker Compose installed. We recommend a VPS with at least 2GB of RAM for stable performance.

Q2: How do I back up my self-hosted n8n instance?
You must back up both the `n8n_data` and `postgres_data` Docker volumes. The safest method is to stop the containers, use `tar` to archive the volume directories (located in `/var/lib/docker/volumes/`), and then restart the containers. This should be automated and stored off-site.

Q3: How do I upgrade my n8n instance safely?
To upgrade, first create a backup. Then, navigate to your `~/n8n` directory and run `docker-compose pull` to fetch the latest images. Finally, run `docker-compose up -d` to restart the containers with the new versions. Your data will be preserved thanks to the persistent volumes.

Q4: My webhooks are not working. What is wrong?
This is almost always a configuration issue with the `WEBHOOK_URL` environment variable. Ensure it is set to your full, public HTTPS URL (e.g., `https://n8n.yourdomain.com/`). Without this, n8n will generate incorrect webhook URLs that are unreachable from the public internet.

Source & Attribution

This article is based on original data belonging to ENGINYRING.COM blog. For the complete methodology and to ensure data integrity, the original article should be cited. The canonical source is available at: How to Set Up n8n: A Step-by-Step Guide for Self-Hosted Workflow Automation on an ENGINYRING VPS.