# Self-Hosting with Docker Compose — AI Automation with n8n

Source: https://www.geekswithgeeks.com/en/n8n-ai-automation/ops-self-hosting

> Run n8n on a server with persistent data, a database and the right environment variables.

## What production needs

For anything beyond a demo, run n8n with a **persistent volume**, a **PostgreSQL** database instead of the default SQLite for heavier use, the public **WEBHOOK_URL** and timezone set, **HTTPS** through a reverse proxy, and a fixed **N8N_ENCRYPTION_KEY**. For high volume, n8n has a queue mode with separate workers. Always check the official hosting docs for current settings.

## From laptop to server

Run n8n with persistent storage and HTTPS, and manage workflows like code.

![Three steps: run, protect, maintain.](assets/figures/n8n-ai-automation/section-7-map.svg) — Figure 7.1 — Run, protect and maintain.

## A minimal Compose file

Keep real secrets in an `.env` file that is not committed. Variable names are from the n8n docs at the time of writing; verify them for your version.

```yaml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    ports: ["5678:5678"]
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - WEBHOOK_URL=https://n8n.example.com/
      - GENERIC_TIMEZONE=Asia/Kolkata
    volumes:
      - n8n_data:/home/node/.n8n
    restart: unless-stopped
volumes:
  n8n_data:
```

## Set WEBHOOK_URL behind a proxy

Behind a reverse proxy n8n does not know its public address. Without WEBHOOK_URL, the webhook URLs it shows are wrong, and external services will call addresses that do not exist.

**Quiz:** Why set WEBHOOK_URL when n8n is behind a reverse proxy?

- [ ] It is only cosmetic
- [ ] To speed up the database
- [ ] To disable authentication
- [x] So generated webhook URLs use the correct public address

*Answer:* So generated webhook URLs use the correct public address. n8n cannot guess its external address behind a proxy, so you tell it.
