# Self-Host n8n on a Hostinger VPS: Docker Compose, Caddy HTTPS, Backups

URL: https://www.savemores.store/vps/self-host-n8n
Author: Mr. Ahmed · Published 2026-10-17 · Updated 2026-10-17 · VPS & deployment

## Short answer

- Self-hosted n8n costs only the server, with no per-execution charges, under n8n's Sustainable Use License for internal use.
- KVM 1 (1 vCPU, 4 GB RAM) handles personal and small-team workflows on SQLite; KVM 2 (2 vCPU, 8 GB) suits Postgres or heavy file and AI work.
- Hostinger's n8n OS template is the fastest route; Docker Compose with Caddy gives you automatic Let's Encrypt HTTPS and full control.
- Back up `N8N_ENCRYPTION_KEY` off the server, because without it restored credentials cannot be decrypted.
- Create the owner account immediately after first launch, since whoever reaches the URL first can claim the instance.

## Why run n8n yourself

n8n is a workflow automation tool in the same category as Zapier and Make: you wire apps together, add logic and let it run. The hosted product bills by workflow executions. Self-hosted, you pay a flat price for the server and run as many executions as it can cope with.

Licensing is worth thirty seconds. n8n ships under its Sustainable Use License, which permits self-hosting for your own and your company's internal use. If you intend to sell n8n to others as a service, read the license before you build a business on it.

## Sizing the server

n8n on its own is light. Workflows that handle files, call AI models or loop over large lists are what eat memory. KVM 1 starts from $4.99/mo on a 48-month term before the coupon.

| Plan | Fits |
| --- | --- |
| KVM 1 (1 vCPU, 4 GB) | Personal automations and a small team's workflows on the default SQLite database |
| KVM 2 (2 vCPU, 8 GB) | Many active workflows, Postgres next to n8n, heavier file or AI processing |
| KVM 4 and up | Queue mode with Redis and multiple workers |

## Route 1: Hostinger's n8n template

Hostinger offers n8n as a VPS OS template. Pick it when you create the server, or reinstall an existing one from the VPS settings, and n8n comes up in Docker without any command-line work.

For most people that is enough. Take route 2 if you want to understand every moving part, run n8n alongside other apps, or decide exactly which version you are on.

> From the bench: Reinstalling a VPS with a template wipes the disk. If anything on the server matters, take a snapshot first. I have never regretted a snapshot; I have regretted skipping one.

## Route 2: Docker Compose with Caddy for HTTPS

Start with a plain Ubuntu 24.04 server you have already [hardened](https://www.savemores.store/vps/secure-new-vps), and an A record for a subdomain such as `n8n.example.com` pointing at it ([how to add one](https://www.savemores.store/vps/point-domain-dns)). Caddy handles HTTPS, requesting and renewing the Let's Encrypt certificate itself.

1. Install Docker, add your user to the docker group, then log out and back in.
2. Create `~/n8n` and generate a random 32-byte hex string for the encryption key.
3. Write `.env`, `compose.yaml` and `Caddyfile` as shown below.
4. Start the stack and watch the logs until Caddy reports a certificate and n8n reports it is ready.

Install Docker and create the project folder:

```bash
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER   # log out and back in after this

mkdir -p ~/n8n && cd ~/n8n
openssl rand -hex 32   # copy this; it becomes N8N_ENCRYPTION_KEY
```

~/n8n/.env

```bash
DOMAIN=n8n.example.com
N8N_ENCRYPTION_KEY=paste-the-random-string-here
GENERIC_TIMEZONE=Asia/Karachi
```

~/n8n/compose.yaml

```yaml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: unless-stopped
    environment:
      - N8N_HOST=${DOMAIN}
      - N8N_PROTOCOL=https
      - N8N_PORT=5678
      - WEBHOOK_URL=https://${DOMAIN}/
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - TZ=${GENERIC_TIMEZONE}
    volumes:
      - n8n_data:/home/node/.n8n

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      - DOMAIN=${DOMAIN}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data

volumes:
  n8n_data:
  caddy_data:
```

~/n8n/Caddyfile

```text
{$DOMAIN} {
    reverse_proxy n8n:5678
}
```

Start it and follow the logs:

```bash
docker compose up -d
docker compose logs -f
```

> From the bench: Look at what the n8n service does not have: a `ports:` section. Caddy reaches it over the private Docker network, so HTTPS through Caddy is the only way in. That sidesteps the problem of Docker-published ports bypassing UFW entirely, and it is how I would lay out any app behind a proxy.

## First login, and the key you must not lose

Browse to `https://n8n.example.com` and create the owner account right away. Until an owner exists, the first person to reach the URL can claim the instance.

Every saved credential is encrypted with `N8N_ENCRYPTION_KEY`. Store a copy somewhere safe that is not this server. Lose it and a restored backup cannot decrypt any of your API keys or passwords, so every credential has to be entered again by hand.

## Updating

n8n ships releases frequently. Read the release notes for breaking changes, take a backup, then pull and restart. If you prefer to upgrade on your own schedule, pin a specific version tag in place of `latest`.

```bash
cd ~/n8n
docker compose pull
docker compose up -d
docker image prune -f
```

## Backups

Workflows, credentials and execution history (in SQLite) all live in the `n8n_data` volume. Archive it on a schedule and copy the archive off the server.

Archive the volume into the current folder:

```bash
docker run --rm \
  -v n8n_n8n_data:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/n8n-$(date +%F).tar.gz -C /data .
```

Or export workflows as JSON, which is convenient for Git:

```bash
docker compose exec n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json
```

> From the bench: Compose prefixes volume names with the project folder, so `n8n_data` inside a folder named `n8n` becomes `n8n_n8n_data`. Run `docker volume ls` and check the real name before you schedule the backup; a cron job pointed at the wrong volume will happily archive an empty directory every night.

## Verify it worked

Check each of these after the first start and again after every update.

- The owner account exists and you can log in.
- A test webhook shows your public `https://` URL, not localhost.
- Your encryption key is stored somewhere other than this server.

```bash
cd ~/n8n
docker compose ps                 # expect: n8n and caddy both running
curl -I https://n8n.example.com   # expect: an HTTP response over HTTPS, no certificate error
docker volume ls                  # expect: n8n_n8n_data and n8n_caddy_data
ls -lh n8n-*.tar.gz               # after a backup: a non-empty archive
```

## FAQ

### Is self-hosted n8n free?

Yes for internal use. The Community Edition is free to self-host under n8n's Sustainable Use License, so you pay only for the server, though some enterprise features need a paid license.

### Will n8n run on KVM 1?

Yes. KVM 1's 4 GB of RAM is plenty for personal and small-team automations; move to KVM 2 when you add Postgres or run heavy file or AI workflows.

### Why do my webhooks show localhost URLs?

WEBHOOK_URL is missing, or n8n started before you set it. Set it to your public https URL with a trailing slash and recreate the container with docker compose up -d.

### Does the WEBHOST2026 coupon apply to VPS plans?

Yes. WEBHOST2026 takes an extra 20% off eligible VPS plans, and the 24 and 48-month terms carry the lowest monthly price.
