What you'll need

Before you start, make sure you have everything from this list on hand:

  • A credit card to rent a VPS (Visa/Mastercard, including cards issued in Ukraine)
  • A domain — optional, but recommended for HTTPS. You can grab one on Namecheap from $6/year
  • An SSH client: Terminal (macOS/Linux) or PuTTY (Windows). On Windows 10+ you can use the built-in OpenSSH
  • 30 minutes of free time
New to the terminal?

That's fine. The whole guide is built on the copy-and-paste principle. Every command is explained. And if something breaks — there's an FAQ section at the end with the most common errors.

Choose and rent a VPS

A VPS (Virtual Private Server) is your own server in the cloud, running 24/7. That's where n8n will live. Here are the best options:

Provider From Locations Why it's good
Hetzner €3.79/mo Germany, Finland Best price/performance ratio, built-in Firewall
DigitalOcean $4/mo Amsterdam, Frankfurt Simple interface, tons of tutorials
Contabo €4.50/mo Germany More resources for the same money

HAIQ's pick: Hetzner Cloud, plan CX22 — 2 vCPU, 4 GB RAM, 40 GB NVMe for €5.18/mo. Enough for dozens of active workflows.

How to create a server on Hetzner

Sign up at hetzner.cloud, create a new project, and click "Add Server". Pick: region — Falkenstein or Helsinki (closest to Ukraine), OS — Ubuntu 24.04, plan — CX22 or at least CX11 (2 GB RAM). In the SSH Keys section, add your public key (otherwise a password will be emailed to you).

Minimum requirements

1 vCPU and 1 GB RAM is the minimum for light workflows (up to 10 active). For production with AI nodes and PostgreSQL, go with 2 vCPU and 4 GB RAM. n8n with AI agents eats more memory.

Connect to your server via SSH

Once the server is created, you'll get an IP address (something like 65.108.xx.xx). Open your terminal and connect:

ssh root@65.108.xx.xx

On the first connection, the system will ask "Are you sure you want to continue connecting?" — type yes. Then enter the password (or the connection will happen automatically if you added an SSH key).

First things first — update the system and install some base utilities:

# Update packages apt update && apt upgrade -y # Install base utilities apt install -y curl wget git nano ufw ca-certificates gnupg

Configure the firewall — allow only SSH, HTTP, and HTTPS:

ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS ufw enable

Install Docker

Docker is a tool that lets you run applications in isolated containers. Think of it as a "box" where n8n lives with all its dependencies. You can install it with a single command:

# Install Docker with a single script curl -fsSL https://get.docker.com | sh # Verify Docker is working docker --version # Should print something like: Docker version 27.x.x # Verify Docker Compose (already included) docker compose version # Docker Compose version v2.x.x
You're set

Docker Compose ships inside modern Docker versions — you don't need to install it separately. If docker compose version works, you're good.

Deploy n8n with PostgreSQL

Now we'll create the configuration for n8n. We'll use PostgreSQL instead of the default SQLite, because PostgreSQL handles load better and is more reliable in production.

Create the working directory and folders for data:

# Create the folder for n8n mkdir -p ~/n8n && cd ~/n8n # Create data folders mkdir -p n8n_data postgres_data # Set the correct permissions for n8n chown -R 1000:1000 n8n_data

Create the environment variables file at ~/n8n/.env:

# === n8n Configuration === N8N_HOST=n8n.yourdomain.com N8N_PORT=5678 N8N_PROTOCOL=https WEBHOOK_URL=https://n8n.yourdomain.com/ GENERIC_TIMEZONE=Europe/Kyiv # Encryption key (SAVE THIS! Without it you can't restore credentials) # Generate with: openssl rand -hex 16 N8N_ENCRYPTION_KEY=your_32_char_key_here # === PostgreSQL === DB_TYPE=postgresdb DB_POSTGRESDB_HOST=postgres DB_POSTGRESDB_PORT=5432 DB_POSTGRESDB_DATABASE=n8n DB_POSTGRESDB_USER=n8n DB_POSTGRESDB_PASSWORD=your_strong_db_password # Disable telemetry (optional) N8N_DIAGNOSTICS_ENABLED=false
Critical

Save your N8N_ENCRYPTION_KEY somewhere safe (password manager, a note on your phone). If you lose this key — every saved credential (API keys, passwords) becomes unreadable, and you'll have to re-enter them all.

Generate an encryption key:

openssl rand -hex 16 # Copy the result into your .env file

Now create the main file — ~/n8n/docker-compose.yml:

services: postgres: image: postgres:16 container_name: n8n_postgres restart: unless-stopped environment: POSTGRES_USER: n8n POSTGRES_PASSWORD: ${DB_POSTGRESDB_PASSWORD} POSTGRES_DB: n8n volumes: - ./postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U n8n"] interval: 10s timeout: 5s retries: 5 n8n: image: docker.n8n.io/n8nio/n8n container_name: n8n restart: unless-stopped ports: - "5678:5678" env_file: - .env depends_on: postgres: condition: service_healthy volumes: - ./n8n_data:/home/node/.n8n

Start the containers:

# Start containers in the background docker compose up -d # Check the status docker compose ps # Watch the n8n logs docker compose logs -f n8n # Look for the line: "n8n ready on 0.0.0.0, port 5678"

If you see "n8n ready on 0.0.0.0, port 5678" — congrats, n8n is running. For now it's reachable at http://your-ip:5678, but you'll want HTTPS for production.

Connect your own domain

To make n8n available at a clean address (like n8n.yourdomain.com), you need to create a DNS record.

Go to your domain's control panel (Namecheap, Cloudflare, GoDaddy — any registrar) and create an A record:

Type Name Value TTL
A n8n 65.108.xx.xx (your VPS IP) 300

Wait 5–10 minutes for DNS to propagate. You can check with:

dig n8n.yourdomain.com # Should return your server's IP

HTTPS via Let's Encrypt

HTTPS is required for n8n — without it, OAuth2 integrations (Google Sheets, Gmail, Slack), webhooks, and secure cookies won't work. We'll use Nginx as a reverse proxy plus Let's Encrypt for a free SSL certificate.

Install Nginx and Certbot:

apt install -y nginx certbot python3-certbot-nginx

Create the Nginx config at /etc/nginx/sites-available/n8n:

server { server_name n8n.yourdomain.com; location / { proxy_pass http://localhost:5678; proxy_http_version 1.1; # WebSocket support (for the n8n editor) proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; # Increase the limit for large payloads client_max_body_size 50m; } }

Activate the config and get the certificate:

# Enable the config ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/ nginx -t # Check syntax systemctl reload nginx # Get the SSL certificate (replace email and domain) certbot --nginx -d n8n.yourdomain.com \ --email your@email.com \ --agree-tos \ --non-interactive

Certbot will automatically fetch a certificate from Let's Encrypt, update the Nginx config for HTTPS, and set up automatic renewal every 90 days. n8n is now available at https://n8n.yourdomain.com.

Automated backups

Backups are your insurance. If anything goes wrong, you can restore every workflow and credential in a minute.

Create the backup script at ~/n8n/backup.sh:

#!/bin/bash # Backup the n8n PostgreSQL database BACKUP_DIR="/root/n8n/backups" DATE=$(date +%Y%m%d_%H%M) mkdir -p $BACKUP_DIR # Database dump docker exec n8n_postgres pg_dump -U n8n n8n \ | gzip > $BACKUP_DIR/n8n_db_$DATE.sql.gz # Backup n8n data (encryption key, custom nodes) tar -czf $BACKUP_DIR/n8n_data_$DATE.tar.gz \ -C /root/n8n n8n_data .env # Delete backups older than 30 days find $BACKUP_DIR -name "*.gz" -mtime +30 -delete echo "Backup completed: $DATE"

Make the script executable and add it to cron — daily at 3:00 AM:

# Make the script executable chmod +x ~/n8n/backup.sh # Add to cron (daily at 3:00 AM) (crontab -l 2>/dev/null; echo "0 3 * * * /root/n8n/backup.sh") | crontab - # Verify the cron job was added crontab -l

Verify everything works

Open https://n8n.yourdomain.com in your browser. You'll see a registration screen — create an account (this is your local account on your own server, not tied to n8n cloud).

Once logged in, run through this quick check:

  • Create a test workflow: add a Manual Trigger → Set Node → change some data → hit Execute
  • Test a webhook: create a Webhook Trigger, copy the URL, open it in a new tab — you should get a response
  • Check the timezone: add a Schedule Trigger and make sure the time matches Europe/Kyiv
  • Activate the free license: Settings → Community — click Activate (unlocks additional features)
You made it

Your n8n is ready to work. You can now build workflows, wire up Telegram bots, set up automated order processing — and everything else covered in our previous article.

How to update n8n

n8n ships updates regularly — new nodes, AI features, fixes. Updating is trivial:

cd ~/n8n # Pull the new version and restart docker compose pull docker compose up -d # Check the version docker compose logs n8n | head -5
Before you update

Always run a backup first: bash ~/n8n/backup.sh. In rare cases, a new release can ship breaking changes.

Frequently asked questions

How much does a VPS for n8n cost?

From $3–5/mo for light workflows (Hetzner CX11, DigitalOcean Basic). For production with AI and PostgreSQL, we recommend $5–12/mo (2 vCPU, 4 GB RAM). Self-hosted n8n Community Edition is completely free — you only pay for the server.

Do I need to know how to code?

No. The whole install is copy-pasting commands from this guide. And n8n itself is a visual builder — you connect blocks with your mouse, no code required.

Why is HTTPS required?

Without HTTPS, OAuth2 integrations (Google Sheets, Gmail, Slack), external webhooks, and secure cookies won't work. In practice, n8n without HTTPS is only good for local development, not production.

What if n8n doesn't start?

Check the logs: docker compose logs n8n. The most common errors: wrong PostgreSQL password (compare .env and docker-compose.yml), port 5678 is used by another process, or wrong permissions on the n8n_data folder (fix with: chown -R 1000:1000 n8n_data).

How do I migrate n8n to another server?

Copy three things to the new server: the .env file with the same N8N_ENCRYPTION_KEY, the postgres_data folder, and the n8n_data folder. Run docker compose up -d — everything will work as before.