How to Install n8n (Self-Hosted Automation Like Zapier, on Your Server)

"When this happens, do that" — a new file in Nextcloud posts to Telegram, a form submission creates a Gitea issue, a daily summary of Uptime Kuma alerts lands in your inbox. n8n is a visual workflow builder with hundreds of connectors, and self-hosted it costs nothing per run. It's also a fine way to glue the apps in this series together.
Quick reference
| Task | What |
|---|---|
| Folder | ~/docker/n8n/compose.yaml |
| Web | http://server-ip:5678 |
| Must set | N8N_HOST, WEBHOOK_URL, N8N_ENCRYPTION_KEY |
| Data | ./data (SQLite and credentials) |
| Webhooks from outside | through the reverse proxy with HTTPS |
| Update | docker compose pull && up -d |
1. The compose file
mkdir -p ~/docker/n8n && cd ~/docker/n8n
nano compose.yaml
services:
n8n:
image: docker.n8n.io/n8nio/n8n
container_name: n8n
ports:
- "127.0.0.1:5678:5678"
environment:
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
GENERIC_TIMEZONE: Europe/London
TZ: Europe/London
N8N_SECURE_COOKIE: "true"
volumes:
- ./data:/home/node/.n8n
restart: unless-stopped
.env:
N8N_ENCRYPTION_KEY=a-long-random-string
The encryption key protects every stored password and API token; keep it with your backups or the credentials are unrecoverable. If you'll only use n8n on the LAN without a proxy, change the port line to "5678:5678", N8N_PROTOCOL to http, WEBHOOK_URL to http://192.168.1.50:5678/ and N8N_SECURE_COOKIE to "false".
docker compose up -d
2. Reverse proxy
Add n8n.example.com → 127.0.0.1:5678 in Nginx with the WebSocket lines (tutorial 28) and a certificate. Open https://n8n.example.com, create the owner account.
3. A first workflow: RSS to Telegram
- Add first step → On a schedule: every hour.
- + → RSS Read: URL of a feed you follow.
- + → Telegram → Send a message: create a credential with your bot token (the same bot from Uptime Kuma works), chat ID, and for the text drag title and link from the left panel into the box.
- Test workflow — a message arrives. Toggle Active. Done: new posts ping you hourly.
Everything else is variations: a trigger node, some processing, an action node.
4. Useful triggers for a home server
- Webhook — anything that can make an HTTP request (Uptime Kuma notifications, Home Assistant, a script's curl) can start a workflow. The URL is shown on the node; it's why WEBHOOK_URL must be your public address.
- Schedule — cron in a form.
- IMAP Email — act on incoming mail.
- Local file trigger — mount a folder (- /mnt/data/inbox:/files) and react when a file appears.
- SSH / Execute Command — run a command on the server as a step (back up, restart a container, fetch df -h).
5. Credentials
Each service's login lives under Credentials, encrypted with your key, and is picked from a dropdown in nodes. OAuth services (Google, Microsoft) need the callback URL n8n shows you — which again must be the public https address.
Keeping it tidy
- Name workflows; after twenty you'll be grateful.
- Settings → Executions: keep failed runs for a week so you can see what went wrong.
- Export important workflows as JSON (⋯ → Download) into Gitea.
- Back up ./data and the encryption key together.
Troubleshooting
Webhook URL shows localhost. WEBHOOK_URL isn't set, or n8n was started before you set it. up -d after changing.
"Secure cookie" error in the browser. You're on plain http with N8N_SECURE_COOKIE: "true". Set it to false for LAN use, or use the https proxy.
Workflow runs by hand, never on schedule. It isn't Active (toggle top right), or the time zone makes it run when you're not watching.
Credentials unusable after a restore. Different N8N_ENCRYPTION_KEY. Restore the original key.
Wrapping up
One container, three URL settings, an encryption key you back up, HTTPS through the proxy for webhooks. The first workflow takes ten minutes; the hundredth takes five. Your apps start talking to each other and the server starts doing jobs you used to.
