These were the remaining `uv init` residue alongside the already-removed main.py stub — not part of the build/deploy path. Also drops the now-stale 'leftover uv-init artifacts' note from README.md since the files are gone.
99 lines
4.3 KiB
Markdown
99 lines
4.3 KiB
Markdown
# n8n
|
|
|
|
[n8n](https://n8n.io/) workflow automation deployment for the homelab.
|
|
Single-container stack with external persistent volume for workflows,
|
|
credentials, and execution history.
|
|
|
|
## Service
|
|
|
|
| Service | Image | Container | Host port |
|
|
|---------|------------------------------------|-----------|-----------|
|
|
| `n8n` | `docker.n8n.io/n8nio/n8n:latest` | `n8n` | 5678 |
|
|
|
|
n8n is reached at `http://<host>:5678/` (or via the Traefik path-prefix
|
|
route — see "Routing" below). Webhooks fire to `WEBHOOK_URL` per
|
|
`.env`.
|
|
|
|
## Run it
|
|
|
|
```bash
|
|
docker compose up -d
|
|
docker compose logs -f n8n
|
|
```
|
|
|
|
## Configuration — `.env`-driven
|
|
|
|
All knobs are in `.env` (gitignored). Required keys (names only — values
|
|
live in the file on the host):
|
|
|
|
| Key | Purpose |
|
|
|--------------------------------|---------------------------------------------------------|
|
|
| `N8N_HOST` | Public hostname (Tailscale magic-DNS in this homelab) |
|
|
| `N8N_PORT` | Listen port (5678) |
|
|
| `N8N_PROTOCOL` | `https` when fronted by Traefik / Tailscale |
|
|
| `N8N_PATH` | URL path prefix (`/n8n/` when using the Traefik route) |
|
|
| `GENERIC_TIMEZONE` | e.g. `America/New_York` |
|
|
| `N8N_SECURE_COOKIE` | `true` for HTTPS-fronted deployments |
|
|
| `N8N_BASIC_AUTH_ACTIVE` | `true` / `false` |
|
|
| `N8N_BASIC_AUTH_USER` | Basic-auth username |
|
|
| `N8N_BASIC_AUTH_PASSWORD` | Basic-auth password (rotate via .env, not via UI) |
|
|
| `WEBHOOK_URL` | Outward-facing webhook base (must match real ingress) |
|
|
| `PBS_*` | Workflow-side integration creds (Google Chat, Portainer, monitor base URLs, healer webhook) |
|
|
|
|
Rotate any of these by editing `.env` and restarting:
|
|
`docker compose up -d` (compose will recreate the container).
|
|
|
|
**Never commit `.env`** — it's listed in `.gitignore` for this reason.
|
|
If you need a checked-in template, create `.env.example` with the keys
|
|
but no values.
|
|
|
|
## Persistence — external volume
|
|
|
|
```
|
|
volumes:
|
|
n8n_data:
|
|
name: n8n_server_n8n_data
|
|
external: true
|
|
```
|
|
|
|
The volume is **external** with an explicit `name:` (`n8n_server_n8n_data`)
|
|
that pins it to the data originally created by a prior compose stack
|
|
called `n8n_server`. Don't remove the `name:` override — Docker would
|
|
create a new empty volume and n8n would boot with no workflows,
|
|
credentials, or history.
|
|
|
|
Backup: `docker run --rm -v n8n_server_n8n_data:/data -v $PWD:/backup
|
|
alpine tar czf /backup/n8n-backup-$(date +%F).tgz -C /data .`
|
|
|
|
## Routing (homelab-specific)
|
|
|
|
In this homelab, n8n is reachable two ways depending on which compose
|
|
state you're running:
|
|
|
|
- **Direct host port** (current working-copy default): browse to
|
|
`http://<host>:5678/`. Tailscale-only reachable because the host
|
|
itself is Tailscale-fronted.
|
|
- **Through Traefik** (committed state): path-prefix
|
|
`/n8n` on `us-test-authy.taila7f44e.ts.net`, with a separate
|
|
`/n8n/api` route that bypasses the Authelia middleware so API-key
|
|
clients don't double-auth. If you re-enable this, the container
|
|
needs to be on the external `traefik` network and the labels
|
|
block from the committed `compose.yml` should be restored.
|
|
|
|
## Gotchas
|
|
|
|
- **`:latest` image tag.** No pin. n8n minor releases occasionally
|
|
require workflow re-saves or credential re-entry; check release
|
|
notes before pulling.
|
|
- **`WEBHOOK_URL` must match ingress.** If you put n8n behind Traefik
|
|
at `/n8n/`, `WEBHOOK_URL` must be `https://<host>/n8n/` — n8n bakes
|
|
that URL into the webhooks it shows in the UI, so a mismatch
|
|
silently breaks third-party integrations even though the workflow
|
|
page looks right.
|
|
- **The basic-auth password lives in `.env`.** Don't change it through
|
|
the UI — there's nothing to change in the UI; it's enforced by the
|
|
HTTP layer from `N8N_BASIC_AUTH_PASSWORD`.
|
|
- **Don't commit `.env`.** Contains real PBS integration credentials
|
|
(Portainer API key, Google Chat webhook, healer webhook). The
|
|
`.gitignore` already excludes it; keep it that way.
|