Grzegorz Bartman
March 8, 2025 · 4 min read

n8n on VPS: Step by Step from Bare Ubuntu to Running n8n

n8n lets you easily create automated workflows between various services (Jira, Slack, email, OpenAI and many more). You can self-host it for full control over your data and costs.

Starting from scratch on a fresh Ubuntu server, installing all the tools, securing it, and configuring SSL for n8n can be complex. It’s easy to skip important steps or misconfigure things, leading to permission errors and unprotected HTTP traffic.

In this guide you’ll learn how to:

  1. Prepare Ubuntu (firewall, packages, automatic updates).
  2. Generate SSH keys and configure a Git repo for Docker Compose.
  3. Create docker-compose.yml, .gitignore and Caddyfile files.
  4. Clone the repo to the server, set correct permissions and solve common errors.
  5. Run n8n with an SSL certificate from Let’s Encrypt using the Caddy reverse proxy.

Where to Buy a Cheap VPS/Cloud Server

Here are some of the most popular providers worth checking:

  • Hetzner
  • OVH
  • DigitalOcean
  • Linode
  • Mikrus

Prices at these providers typically start around $5 per month. Check current offers and compare CPU power, RAM, data transfer, and server locations.

Preparing the Ubuntu Server — Packages, Security, Firewall

Start by updating packages:

apt update
apt upgrade -y

Install the automatic updates tool:

apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades

Firewall (UFW)

Install and enable ufw, opening the basic ports (SSH, HTTP, HTTPS):

apt install -y ufw
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 5678/tcp
ufw enable

portsentry — Port Scan Protection

To further protect the server from port scans and suspicious connection attempts, install portsentry:

apt install -y portsentry
  • The config file is usually at /etc/portsentry/portsentry.conf.

  • You can add trusted IP addresses to the whitelist in /etc/portsentry/portsentry.ignore.static:

    echo "123.123.123.123" >> /etc/portsentry/portsentry.ignore.static
  • Start and enable the service:

    systemctl enable portsentry
    systemctl start portsentry

This reduces the risk of attacks on open ports.

SSH Keys — Working with the Docker Compose Repository

Generate an SSH key (e.g. for Bitbucket) to easily clone and push changes to the repository:

ssh-keygen -t rsa -b 4096 -C "your_email@domain.com" -f ~/.ssh/id_rsa_bitbucket

Add the public key (id_rsa_bitbucket.pub) to the repo settings (Bitbucket/GitLab/GitHub). This way you won’t need to enter a password on every git push/pull.

Files in the Repo: Docker Compose, .gitignore and Caddyfile

Prepare the following in your local repo (or directly on the server):

docker-compose.yml

Contains service definitions (n8n and Caddy) with automatic SSL configuration:

version: "3"
services:
 n8n:
   image: n8nio/n8n
   container_name: n8n
   restart: unless-stopped
   environment:
     - N8N_HOST=n8n.your-domain.com
     - N8N_PROTOCOL=https
     - N8N_PORT=5678
     - WEBHOOK_URL=https://n8n.your-domain.com/
     - N8N_SECURE_COOKIE=false
   volumes:
     - ./n8n-data:/home/node/.n8n
 caddy:
   image: caddy:latest
   container_name: caddy
   restart: unless-stopped
   ports:
     - "80:80"
     - "443:443"
   volumes:
     # Our Caddy config file
     - ./Caddyfile:/etc/caddy/Caddyfile:ro
     # Storing data and certificates
     - caddy_data:/data
     - caddy_config:/config
   depends_on:
     - n8n
volumes:
 caddy_data:
 caddy_config:

Caddyfile

Caddy will automatically obtain and renew a Let’s Encrypt certificate:

{
   email your_email@domain.com
}
n8n.your-domain.com {
   reverse_proxy n8n:5678
}

.gitignore

Don’t commit local n8n data to the repo:

n8n-data
.env

Cloning the Repo, Permissions and Common Errors

On the server:

apt install -y git
mkdir /opt/n8n
cd /opt/n8n
git clone git@bitbucket.org:your_user/your_repo.git
cd your_repo

If you use containers (like n8n) with uid/gid 1000, make sure the directories have the correct permissions:

mkdir n8n-data
chown -R 1000:1000 n8n-data

Most Common Errors and Solutions:

  • Port not open (e.g. 5678) — check ufw or the security rules in your VPS panel.
  • EACCES (permission denied) — set correct permissions on the n8n data directory.
  • Wrong address / HTTPS — make sure you set the correct domain (e.g. n8n.your-domain.com).

5. Running n8n with SSL

Everything ready? In the project directory:

docker-compose up -d

Caddy will start, obtain the Let’s Encrypt certificate, and n8n will be accessible at:

https://n8n.your-domain.com

(replace n8n.your-domain.com with your actual subdomain).


Summary

You now have a working n8n instance on your own Ubuntu server, running via Docker Compose, with automatic system updates, UFW firewall, and a Let’s Encrypt certificate managed by Caddy. All steps — from SSH keys, through file configuration, to avoiding common permission errors — are in one place, so you can easily adapt this recipe to your own needs.