Back to Article List

Install n8n on Ubuntu 24.04 with Docker and Caddy

 Install n8n on Ubuntu 24.04 with Docker and Caddy

Ubuntu 24.04 is now the go-to base for many VPS deployments. It’s stable, supported for years, and plays well with container workloads. If you want to run n8n in production, Docker and Caddy are a clean way to do it. Docker handles the app and dependencies, while Caddy gives you HTTPS and a reverse proxy without hours of manual config.

I’ll walk through a full installation, from a bare VPS to a working, SSL-enabled n8n instance. Along the way I’ll point out common pitfalls and some production tips.

Prerequisites

  • A fresh Ubuntu 24.04 VPS (1 vCPU / 2GB RAM minimum; 2 vCPU / 4GB recommended for production).
  • Root or sudo access via SSH.
  • A domain name (optional but recommended) pointing to your VPS IP.
  • Basic knowledge of Linux command line.

If you’d rather skip manual setup, you can always start from a ready-to-deploy n8n VPS with Docker and Caddy already preconfigured.

Buuuut…. let’s assume you’re doing this yourself :)

Step 1: Update and install dependencies

Always update first:

sudo apt update && sudo apt upgrade -y

Install the required packages:

sudo apt install -y curl git ufw

We’ll use UFW later to secure the firewall.

Step 2: Install Docker and Docker Compose

On Ubuntu 24.04, the Docker packages from the official repository are the best choice.

curl -fsSL https://get.docker.com | sudo sh

Add your user to the docker group (replace ubuntu with your username):

sudo usermod -aG docker ubuntu
newgrp docker

Check versions:

docker --version
docker compose version

Docker Compose is now built into the Docker CLI, so you can use docker compose directly.

Step 3: Set up project directory

Create a working directory for n8n:

mkdir ~/n8n && cd ~/n8n

Inside, create folders for data:

mkdir n8n_data db_data

Step 4: Configure Docker Compose

Here’s a production-ready Compose file using Postgres and Caddy:

services:
  n8n:
    image: n8nio/n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=changeme
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=strongpassword
      - N8N_HOST=automation.example.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://automation.example.com/
      - N8N_PORT=5678
    volumes:
      - ./n8n_data:/home/node/.n8n
    depends_on:
      - postgres

  postgres:
    image: postgres:15
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=changeme
      - POSTGRES_DB=n8n
    volumes:
      - ./db_data:/var/lib/postgresql/data

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddy_data:/data
      - ./caddy_config:/config
    depends_on:
      - n8n

Notes

  • Replace automation.example.com with your domain.
  • Caddy will handle HTTPS automatically.
  • For security, change the Postgres and n8n credentials before launch.

Step 5: Write the Caddyfile

Create Caddyfile in the same directory:

automation.example.com {
  reverse_proxy n8n:5678
}

If you don’t have a domain, you can skip Caddy and access n8n at http://your-vps-ip:5678, but you won’t get SSL.

Step 6: Start the stack

Bring everything up:

docker compose up -d

Check logs:

docker compose logs -f n8n

After a few seconds, open your browser at https://automation.example.com and you should see the n8n login page.

Step 7: Firewall setup

Block everything except SSH, HTTP, and HTTPS:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable

Check with:

sudo ufw status verbose

Step 8: Backups and monitoring

This is the part most people forget. Postgres holds all workflows and execution history — if you lose it, you start from zero. At minimum:

  • Use pg_dump to back up the database daily.
  • Snapshot your VPS or use a backup service.
  • Enable incremental backups if your provider supports them.

For monitoring, I like Uptime Kuma for simple webhook checks and Grafana with Prometheus for deeper insights. See the Prometheus and Grafana monitoring guide for details.

Step 9: Going further

FAQ

Can I run this without Docker?

Yes, but it’s painful. Docker keeps everything isolated and reproducible.

Do I need a domain name?

Not strictly. You can run on IP only, but services like Stripe or GitHub require HTTPS callbacks. Domains plus Caddy solve this.

How do I upgrade later?

Pull the new image and restart:

docker compose pull n8n
docker compose up -d

Keep backups before upgrading.

Is 2GB RAM enough?

Yes, for light workloads. For anything beyond a few integrations, go 4GB+.

What if I don’t want to manage any of this?

That’s when a managed n8n VPS is worth it. It ships with Docker, Caddy, SSL, backups, and monitoring preconfigured so you can focus on workflows instead of infrastructure.

Automate faster, for less

Bring your winning ideas to life with AMD power, NVMe speed and unmetered bandwidth. Everything backed by 24/7 support, plus a 30-day refund period.