Add notification image proxy, expand README, fix compose env-file handling
- Proxy notification image_url server-side (GET /api/v1/notifications/:id/image) instead of loading it directly in the browser, so LAN-only image sources (e.g. Frigate snapshots) still load for clients off that network - Tighten CSP img-src to 'self' now that images are same-origin - Update threat model / architecture docs to match the new image-fetch design - Expand README: Home Assistant quick-start, Pocket ID/OIDC walkthrough, Pangolin note, backup automation, new troubleshooting entries - Fix docker-compose.yml: document that --env-file .env must be passed explicitly (Compose's implicit .env lookup was unreliable with -f from a different directory) - Fix image-proxy tests to build a real session cookie (AUTH_MODE=oidc applies inside the test container too, so requireAuth needs one)
This commit is contained in:
1 parent
a82c29a69d
commit
079013730b
10 files changed
+332
-32
No files matched your search
@@ -34,6 +34,49 @@ the actual provider details (issuer URL, client ID/secret, redirect URL,
|
||||
scopes) are editable any time from **Admin → Auth** — no further env file
|
||||
edits or restarts needed for those.
|
||||
|
||||
### Setting up OIDC with Pocket ID
|
||||
|
||||
Notizarr handles the OIDC login flow itself (Authorization Code + PKCE) —
|
||||
it does not delegate auth to the reverse proxy via trusted headers, so
|
||||
Pangolin (or whatever sits in front of it) only needs to forward HTTP, no
|
||||
auth injection.
|
||||
|
||||
1. In Pocket ID, create a new OIDC client:
|
||||
- **Name**: `Notizarr`
|
||||
- **Client's start URL**: your public Notizarr URL (e.g.
|
||||
`https://notify.example.com`)
|
||||
- **Callback URLs**: `https://notify.example.com/api/v1/auth/oidc/callback`
|
||||
— this exact path is hardcoded server-side
|
||||
([apps/server/src/modules/auth/routes.ts](apps/server/src/modules/auth/routes.ts)),
|
||||
it has to match exactly
|
||||
- **Public Client**: **off** — Notizarr is a confidential/server-side
|
||||
client and needs a client secret. Leaving this on means Pocket ID
|
||||
never issues one.
|
||||
- **PKCE**: **on** — Notizarr always sends a PKCE challenge regardless,
|
||||
so this just means Pocket ID requires it too
|
||||
- Everything else (logout callback URLs, skip consent, logo) is
|
||||
optional/cosmetic
|
||||
2. Save, then open the client back up and find its **Referenser** /
|
||||
Credentials tab — client secrets in Pocket ID live there, not on the
|
||||
creation form, and are only shown once when generated.
|
||||
3. In Notizarr, go to **Admin → Auth** and fill in the Issuer URL, Client
|
||||
ID, Client Secret, Redirect URL (same value as the Callback URL above),
|
||||
and Scopes (`openid profile email`). Save.
|
||||
4. Set `AUTH_MODE=oidc` in `.env` and restart the container — this one
|
||||
setting is the only part that still needs a restart, since it changes
|
||||
which routes the server exposes at boot. Everything from step 3 takes
|
||||
effect immediately without one.
|
||||
5. Log in once. If you'd previously been running `AUTH_MODE=disabled`, its
|
||||
implicit "Local Admin" user already claimed the bootstrap-admin slot
|
||||
(the very first user *ever created*), so your real login likely comes
|
||||
back as a normal user — see the "First-ever login should be an admin
|
||||
but isn't" entry under [Troubleshooting](#troubleshooting) to fix that.
|
||||
|
||||
**Pangolin**: point it at the web listener only (`notizarr:8080` on the
|
||||
same Docker network, or the host's `PUBLIC_BASE_URL`) — never at `:8081`,
|
||||
the LAN-only ingestion listener. See [Unraid deployment](#unraid-deployment-production)
|
||||
below.
|
||||
|
||||
All mutating requests on the web listener (`POST`/`PUT`/`PATCH`/`DELETE`
|
||||
under `/api/`) require a `X-Requested-With: notizarr` header — this is the
|
||||
CSRF defense described in the threat model, not optional. The ingestion
|
||||
@@ -74,7 +117,7 @@ use the dev Docker Compose stack below, which includes one.
|
||||
## Local development via Docker
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml up -d
|
||||
docker compose --env-file .env -f docker/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
Brings up `notizarr-postgres-dev` and `notizarr-dev` (hot-reload: the repo
|
||||
@@ -91,7 +134,7 @@ anonymous `node_modules` volumes in one go, or the container keeps running
|
||||
against the old, pre-change `node_modules`:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml up -d --build --force-recreate -V
|
||||
docker compose --env-file .env -f docker/docker-compose.yml up -d --build --force-recreate -V
|
||||
```
|
||||
|
||||
Override host ports if they also collide, either inline or via a
|
||||
@@ -99,7 +142,7 @@ Override host ports if they also collide, either inline or via a
|
||||
|
||||
```bash
|
||||
HOST_PORT_WEB=28080 HOST_PORT_INGEST=28081 HOST_PORT_PG=25432 \
|
||||
docker compose -f docker/docker-compose.yml up -d
|
||||
docker compose --env-file .env -f docker/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
Check health:
|
||||
@@ -115,7 +158,7 @@ this writes real PNGs into `apps/web/public/icons/`, committed to the repo
|
||||
rather than regenerated on every build):
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml exec notizarr pnpm --filter @notizarr/web generate-icons
|
||||
docker compose --env-file .env -f docker/docker-compose.yml exec notizarr pnpm --filter @notizarr/web generate-icons
|
||||
```
|
||||
|
||||
## Unraid deployment (production)
|
||||
@@ -242,6 +285,14 @@ work the same way.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **`docker compose ... exec/logs/etc` fails with `required variable
|
||||
POSTGRES_PASSWORD is missing a value`.** Compose's implicit `.env`
|
||||
lookup when the compose file is passed via `-f docker/docker-compose.yml`
|
||||
from the repo root doesn't reliably resolve to the repo root's `.env` —
|
||||
it's ambiguous/version-dependent, and got this wrong in practice. Always
|
||||
pass `--env-file .env` explicitly, on every invocation against this
|
||||
file, not just `up` (see the comment at the top of
|
||||
`docker/docker-compose.yml`).
|
||||
- **A `docker compose up -d --build` didn't pick up a dependency change.**
|
||||
Anonymous `node_modules` volumes are reused by default — add `-V
|
||||
--force-recreate` (see [Local development via
|
||||
|
||||
Reference in new issue
Block a user