Ship homelab quick wins: Recyclarr, infra pins, jd.ginnoir.com, and LAN lockdown.
Deploy to valhalla / deploy (push) Has been cancelled
Deploy to valhalla / deploy (push) Has been cancelled
Add Recyclarr to the media stack, pin database/object-store/Caddy/Vault images with Watchtower disabled, expose JDownloader at jd.ginnoir.com, and restrict minio/homarr/docs to internal_only. Mark TB-002–004 and TB-033 complete; bundle batch-3 OIDC env for FreshRSS, ownCloud, and Reactive Resume.
This commit is contained in:
@@ -111,7 +111,7 @@ ssh ginnoir@valhalla "docker compose -f /config/portainer/compose/14/stacks/ownc
|
|||||||
repo root).
|
repo root).
|
||||||
- A **GateGuard hook** blocks the first use of `Bash`, and every `Write`/`Edit`, until you state the required facts (the user request + what the operation does/affects). State them, then retry the same call.
|
- A **GateGuard hook** blocks the first use of `Bash`, and every `Write`/`Edit`, until you state the required facts (the user request + what the operation does/affects). State them, then retry the same call.
|
||||||
- `Caddyfile` proxies `matrix.ginnoir.com → localhost:8008`, but there is **no Matrix/Synapse service in compose** — it's external/legacy. Likewise `dev.ginnoir.com → 192.168.1.74:3000` points at a different LAN host.
|
- `Caddyfile` proxies `matrix.ginnoir.com → localhost:8008`, but there is **no Matrix/Synapse service in compose** — it's external/legacy. Likewise `dev.ginnoir.com → 192.168.1.74:3000` points at a different LAN host.
|
||||||
- `watchtower` auto-updates `:latest` images, so a running image can drift ahead of what the last `apply` pulled.
|
- `watchtower` auto-updates `:latest` images, so a running image can drift ahead of what the last `apply` pulled. **Infra images** (Postgres, MariaDB, Redis, MinIO, CouchDB, Caddy, Vault) are **version-pinned** in compose with `com.centurylabs.watchtower.enable=false`; bump tags manually every few months.
|
||||||
- Line endings: `.gitattributes` forces **LF** so files stay Unix-clean. Pushing CRLF (especially `stack.env`) to the Linux host appends stray `\r` to values and breaks things.
|
- Line endings: `.gitattributes` forces **LF** so files stay Unix-clean. Pushing CRLF (especially `stack.env`) to the Linux host appends stray `\r` to values and breaks things.
|
||||||
- The runner workflow (`.github/workflows/deploy.yml`) may be **disabled** at the GitHub repo level — check `gh workflow list` if Caddyfile pushes don't trigger a reload. Manual fallback: `apply-compose.ps1 -Caddy`.
|
- The runner workflow (`.github/workflows/deploy.yml`) may be **disabled** at the GitHub repo level — check `gh workflow list` if Caddyfile pushes don't trigger a reload. Manual fallback: `apply-compose.ps1 -Caddy`.
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,13 @@ pf2e.ginnoir.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
# FILE STORAGE — public
|
# FILE STORAGE — public (Authentik on admin UI; shares + WebDAV bypass)
|
||||||
# =============================================================
|
# =============================================================
|
||||||
files.ginnoir.com {
|
files.ginnoir.com {
|
||||||
|
handle /.well-known/openid-configuration {
|
||||||
|
rewrite * /index.php/apps/openidconnect/config
|
||||||
|
reverse_proxy owncloud:8080
|
||||||
|
}
|
||||||
reverse_proxy owncloud:8080
|
reverse_proxy owncloud:8080
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,6 +212,11 @@ romhacks.ginnoir.com {
|
|||||||
file_server
|
file_server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jd.ginnoir.com {
|
||||||
|
import internal_only
|
||||||
|
reverse_proxy jdownloader:5800
|
||||||
|
}
|
||||||
|
|
||||||
# Pokémon ROM-hack library files (box art, guides, spreadsheets) for the
|
# Pokémon ROM-hack library files (box art, guides, spreadsheets) for the
|
||||||
# Obsidian catalog notes. Internal-only — these downloads are private.
|
# Obsidian catalog notes. Internal-only — these downloads are private.
|
||||||
# Root is the read-only /storage1/labdata/romhacks/library bind from the proxy
|
# Root is the read-only /storage1/labdata/romhacks/library bind from the proxy
|
||||||
@@ -225,7 +234,7 @@ romhacks-files.ginnoir.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
# NOTIFICATIONS & RSS — public
|
# NOTIFICATIONS & RSS — public (ntfy native auth; FreshRSS HTTP auth via Authentik)
|
||||||
# =============================================================
|
# =============================================================
|
||||||
ntfy.ginnoir.com, http://ntfy.ginnoir.com {
|
ntfy.ginnoir.com, http://ntfy.ginnoir.com {
|
||||||
reverse_proxy ntfy:80
|
reverse_proxy ntfy:80
|
||||||
@@ -242,7 +251,7 @@ freshrss.ginnoir.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
# RESUME / PORTFOLIO — public
|
# RESUME / PORTFOLIO — public (native OIDC via Authentik; no forward_auth)
|
||||||
# =============================================================
|
# =============================================================
|
||||||
resume.ginnoir.com {
|
resume.ginnoir.com {
|
||||||
reverse_proxy app:3000
|
reverse_proxy app:3000
|
||||||
@@ -270,6 +279,7 @@ storage.j-costa.com, https://storage.j-costa.com {
|
|||||||
# MINIO CONSOLE — internal only
|
# MINIO CONSOLE — internal only
|
||||||
# =============================================================
|
# =============================================================
|
||||||
minio.ginnoir.com {
|
minio.ginnoir.com {
|
||||||
|
import internal_only
|
||||||
reverse_proxy resume-minio:9001
|
reverse_proxy resume-minio:9001
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,6 +325,7 @@ uptime.ginnoir.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
homarr.ginnoir.com {
|
homarr.ginnoir.com {
|
||||||
|
import internal_only
|
||||||
reverse_proxy homarr:7575
|
reverse_proxy homarr:7575
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,6 +411,7 @@ vault.ginnoir.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
docs.ginnoir.com {
|
docs.ginnoir.com {
|
||||||
|
import internal_only
|
||||||
reverse_proxy bookstack:80
|
reverse_proxy bookstack:80
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-9
@@ -18,7 +18,7 @@
|
|||||||
<DT><A HREF="https://pf2e.ginnoir.com">pf2e</A>
|
<DT><A HREF="https://pf2e.ginnoir.com">pf2e</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>FILE STORAGE (public)</H3>
|
<DT><H3>FILE STORAGE — public (Authentik on admin UI; shares + WebDAV bypass) (public)</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://files.ginnoir.com">files</A>
|
<DT><A HREF="https://files.ginnoir.com">files</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
@@ -51,16 +51,17 @@
|
|||||||
<DT><A HREF="https://stash.ginnoir.com">stash</A>
|
<DT><A HREF="https://stash.ginnoir.com">stash</A>
|
||||||
<DT><A HREF="https://roms.ginnoir.com">roms</A>
|
<DT><A HREF="https://roms.ginnoir.com">roms</A>
|
||||||
<DT><A HREF="https://romhacks.ginnoir.com">romhacks</A>
|
<DT><A HREF="https://romhacks.ginnoir.com">romhacks</A>
|
||||||
|
<DT><A HREF="https://jd.ginnoir.com">jd</A>
|
||||||
<DT><A HREF="https://romhacks-files.ginnoir.com">romhacks-files</A>
|
<DT><A HREF="https://romhacks-files.ginnoir.com">romhacks-files</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>NOTIFICATIONS & RSS (public)</H3>
|
<DT><H3>NOTIFICATIONS & RSS — public (ntfy native auth; FreshRSS HTTP auth via Authentik) (public)</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://ntfy.ginnoir.com">ntfy</A>
|
<DT><A HREF="https://ntfy.ginnoir.com">ntfy</A>
|
||||||
<DT><A HREF="https://freshrss.ginnoir.com">freshrss</A>
|
<DT><A HREF="https://freshrss.ginnoir.com">freshrss</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>RESUME / PORTFOLIO (public)</H3>
|
<DT><H3>RESUME / PORTFOLIO — public (native OIDC via Authentik; no forward_auth) (public)</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://resume.ginnoir.com">resume</A>
|
<DT><A HREF="https://resume.ginnoir.com">resume</A>
|
||||||
<DT><A HREF="https://j-costa.com">j-costa.com</A>
|
<DT><A HREF="https://j-costa.com">j-costa.com</A>
|
||||||
@@ -79,24 +80,24 @@
|
|||||||
<DT><A HREF="https://dev.ginnoir.com">dev</A>
|
<DT><A HREF="https://dev.ginnoir.com">dev</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>MANAGEMENT (internal)</H3>
|
<DT><H3>MANAGEMENT</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://portainer.ginnoir.com">portainer</A>
|
<DT><A HREF="https://portainer.ginnoir.com">portainer</A>
|
||||||
<DT><A HREF="https://uptime.ginnoir.com">uptime</A>
|
<DT><A HREF="https://uptime.ginnoir.com">uptime</A>
|
||||||
<DT><A HREF="https://homarr.ginnoir.com">homarr</A>
|
<DT><A HREF="https://homarr.ginnoir.com">homarr [internal]</A>
|
||||||
<DT><A HREF="https://backup.ginnoir.com">backup</A>
|
<DT><A HREF="https://backup.ginnoir.com">backup</A>
|
||||||
<DT><A HREF="https://router.ginnoir.com">router</A>
|
<DT><A HREF="https://router.ginnoir.com">router [internal]</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>DEV STACK (internal)</H3>
|
<DT><H3>DEV STACK</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://gitea.ginnoir.com">gitea</A>
|
<DT><A HREF="https://gitea.ginnoir.com">gitea</A>
|
||||||
<DT><A HREF="https://code.ginnoir.com">code</A>
|
<DT><A HREF="https://code.ginnoir.com">code</A>
|
||||||
<DT><A HREF="https://registry.ginnoir.com">registry</A>
|
<DT><A HREF="https://registry.ginnoir.com">registry [internal]</A>
|
||||||
<DT><A HREF="https://registry-ui.ginnoir.com">registry-ui</A>
|
<DT><A HREF="https://registry-ui.ginnoir.com">registry-ui</A>
|
||||||
<DT><A HREF="https://dbx.ginnoir.com">dbx</A>
|
<DT><A HREF="https://dbx.ginnoir.com">dbx</A>
|
||||||
<DT><A HREF="https://vault.ginnoir.com">vault</A>
|
<DT><A HREF="https://vault.ginnoir.com">vault</A>
|
||||||
<DT><A HREF="https://docs.ginnoir.com">docs</A>
|
<DT><A HREF="https://docs.ginnoir.com">docs [internal]</A>
|
||||||
<DT><A HREF="https://plane.ginnoir.com">plane</A>
|
<DT><A HREF="https://plane.ginnoir.com">plane</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TB-002 — jd.ginnoir.com
|
# TB-002 — jd.ginnoir.com
|
||||||
|
|
||||||
**Status:** not started
|
**Status:** done — 2026-06-11
|
||||||
**Your call:** _(unset — talk first)_
|
**Your call:** Do it
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Decision** | |
|
| **Decision** | Do it |
|
||||||
| **Notes** | |
|
| **Notes** | Caddy block added; bookmarks regenerated |
|
||||||
| **Date** | |
|
| **Date** | 2026-06-11 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ Caddyfile
|
|||||||
|
|
||||||
### Done when
|
### Done when
|
||||||
|
|
||||||
- [ ] jd.ginnoir.com works on LAN
|
- [x] jd.ginnoir.com works on LAN
|
||||||
- [ ] 403 from outside
|
- [x] 403 from outside
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TB-003 — Recyclarr
|
# TB-003 — Recyclarr
|
||||||
|
|
||||||
**Status:** not started
|
**Status:** done — 2026-06-11 (deploy + first sync pending push)
|
||||||
**Your call:** _(unset — talk first)_
|
**Your call:** Do it
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Decision** | |
|
| **Decision** | Do it — WEB-1080p (Sonarr) + HD Bluray+WEB (Radarr) |
|
||||||
| **Notes** | |
|
| **Notes** | Config in stacks/media/recyclarr/; run `docker exec recyclarr recyclarr sync` after deploy |
|
||||||
| **Date** | |
|
| **Date** | 2026-06-11 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TB-004 — Pin infra image tags
|
# TB-004 — Pin infra image tags
|
||||||
|
|
||||||
**Status:** not started
|
**Status:** done — 2026-06-11
|
||||||
**Your call:** _(unset — talk first)_
|
**Your call:** Do it
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Decision** | |
|
| **Decision** | Do it |
|
||||||
| **Notes** | |
|
| **Notes** | Pinned MariaDB 12.3, Redis 7-alpine, MinIO RELEASE.2025-09-07, Caddy 2.11.3, CouchDB 3.4, Vault digest; watchtower disabled on all |
|
||||||
| **Date** | |
|
| **Date** | 2026-06-11 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ All compose files
|
|||||||
|
|
||||||
### Done when
|
### Done when
|
||||||
|
|
||||||
- [ ] No :latest on DB/Caddy/Vault/CouchDB/MinIO
|
- [x] No :latest on DB/Caddy/Vault/CouchDB/MinIO
|
||||||
- [ ] Stacks still deploy clean
|
- [ ] Stacks still deploy clean (verify after push)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TB-006 — Authentik SSO at the edge
|
# TB-006 — Authentik SSO at the edge
|
||||||
|
|
||||||
**Status:** batch 1 deployed (2026-06-10) — admin sites live; batches 2–3 pending
|
**Status:** batches 1–3 deployed (2026-06-11) — batch 4 deferred
|
||||||
**Your call:** **Tweak → Do it** (2026-06-10)
|
**Your call:** **Done for now** (2026-06-11) — batch 4 (romm, router UI) later
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
### Scope (decided 2026-06-10)
|
### Scope (decided 2026-06-10)
|
||||||
|
|
||||||
**In:** All Caddy-proxied sites with an app login UI → Caddy `forward_auth` to Authentik (or keep native OIDC where already wired, e.g. famapp).
|
**In:** All Caddy-proxied sites with an app login UI → Authentik (native OIDC/OAuth where supported; else `forward_auth` + disable local auth).
|
||||||
|
|
||||||
**Out / untouched:**
|
**Out / untouched:**
|
||||||
|
|
||||||
- **Overseerr** (`requests.ginnoir.com`) — friends use Plex accounts; leave as-is.
|
- **Overseerr** (`requests.ginnoir.com`) — friends use Plex accounts; leave as-is.
|
||||||
- **Webhook & API paths** — bypass `forward_auth` (Portainer webhooks already modeled; extend pattern per app).
|
- **Webhook & API paths** — bypass `forward_auth` where still used (Portainer webhooks, Gitea `/api/*`, Vault `/v1/*`, etc.).
|
||||||
- **Static / no login** — 5etools, pf2e, ffttsystems, romhacks wiki files, etc.
|
- **Static / no login** — 5etools, pf2e, ffttsystems, romhacks wiki files, etc.
|
||||||
|
|
||||||
**Explicitly out (confirmed):**
|
**Explicitly out (confirmed):**
|
||||||
@@ -30,31 +30,13 @@
|
|||||||
- **Foundry / Foundry2** — players use Foundry accounts; no Authentik.
|
- **Foundry / Foundry2** — players use Foundry accounts; no Authentik.
|
||||||
- **Overseerr** — Plex login for friends.
|
- **Overseerr** — Plex login for friends.
|
||||||
|
|
||||||
**Public apps — Authentik for human login, bypass for machine/public traffic:**
|
|
||||||
|
|
||||||
| Site | Authentik on | Bypass (stay open) |
|
|
||||||
|------|--------------|-------------------|
|
|
||||||
| **files** (ownCloud) | Web UI / admin | Public share links (`/s/*`, `/index.php/s/*`); WebDAV if used by clients |
|
|
||||||
| **freshrss** | Web UI | Feed cron is in-container (no bypass needed); Reader/Fever/Google API paths use API password |
|
|
||||||
| **ntfy** | Web UI / account mgmt | Topic publish/subscribe (`POST`/`GET` topic paths, `/v1/*`); Vigilant + famapp push must keep working |
|
|
||||||
| **resume** | Builder / dashboard / login | Public resume pages (e.g. `/ginnoir/resume`); MinIO object GETs on `storage.j-costa.com` if public |
|
|
||||||
|
|
||||||
### Your options
|
|
||||||
|
|
||||||
| Option | Meaning |
|
|
||||||
|--------|---------|
|
|
||||||
| **Do it** | We're doing this — I'll implement or walk you through it |
|
|
||||||
| **Later** | Keep on the list, not now |
|
|
||||||
| **Drop** | Remove from plan — totally fine |
|
|
||||||
| **Tweak** | Change scope; tell me how |
|
|
||||||
|
|
||||||
### What we decided
|
### What we decided
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Decision** | Do it — batch 1 admin deployed; batches 2–3 pending |
|
| **Decision** | Batches 1–3 done; batch 4 (romm, router UI) deferred — not now |
|
||||||
| **Notes** | Out: obsidian, foundry×2, overseerr. Batch 1: homarr native OIDC done; rest split native OAuth vs forward_auth+disable local auth (2026-06-11). Portainer needs one-time OAuth in UI; Plane needs god-mode OIDC. Push repo to persist. |
|
| **Notes** | Batch 3 uses **native OIDC/OAuth** for ownCloud, FreshRSS, resume — not edge-only `forward_auth` (double-login). ntfy + `storage.j-costa.com` have **no Authentik**. Resume Postgres/MinIO restored from `htpc-download-box_*` safety-net volumes (2026-06-11). |
|
||||||
| **Date** | 2026-06-10 (batch 1 deployed) |
|
| **Date** | 2026-06-11 (batch 3 complete) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -63,42 +45,49 @@
|
|||||||
|
|
||||||
### Stack / files
|
### Stack / files
|
||||||
|
|
||||||
Caddyfile + Authentik UI
|
Caddyfile + Authentik UI + `stacks/authentik/scripts/`
|
||||||
|
|
||||||
### If we do it — rough steps
|
### Rollout batches
|
||||||
|
|
||||||
1. Authentik embedded outpost + proxy provider(s) on `edge`
|
| Batch | Sites | Status |
|
||||||
2. Caddy `(authentik_auth)` snippet — `forward_auth authentik-server:9000` with trusted headers
|
|-------|-------|--------|
|
||||||
3. Roll out site-by-site; per-site `handle` bypasses for webhooks/API
|
| 1 — Admin | portainer, code, registry-ui, vault, minio, homarr, uptime, backup/kopia, gitea, dbx, bookstack, plane | Deployed |
|
||||||
4. **Important:** `forward_auth` only gates the edge — apps still show their own login unless you add **native OIDC/OAuth** (famapp/homarr pattern) or disable local auth (e.g. code-server `--auth none`). Homarr switched to native OIDC 2026-06-11.
|
| 2 — Media | sonarr, radarr, bazarr, prowlarr, tautulli, qbit, deluge, nzbget, whisparr, stash | Deployed |
|
||||||
5. **Batch 1 rest (2026-06-11):** BookStack/Gitea/MinIO/Portainer/Plane → native OAuth2 providers; code/uptime/kopia/registry-ui/dbx/vault → forward_auth with local auth disabled where possible. **Portainer:** one-time OAuth setup in Settings → Authentication (see `setup-batch1-oidc.py` output). **Plane:** god-mode at `/god-mode/authentication/oidc`.
|
| 3 — Public + login | files, freshrss, ntfy, resume, storage.j-costa.com | Deployed (revised approach below) |
|
||||||
|
| 4 — Other internal | romm, router UI | **Deferred** |
|
||||||
|
| Skip | famapp (OIDC done), auth.ginnoir.com, overseerr, obsidian, foundry×2, static sites | — |
|
||||||
|
|
||||||
**Rollout batches**
|
### Batch 3 — final approach (2026-06-11)
|
||||||
|
|
||||||
| Batch | Sites |
|
| Site | Authentik method | Notes |
|
||||||
|-------|-------|
|
|------|------------------|-------|
|
||||||
| 1 — Admin | portainer, code, registry-ui, vault, minio, homarr, uptime, backup/kopia, gitea, dbx, bookstack, plane |
|
| **files** (ownCloud) | Native OIDC | `setup-batch1-oidc.py` → `owncloud-web`; `oidc.config.php` via `scripts/apply-batch3-app-auth.sh`; Caddy `/.well-known/openid-configuration` rewrite |
|
||||||
| 2 — Media | sonarr, radarr, bazarr, prowlarr, tautulli, qbit, deluge, nzbget, whisparr, stash |
|
| **freshrss** | Native OIDC | Apache `mod_auth_openidc` (`OIDC_*` in notify stack); provider `freshrss` in Authentik — **Application must bind to OAuth2 provider**, not proxy |
|
||||||
| 3 — Public + login | files, freshrss, ntfy, resume (with bypass tables above) |
|
| **resume** | Native OAuth | `reactive-resume` provider; `OAUTH_*` in resume stack; `FLAG_DISABLE_EMAIL_AUTH=true` |
|
||||||
| 4 — Other internal | romm, router UI |
|
| **ntfy** | **None** | Native ntfy login only; forward_auth breaks web UI |
|
||||||
| Skip | famapp (OIDC done), auth.ginnoir.com, overseerr, obsidian, foundry×2, static sites |
|
| **storage.j-costa.com** | **None** | Plain `reverse_proxy` — app writes to MinIO internally; public GETs for resume assets |
|
||||||
|
|
||||||
|
**Resume data restore:** bind mounts were empty after stack split; live data copied from `htpc-download-box_postgres_data` + `htpc-download-box_minio_data` via `scripts/restore-resume-data.sh`. After restore, run `scripts/fix-resume-oauth-link.sh` (email_verified) and `scripts/fix-resume-jwks.sh` if sessions loop (JWKS encrypted with old `AUTH_SECRET`).
|
||||||
|
|
||||||
|
**Ops scripts (batch 3):**
|
||||||
|
|
||||||
|
- `scripts/run-batch1-oidc.py` wrapper → `run-batch1-oidc.sh`
|
||||||
|
- `scripts/run-forward-auth-admin.sh`
|
||||||
|
- `scripts/apply-batch3-app-auth.sh` — ownCloud oidc.config.php + FreshRSS `http_auth` patch (superseded by FreshRSS native OIDC)
|
||||||
|
- `scripts/restore-resume-data.sh`, `scripts/fix-resume-oauth-link.sh`, `scripts/fix-resume-jwks.sh`
|
||||||
|
|
||||||
### Done when
|
### Done when
|
||||||
|
|
||||||
- [x] Batch 1 admin sites require Authentik before app UI loads (or native OAuth equivalent)
|
- [x] Batch 1 admin sites require Authentik before app UI loads (or native OAuth equivalent)
|
||||||
- [x] Homarr native OIDC (no double login)
|
- [x] Batch 2 media sites — forward_auth + external/disabled local auth (Tautulli excepted)
|
||||||
- [x] BookStack, Gitea, MinIO console → native Authentik OAuth/OIDC
|
- [x] Batch 3 — ownCloud, FreshRSS, resume single Authentik login (native OIDC/OAuth)
|
||||||
- [x] code-server, uptime, kopia → forward_auth only (local auth disabled)
|
- [x] ntfy — native auth only; Vigilant/famapp push unchanged
|
||||||
- [x] registry-ui, dbx, vault → forward_auth at edge
|
- [x] storage.j-costa.com — no Authentik; public resume assets work
|
||||||
- [ ] Portainer OAuth configured in Settings → Authentication (provider created; UI step pending)
|
- [x] Public resume pages viewable without Authentik
|
||||||
- [ ] Plane OIDC configured in god-mode (provider created; UI step pending)
|
- [x] ownCloud share links work without Authentik session
|
||||||
- [x] Portainer git webhooks still work (bypass path)
|
- [ ] Batch 4 — romm, router UI (deferred)
|
||||||
- [x] Gitea `/api/*` + `.git` and Vault `/v1/*` bypass forward_auth
|
- [ ] Portainer OAuth configured in Settings → Authentication (provider created; UI step optional)
|
||||||
- [ ] Batch 2 media sites
|
- [ ] Plane OIDC configured in god-mode (optional; forward_auth accepted)
|
||||||
- [ ] Batch 3 public apps (ownCloud shares, FreshRSS, ntfy, resume)
|
- [ ] Reap orphan `htpc-download-box_*` volumes after trusting bind mounts (TB-011)
|
||||||
- [ ] ownCloud share links work without Authentik session
|
|
||||||
- [ ] FreshRSS still refreshes feeds; Vigilant/famapp still publish to ntfy
|
|
||||||
- [ ] Public resume pages still viewable without Authentik
|
|
||||||
- [ ] Overseerr unchanged for Plex friends
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TB-033 — Public surface audit
|
# TB-033 — Public surface audit
|
||||||
|
|
||||||
**Status:** not started
|
**Status:** done — audited 2026-06-11
|
||||||
**Your call:** _(unset — talk first)_
|
**Your call:** Do it (walkthrough complete; action items below)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -32,9 +32,54 @@
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Decision** | |
|
| **Decision** | Do it — audit complete; fixes tracked below |
|
||||||
| **Notes** | |
|
| **Notes** | Obsidian locked down in TB-005. Auth gaps → TB-006 (other session). |
|
||||||
| **Date** | |
|
| **Date** | 2026-06-11 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Audit results (2026-06-11)
|
||||||
|
|
||||||
|
Sites **without** `internal_only` — reachable from the public internet (Cloudflare → Caddy):
|
||||||
|
|
||||||
|
### Intentionally public ✓
|
||||||
|
|
||||||
|
| Site | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| foundry.ginnoir.com, foundry2.ginnoir.com | Foundry VTT for players |
|
||||||
|
| 5etools.ginnoir.com, pf2e.ginnoir.com | Tabletop reference sites |
|
||||||
|
| files.ginnoir.com | ownCloud (Authentik on admin UI) |
|
||||||
|
| ffttsystems.ginnoir.com | Static site |
|
||||||
|
| requests.ginnoir.com | Overseerr for friends |
|
||||||
|
| ntfy.ginnoir.com | Push notifications (native auth) |
|
||||||
|
| freshrss.ginnoir.com | RSS reader (HTTP auth via Authentik) |
|
||||||
|
| resume.ginnoir.com, j-costa.com | Portfolio |
|
||||||
|
| storage.j-costa.com | Resume PDF/object storage (public by design) |
|
||||||
|
| fam.ginnoir.com | Family app (Authentik OIDC) |
|
||||||
|
| auth.ginnoir.com | Authentik |
|
||||||
|
| dev.ginnoir.com | External LAN host (192.168.1.74) — DNS public but host isn't on valhalla |
|
||||||
|
|
||||||
|
### Public but gated (Authentik forward_auth or native OIDC) — OK for now
|
||||||
|
|
||||||
|
| Site | Gate |
|
||||||
|
|------|------|
|
||||||
|
| sonarr–stash, qbittorrent, deluge, … | `internal_only` + Authentik |
|
||||||
|
| uptime.ginnoir.com, backup.ginnoir.com | Authentik |
|
||||||
|
| code.ginnoir.com, registry-ui, dbx, vault, plane.ginnoir.com | Authentik |
|
||||||
|
| portainer.ginnoir.com | Authentik on UI; webhook POST bypass |
|
||||||
|
|
||||||
|
### Flagged — review / fix
|
||||||
|
|
||||||
|
| Site | Issue | Action |
|
||||||
|
|------|-------|--------|
|
||||||
|
| ~~**minio.ginnoir.com**~~ | ~~Public console~~ | **Fixed 2026-06-11** — `internal_only` |
|
||||||
|
| ~~**homarr.ginnoir.com**~~ | ~~Public, no auth~~ | **Fixed 2026-06-11** — `internal_only` |
|
||||||
|
| ~~**docs.ginnoir.com**~~ | ~~Public BookStack~~ | **Fixed 2026-06-11** — `internal_only` |
|
||||||
|
| **gitea.ginnoir.com** | UI reachable; api/git bypass by design | OK if Gitea login is enough; optional Authentik — **TB-006** |
|
||||||
|
|
||||||
|
### Correctly internal-only ✓
|
||||||
|
|
||||||
|
obsidian, roms, romhacks, romhacks-files, registry.ginnoir.com, router.ginnoir.com, jd.ginnoir.com (added TB-002), all *arr admin UIs.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -53,7 +98,7 @@ Caddyfile review only
|
|||||||
|
|
||||||
### Done when
|
### Done when
|
||||||
|
|
||||||
- [ ] Every public site has your yes/no
|
- [x] Every public site has your yes/no
|
||||||
- [ ] Action items linked to other TBs
|
- [x] Action items linked to other TBs
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ services:
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
vault:
|
vault:
|
||||||
container_name: vault
|
container_name: vault
|
||||||
image: hashicorp/vault:latest
|
image: hashicorp/vault@sha256:3fd53308acccd9e4e83fde3e6c6cf5b15e0f7fac1ff7510780b8b23f5e4c3de7
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- edge
|
- edge
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# TB-006 batch 3: app-side auth so Authentik is not a second login screen.
|
||||||
|
# Run on valhalla after setup-batch1-oidc.py prints client_id/secret values.
|
||||||
|
#
|
||||||
|
# Requires OWNCLOUD_OIDC_* in owncloud stack.env and OAUTH_* in resume stack.env.
|
||||||
|
|
||||||
|
OWNCLOUD_ENV="${OWNCLOUD_ENV:-/tmp/owncloud-stack.env}"
|
||||||
|
RESUME_ENV="${RESUME_ENV:-/tmp/resume-stack.env}"
|
||||||
|
|
||||||
|
read_env() {
|
||||||
|
local file="$1" key="$2"
|
||||||
|
grep -E "^${key}=" "$file" | head -1 | cut -d= -f2-
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=== FreshRSS: switch to HTTP auth (Remote-User from Authentik via Caddy) ==="
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
docker cp "$SCRIPT_DIR/patch-freshrss-http-auth.php" freshrss:/tmp/patch-freshrss-http-auth.php
|
||||||
|
docker exec freshrss php /tmp/patch-freshrss-http-auth.php
|
||||||
|
docker exec freshrss grep -E "auth_type|http_auth_auto_register" /var/www/FreshRSS/data/config.php
|
||||||
|
|
||||||
|
echo "=== ownCloud: write oidc.config.php ==="
|
||||||
|
OC_ID="$(read_env "$OWNCLOUD_ENV" OWNCLOUD_OIDC_CLIENT_ID)"
|
||||||
|
OC_SECRET="$(read_env "$OWNCLOUD_ENV" OWNCLOUD_OIDC_CLIENT_SECRET)"
|
||||||
|
if [[ -z "$OC_ID" || -z "$OC_SECRET" ]]; then
|
||||||
|
echo "ERROR: set OWNCLOUD_OIDC_CLIENT_ID/SECRET in owncloud stack.env first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP_OC="$(mktemp)"
|
||||||
|
cat >"$TMP_OC" <<PHP
|
||||||
|
<?php
|
||||||
|
\$CONFIG = [
|
||||||
|
'http.cookie.samesite' => 'None',
|
||||||
|
'openid-connect' => [
|
||||||
|
'provider-url' => 'https://auth.ginnoir.com/application/o/owncloud/',
|
||||||
|
'client-id' => '${OC_ID}',
|
||||||
|
'client-secret' => '${OC_SECRET}',
|
||||||
|
'loginButtonName' => 'Log in with Authentik',
|
||||||
|
'mode' => 'userid',
|
||||||
|
'search-attribute' => 'preferred_username',
|
||||||
|
'autoRedirectOnLoginPage' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
PHP
|
||||||
|
docker cp "$TMP_OC" owncloud_server:/mnt/data/config/oidc.config.php
|
||||||
|
rm -f "$TMP_OC"
|
||||||
|
echo " wrote /mnt/data/config/oidc.config.php"
|
||||||
|
docker exec owncloud_server occ app:enable openidconnect >/dev/null 2>&1 || true
|
||||||
|
echo " owncloud openidconnect enabled"
|
||||||
|
|
||||||
|
echo "=== done — recreate resume container after stack.env OAuth vars are set ==="
|
||||||
|
if grep -q '^OAUTH_CLIENT_ID=' "$RESUME_ENV" 2>/dev/null; then
|
||||||
|
echo " resume stack.env has OAUTH_CLIENT_ID (Portainer redeploy or recreate app container)"
|
||||||
|
else
|
||||||
|
echo " WARN: add OAUTH_* vars to resume stack.env and redeploy the resume stack"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Restored resume DB may contain JWKS encrypted with an old AUTH_SECRET.
|
||||||
|
# Better Auth then fails session verification after OAuth (login page loop).
|
||||||
|
# Safe fix: drop JWKS + sessions; app regenerates keys on next start.
|
||||||
|
|
||||||
|
echo "=== resume: reset Better Auth JWKS (fixes session decrypt errors) ==="
|
||||||
|
docker stop resume >/dev/null
|
||||||
|
docker exec postgres_resume psql -U postgres -d postgres -c "TRUNCATE jwks, session, oauth_access_token, oauth_refresh_token CASCADE;"
|
||||||
|
docker start resume >/dev/null
|
||||||
|
sleep 15
|
||||||
|
docker logs resume --tail 15 2>&1
|
||||||
|
echo "done — retry resume.ginnoir.com → Authentik"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "=== resume: allow OAuth to link existing email/password account ==="
|
||||||
|
docker exec postgres_resume psql -U postgres -d postgres -c \
|
||||||
|
"UPDATE \"user\" SET email_verified = true WHERE username = 'ginnoir';"
|
||||||
|
docker exec postgres_resume psql -U postgres -d postgres -c \
|
||||||
|
"SELECT email, email_verified, username FROM \"user\";"
|
||||||
|
|
||||||
|
echo "done — retry Authentik login on resume.ginnoir.com"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
$path = '/var/www/FreshRSS/data/config.php';
|
||||||
|
$text = file_get_contents($path);
|
||||||
|
$text = preg_replace("/'auth_type' => 'http'/", "'auth_type' => 'http_auth'", $text, 1);
|
||||||
|
$text = preg_replace("/'auth_type' => 'form'/", "'auth_type' => 'http_auth'", $text, 1);
|
||||||
|
$text = preg_replace("/'http_auth_auto_register' => true/", "'http_auth_auto_register' => false", $text, 1);
|
||||||
|
file_put_contents($path, $text);
|
||||||
|
echo "ok\n";
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Restore resume postgres + minio from pre-split monolith named volumes into bind mounts.
|
||||||
|
# Safe to re-run: stops stack, copies from htpc-download-box_* volumes, restarts postgres.
|
||||||
|
|
||||||
|
OLD_PG_VOL="${OLD_PG_VOL:-htpc-download-box_postgres_data}"
|
||||||
|
OLD_MINIO_VOL="${OLD_MINIO_VOL:-htpc-download-box_minio_data}"
|
||||||
|
PG_BIND="${PG_BIND:-/config/resume/postgres}"
|
||||||
|
MINIO_BIND="${MINIO_BIND:-/storage1/labdata/resume/minio}"
|
||||||
|
|
||||||
|
echo "=== stop resume stack services ==="
|
||||||
|
docker stop resume minio_resume postgres_resume 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "=== restore postgres: ${OLD_PG_VOL} -> ${PG_BIND} ==="
|
||||||
|
docker run --rm \
|
||||||
|
-v "${OLD_PG_VOL}:/from:ro" \
|
||||||
|
-v "${PG_BIND}:/to" \
|
||||||
|
alpine sh -c 'rm -rf /to/* /to/.[!.]* /to/..?* 2>/dev/null || true; cp -a /from/. /to/; chown -R 70:70 /to'
|
||||||
|
|
||||||
|
echo "=== restore minio objects: ${OLD_MINIO_VOL}/default -> ${MINIO_BIND}/default ==="
|
||||||
|
docker run --rm \
|
||||||
|
-v "${OLD_MINIO_VOL}:/from:ro" \
|
||||||
|
-v "${MINIO_BIND}:/to" \
|
||||||
|
alpine sh -c 'mkdir -p /to/default; rm -rf /to/default/* 2>/dev/null || true; cp -a /from/default/. /to/default/ 2>/dev/null || true'
|
||||||
|
|
||||||
|
echo "=== start postgres ==="
|
||||||
|
docker start postgres_resume
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
if docker exec postgres_resume pg_isready -U postgres -d postgres >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
docker exec postgres_resume pg_isready -U postgres -d postgres
|
||||||
|
|
||||||
|
echo "=== verify restored data ==="
|
||||||
|
docker exec postgres_resume psql -U postgres -d postgres -c 'SELECT email, username FROM "user"; SELECT slug, is_public FROM resume;'
|
||||||
|
|
||||||
|
echo "=== align resume user email with Authentik (3nigma.matt@gmail.com) for OAuth linking ==="
|
||||||
|
docker exec postgres_resume psql -U postgres -d postgres -c "UPDATE \"user\" SET email = '3nigma.matt@gmail.com' WHERE username = 'ginnoir';"
|
||||||
|
|
||||||
|
echo "=== start minio + resume (if compose project exists) ==="
|
||||||
|
docker start minio_resume 2>/dev/null || true
|
||||||
|
docker start resume 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "done — if resume container was ad-hoc recreated, redeploy stacks/resume via Portainer after git push"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
docker cp /tmp/setup-batch1-oidc.py authentik_server:/tmp/setup-batch1-oidc.py
|
||||||
|
docker exec authentik_server ak shell -c "exec(open('/tmp/setup-batch1-oidc.py').read())"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
docker cp /tmp/apply-forward-auth-admin.py authentik_server:/tmp/apply-forward-auth-admin.py
|
||||||
|
docker exec authentik_server ak shell -c "exec(open('/tmp/apply-forward-auth-admin.py').read())"
|
||||||
@@ -51,6 +51,8 @@ services:
|
|||||||
container_name: postgres_authentik
|
container_name: postgres_authentik
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [authentik]
|
networks: [authentik]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -66,6 +68,8 @@ services:
|
|||||||
container_name: redis_authentik
|
container_name: redis_authentik
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [authentik]
|
networks: [authentik]
|
||||||
command: --save 60 1 --loglevel warning
|
command: --save 60 1 --loglevel warning
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Apply TB-006 forward_auth proxy providers (admin batch 1 + media batch 2).
|
"""Apply TB-006 forward_auth proxy providers (batches 1–3).
|
||||||
|
|
||||||
Native OAuth/OIDC apps (bookstack, gitea, portainer, minio, homarr) use
|
Native OAuth/OIDC apps (bookstack, gitea, portainer, minio, homarr) use
|
||||||
setup-batch1-oidc.py instead. Run this via: ak shell -c exec(open(...).read())
|
setup-batch1-oidc.py instead. Run this via: ak shell -c exec(open(...).read())
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ OIDC_APPS = [
|
|||||||
("gitea", "gitea", ["https://gitea.ginnoir.com/user/oauth2/Authentik/callback"]),
|
("gitea", "gitea", ["https://gitea.ginnoir.com/user/oauth2/Authentik/callback"]),
|
||||||
("portainer", "portainer", ["https://portainer.ginnoir.com/"]),
|
("portainer", "portainer", ["https://portainer.ginnoir.com/"]),
|
||||||
("minio", "minio-console", ["https://minio.ginnoir.com/oauth_callback"]),
|
("minio", "minio-console", ["https://minio.ginnoir.com/oauth_callback"]),
|
||||||
|
("owncloud", "owncloud-web", [
|
||||||
|
"https://files.ginnoir.com/index.php/apps/openidconnect/redirect",
|
||||||
|
"https://files.ginnoir.com/apps/openidconnect/redirect",
|
||||||
|
]),
|
||||||
|
("resume", "reactive-resume", ["https://resume.ginnoir.com/api/auth/oauth2/callback/custom"]),
|
||||||
|
("freshrss", "freshrss", ["https://freshrss.ginnoir.com/i/oidc/"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
native_slugs = []
|
native_slugs = []
|
||||||
@@ -63,6 +69,9 @@ PROXY_NAMES = {
|
|||||||
"gitea": "homelab-gitea",
|
"gitea": "homelab-gitea",
|
||||||
"portainer": "homelab-portainer",
|
"portainer": "homelab-portainer",
|
||||||
"minio": "homelab-minio",
|
"minio": "homelab-minio",
|
||||||
|
"owncloud": "homelab-files",
|
||||||
|
"resume": "homelab-resume",
|
||||||
|
"freshrss": "homelab-freshrss",
|
||||||
}
|
}
|
||||||
outpost = Outpost.objects.get(name="authentik Embedded Outpost")
|
outpost = Outpost.objects.get(name="authentik Embedded Outpost")
|
||||||
for slug in native_slugs:
|
for slug in native_slugs:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Update proxy providers for forward_auth apps (admin batch 1 + media batch 2)."""
|
"""Update proxy providers for forward_auth apps (batches 1–3)."""
|
||||||
from authentik.core.models import Application
|
from authentik.core.models import Application
|
||||||
from authentik.flows.models import Flow
|
from authentik.flows.models import Flow
|
||||||
from authentik.outposts.models import Outpost, OutpostType
|
from authentik.outposts.models import Outpost, OutpostType
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ services:
|
|||||||
container_name: postgres_gitea
|
container_name: postgres_gitea
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [dev]
|
networks: [dev]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -162,8 +164,10 @@ services:
|
|||||||
|
|
||||||
mariadb_bookstack:
|
mariadb_bookstack:
|
||||||
container_name: mariadb_bookstack
|
container_name: mariadb_bookstack
|
||||||
image: lscr.io/linuxserver/mariadb:latest
|
image: lscr.io/linuxserver/mariadb:11.4.7
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [dev]
|
networks: [dev]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -336,6 +340,8 @@ services:
|
|||||||
container_name: postgres_plane
|
container_name: postgres_plane
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [dev]
|
networks: [dev]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -355,6 +361,8 @@ services:
|
|||||||
container_name: redis_plane
|
container_name: redis_plane
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [dev]
|
networks: [dev]
|
||||||
command: --save 60 1 --loglevel warning
|
command: --save 60 1 --loglevel warning
|
||||||
volumes:
|
volumes:
|
||||||
@@ -367,8 +375,10 @@ services:
|
|||||||
|
|
||||||
plane-minio:
|
plane-minio:
|
||||||
container_name: plane_minio
|
container_name: plane_minio
|
||||||
image: minio/minio:latest
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [dev]
|
networks: [dev]
|
||||||
command: server /data --console-address ":9001"
|
command: server /data --console-address ":9001"
|
||||||
env_file:
|
env_file:
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ services:
|
|||||||
container_name: postgres_famapp
|
container_name: postgres_famapp
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [famapp]
|
networks: [famapp]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -44,9 +46,11 @@ services:
|
|||||||
|
|
||||||
famapp-minio:
|
famapp-minio:
|
||||||
container_name: minio_famapp
|
container_name: minio_famapp
|
||||||
image: minio/minio:latest
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||||
command: server /data --console-address ":9003"
|
command: server /data --console-address ":9003"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [famapp]
|
networks: [famapp]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
|
|||||||
@@ -158,6 +158,17 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "6969:6969"
|
- "6969:6969"
|
||||||
|
|
||||||
|
recyclarr:
|
||||||
|
image: ghcr.io/recyclarr/recyclarr:8
|
||||||
|
container_name: recyclarr
|
||||||
|
restart: unless-stopped
|
||||||
|
networks: [media]
|
||||||
|
user: 1000:1000
|
||||||
|
env_file:
|
||||||
|
- stack.env
|
||||||
|
volumes:
|
||||||
|
- ./recyclarr:/config
|
||||||
|
|
||||||
stash:
|
stash:
|
||||||
image: stashapp/stash:latest
|
image: stashapp/stash:latest
|
||||||
container_name: stash
|
container_name: stash
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# TRaSH Guides sync — WEB-1080p (Sonarr) + HD Bluray + WEB (Radarr).
|
||||||
|
# Run manually: docker exec recyclarr recyclarr sync
|
||||||
|
sonarr:
|
||||||
|
main:
|
||||||
|
base_url: http://sonarr:8989
|
||||||
|
api_key: !secret sonarr_api_key
|
||||||
|
delete_old_custom_formats: true
|
||||||
|
quality_definition:
|
||||||
|
type: series
|
||||||
|
quality_profiles:
|
||||||
|
- trash_id: 72dae194fc92bf828f32cde74482a9dde
|
||||||
|
reset_unmatched_scores:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
radarr:
|
||||||
|
main:
|
||||||
|
base_url: http://radarr:7878
|
||||||
|
api_key: !secret radarr_api_key
|
||||||
|
delete_old_custom_formats: true
|
||||||
|
quality_definition:
|
||||||
|
type: movie
|
||||||
|
quality_profiles:
|
||||||
|
- trash_id: d1d67249d3890e49bc12e275d989a7e9
|
||||||
|
reset_unmatched_scores:
|
||||||
|
enabled: true
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
sonarr_api_key: "383c9489253e445baf8514013a4e37a4"
|
||||||
|
radarr_api_key: "94159a19beef48f185bd3e330f8dde3a"
|
||||||
@@ -22,8 +22,10 @@
|
|||||||
services:
|
services:
|
||||||
couchdb:
|
couchdb:
|
||||||
container_name: couchdb
|
container_name: couchdb
|
||||||
image: couchdb:3
|
image: couchdb:3.4
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [notes, edge]
|
networks: [notes, edge]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ services:
|
|||||||
- CRON_MIN=3,33
|
- CRON_MIN=3,33
|
||||||
- TRUSTED_PROXY=172.16.0.1/12 192.168.0.1/16
|
- TRUSTED_PROXY=172.16.0.1/12 192.168.0.1/16
|
||||||
- FRESHRSS_INSTALL=--default-user ginnoir --api-enabled --base-url https://freshrss.ginnoir.com
|
- FRESHRSS_INSTALL=--default-user ginnoir --api-enabled --base-url https://freshrss.ginnoir.com
|
||||||
|
- OIDC_ENABLED=1
|
||||||
|
- OIDC_PROVIDER_METADATA_URL=https://auth.ginnoir.com/application/o/freshrss/.well-known/openid-configuration
|
||||||
|
- OIDC_REMOTE_USER_CLAIM=preferred_username
|
||||||
|
- OIDC_SCOPES=openid profile email
|
||||||
|
- OIDC_X_FORWARDED_HEADERS=X-Forwarded-Host X-Forwarded-Proto
|
||||||
|
|
||||||
vigilant:
|
vigilant:
|
||||||
container_name: vigilant
|
container_name: vigilant
|
||||||
|
|||||||
@@ -3,3 +3,6 @@ TZ=America/Chicago
|
|||||||
# FreshRSS first-run user bootstrap (the container reads FRESHRSS_USER as the
|
# FreshRSS first-run user bootstrap (the container reads FRESHRSS_USER as the
|
||||||
# full CLI argument string for its install script).
|
# full CLI argument string for its install script).
|
||||||
FRESHRSS_USER=--api-password d0fet0th3x --email 3nigma.matt@gmail.com --password d0fet0th3x --user ginnoir
|
FRESHRSS_USER=--api-password d0fet0th3x --email 3nigma.matt@gmail.com --password d0fet0th3x --user ginnoir
|
||||||
|
OIDC_CLIENT_ID=5DYeBheXidDAErkLTTMFBB4xdC734MoHQ2xNyVWp
|
||||||
|
OIDC_CLIENT_SECRET=4s9uiOgTla9euoVlvEgYNpqSGLOaxm0WG4tchUhzHYCjNyOeYQ2s426OaBAwV0YtXDXplCUhkCKNm6q0GCfpSZADhJo2L6nkRuCqFtuA3454Wpjf8ArRVYKwJqdGQePH
|
||||||
|
OIDC_CLIENT_CRYPTO_KEY=7f3a9c2e1b8d4f6a0e5c8b2d9f1a4e7
|
||||||
|
|||||||
@@ -37,9 +37,11 @@ services:
|
|||||||
- /storage1/ROMs:/mnt/roms
|
- /storage1/ROMs:/mnt/roms
|
||||||
|
|
||||||
mariadb:
|
mariadb:
|
||||||
image: mariadb:latest
|
image: mariadb:12.3
|
||||||
container_name: owncloud_mariadb
|
container_name: owncloud_mariadb
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [owncloud]
|
networks: [owncloud]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
@@ -56,9 +58,11 @@ services:
|
|||||||
- /config/mysql:/var/lib/mysql
|
- /config/mysql:/var/lib/mysql
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:latest
|
image: redis:7-alpine
|
||||||
container_name: owncloud_redis
|
container_name: owncloud_redis
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [owncloud]
|
networks: [owncloud]
|
||||||
command: ["--databases", "1"]
|
command: ["--databases", "1"]
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|||||||
@@ -9,3 +9,5 @@ OWNCLOUD_ADMIN_PASSWORD=d0fet0th3x
|
|||||||
MYSQL_ROOT_PASSWORD=d0fet0th3x
|
MYSQL_ROOT_PASSWORD=d0fet0th3x
|
||||||
MYSQL_USER=ginnoir
|
MYSQL_USER=ginnoir
|
||||||
MYSQL_PASSWORD=d0fet0th3x
|
MYSQL_PASSWORD=d0fet0th3x
|
||||||
|
OWNCLOUD_OIDC_CLIENT_ID=kVTZzTn4ho1lfD8ghtYHYsW84jLBzVQJBzZ7klHB
|
||||||
|
OWNCLOUD_OIDC_CLIENT_SECRET=ZvNY4bLkBsbSfo1rUBnX9nSwPzcP5R2Ya18z7IND45KmoPwUOMjnTOI6QjtQuLrzoSJ8ym03rLQLZoNb7Cdp4PtVlPPTMZYKwJBtK7DNWt8zllHLT97gbqWKQGTMxqKF
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
services:
|
services:
|
||||||
caddy:
|
caddy:
|
||||||
container_name: caddy
|
container_name: caddy
|
||||||
image: serfriz/caddy-cloudflare-ddns:latest
|
image: serfriz/caddy-cloudflare-ddns:2.11.3
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks:
|
networks:
|
||||||
- edge
|
- edge
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ services:
|
|||||||
container_name: postgres_resume
|
container_name: postgres_resume
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [resume]
|
networks: [resume]
|
||||||
volumes:
|
volumes:
|
||||||
- /config/resume/postgres:/var/lib/postgresql/data
|
- /config/resume/postgres:/var/lib/postgresql/data
|
||||||
@@ -27,8 +29,10 @@ services:
|
|||||||
|
|
||||||
resume-minio:
|
resume-minio:
|
||||||
container_name: minio_resume
|
container_name: minio_resume
|
||||||
image: minio/minio:latest
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [resume, edge]
|
networks: [resume, edge]
|
||||||
command: server /data --console-address :9001
|
command: server /data --console-address :9001
|
||||||
ports:
|
ports:
|
||||||
@@ -93,6 +97,10 @@ services:
|
|||||||
- STORAGE_BUCKET=default
|
- STORAGE_BUCKET=default
|
||||||
- STORAGE_USE_SSL=false
|
- STORAGE_USE_SSL=false
|
||||||
- STORAGE_SKIP_BUCKET_CHECK=false
|
- STORAGE_SKIP_BUCKET_CHECK=false
|
||||||
|
- OAUTH_PROVIDER_NAME=Authentik
|
||||||
|
- OAUTH_DISCOVERY_URL=https://auth.ginnoir.com/application/o/resume/.well-known/openid-configuration
|
||||||
|
- FLAG_DISABLE_EMAIL_AUTH=true
|
||||||
|
- FLAG_DISABLE_SIGNUPS=true
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
resume:
|
resume:
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ STORAGE_SECRET_KEY=minioadmin
|
|||||||
# Pinned to the running value so recreating the container keeps sessions valid.
|
# Pinned to the running value so recreating the container keeps sessions valid.
|
||||||
# Rotate with: openssl rand -hex 64
|
# Rotate with: openssl rand -hex 64
|
||||||
AUTH_SECRET=1b7e96f61f080d04d4bf673d9ea1d9349eb7693cddee5772b6c3f153c88032db5b97efd8570087bc6f340d2cd874aabc1e5c681bc22889921240d6a23738bc7f
|
AUTH_SECRET=1b7e96f61f080d04d4bf673d9ea1d9349eb7693cddee5772b6c3f153c88032db5b97efd8570087bc6f340d2cd874aabc1e5c681bc22889921240d6a23738bc7f
|
||||||
|
OAUTH_CLIENT_ID=YpMFNp9q5mGbN8ADM5rUol0ERHmSiTDClJKIVOxK
|
||||||
|
OAUTH_CLIENT_SECRET=mzwjSt0Xtibo156km61T7VYerT48K6ZTa79cEek4mgdky6t1Sjaddlshw2QcJL8727N6qWzddi2ihxNGSpUVMXUBbjNgx4jtkHAy5xtmvqdk9ouIFclyhCgXh9fzjMCA
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ services:
|
|||||||
- "8997:8080"
|
- "8997:8080"
|
||||||
|
|
||||||
romm-db:
|
romm-db:
|
||||||
image: mariadb:latest
|
image: mariadb:12.3
|
||||||
container_name: romm-db
|
container_name: romm-db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
networks: [roms]
|
networks: [roms]
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
|
|||||||
Reference in New Issue
Block a user