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:
- Prepare Ubuntu (firewall, packages, automatic updates).
- Generate SSH keys and configure a Git repo for Docker Compose.
- Create
docker-compose.yml,.gitignoreandCaddyfilefiles. - Clone the repo to the server, set correct permissions and solve common errors.
- 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
ufwor 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.
Links
- n8n homepage: https://n8n.io
- n8n documentation: https://docs.n8n.io
- Source code (GitHub): https://github.com/n8n-io/n8n