Compare commits
2 Commits
80a5ad24a2
...
e1afd08bf3
| Author | SHA1 | Date | |
|---|---|---|---|
| e1afd08bf3 | |||
| 268df30a13 |
@@ -43,7 +43,7 @@ services:
|
||||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: redis:7.4-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99
|
||||
image: redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- immich_default
|
||||
@@ -52,14 +52,15 @@ services:
|
||||
|
||||
database:
|
||||
container_name: immich_postgres
|
||||
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
|
||||
POSTGRES_USER: immich
|
||||
POSTGRES_DB: immich
|
||||
shm_size: 128mb
|
||||
volumes:
|
||||
- /mnt/user/appdata/immich_postgres:/var/lib/postgresql/data
|
||||
- /mnt/user/appdata/immich_postgres_vectorchord:/var/lib/postgresql/data
|
||||
- /mnt/user/appdata/secrets/immich_postgres_password.txt:/run/secrets/postgres_password:ro
|
||||
networks:
|
||||
- immich_default
|
||||
|
||||
@@ -38,7 +38,7 @@ services:
|
||||
- traefik.http.services.mealie.loadbalancer.server.port=9000
|
||||
|
||||
mealie-postgres:
|
||||
image: postgres:17.10@sha256:0027bef26712baaee437a4ea48fdf3d2d2e2bc5f0d81615374408ca320f3c7e3
|
||||
image: postgres:18.4@sha256:8ff36f3c66371cba71d20ceedccfc3de9669a68737607888c4ef0af93abe8e39
|
||||
container_name: mealie-postgres
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -47,10 +47,10 @@ services:
|
||||
POSTGRES_USER: mealie
|
||||
POSTGRES_DB: mealie
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
PGDATA: /var/lib/postgresql/18/docker
|
||||
|
||||
volumes:
|
||||
- /mnt/user/appdata/mealie/postgres:/var/lib/postgresql/data
|
||||
- /mnt/user/appdata/mealie/postgres18:/var/lib/postgresql
|
||||
- /mnt/user/appdata/secrets/mealie_postgres_password.txt:/run/secrets/postgres_password:ro
|
||||
|
||||
networks:
|
||||
|
||||
@@ -46,7 +46,7 @@ services:
|
||||
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
|
||||
|
||||
nextcloud-postgres:
|
||||
image: postgres:17.10@sha256:0027bef26712baaee437a4ea48fdf3d2d2e2bc5f0d81615374408ca320f3c7e3
|
||||
image: postgres:18.4@sha256:8ff36f3c66371cba71d20ceedccfc3de9669a68737607888c4ef0af93abe8e39
|
||||
container_name: nextcloud-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@@ -54,9 +54,9 @@ services:
|
||||
POSTGRES_DB: nextcloud
|
||||
POSTGRES_USER: nextcloud
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
PGDATA: /var/lib/postgresql/18/docker
|
||||
volumes:
|
||||
- /mnt/user/appdata/nextcloud/postgres:/var/lib/postgresql/data
|
||||
- /mnt/user/appdata/nextcloud/postgres18:/var/lib/postgresql
|
||||
- /mnt/user/appdata/secrets/nextcloud_postgres_password.txt:/run/secrets/postgres_password:ro
|
||||
networks:
|
||||
- nextcloud_internal
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
- no-new-privileges:true
|
||||
|
||||
nextcloud-redis:
|
||||
image: redis:7.4-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99
|
||||
image: redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1
|
||||
container_name: nextcloud-redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --save 60 1 --loglevel warning
|
||||
|
||||
@@ -261,7 +261,7 @@ Ziel:
|
||||
|
||||
### Stufe 2 - Gemeinsame Backends und Identity
|
||||
|
||||
4. `infra/postgresql17/`
|
||||
4. `infra/postgresql17/` (PostgreSQL 18 runtime, historischer Stack-Name bleibt fuer Service-DNS stabil)
|
||||
5. `security/authelia/`
|
||||
6. `infra/redis/`
|
||||
7. `core/gitea/`
|
||||
@@ -396,6 +396,12 @@ Vor dem Start muessen vorhanden sein:
|
||||
|
||||
Zusaetzlich muss der Nutzdatenpfad `/mnt/user/documents/nextcloud-data` erreichbar sein.
|
||||
|
||||
Beim PostgreSQL-Restore beachten:
|
||||
|
||||
- vor einem produktiven Dump `occ maintenance:mode --on` setzen
|
||||
- die produktive DB-Rolle kann von `POSTGRES_USER` abweichen; aktuell nutzt Nextcloud laut `config.php` die Rolle `oc_admin`
|
||||
- nach Restore und erfolgreichem `occ status` den Wartungsmodus mit `occ maintenance:mode --off` beenden
|
||||
|
||||
### Borg-Dumps
|
||||
|
||||
Die Dump-Erzeugung ist host-seitig gedacht, nicht als Borg-UI-Inline-Hook.
|
||||
@@ -406,6 +412,50 @@ Relevant:
|
||||
- Skript: `ops/borg-ui/scripts/pre-backup-dumps.sh`
|
||||
- Unraid-Flash-Artefakt: `unraid-flash-config.tar.gz` plus `.sha256` und Manifest im selben Zielpfad
|
||||
|
||||
### Redis 8 Restore / Rollback
|
||||
|
||||
Redis-Instanzen laufen auf der 8.x-Schiene. Vor Major-Upgrades wird `redis-cli SAVE` ausgefuehrt und der jeweilige Datenpfad kopiert.
|
||||
|
||||
Aktive Pfade und Besonderheiten:
|
||||
|
||||
- Shared Redis: `/mnt/user/appdata/redis`, Passwort aus `redis_password.txt`, AOF aktiv.
|
||||
- Nextcloud Redis: `/mnt/user/appdata/nextcloud/redis`, ohne Redis-Passwort, Snapshot-Persistenz.
|
||||
- Immich Redis: cache/queue-only ohne bind-mounted Datenpfad; Restore-Wahrheit ist Immich Postgres + Foto-Dateien, nicht Redis.
|
||||
|
||||
Rollback:
|
||||
|
||||
1. Abhaengige App stoppen.
|
||||
2. Redis stoppen.
|
||||
3. Compose auf das vorherige Redis-7.4-Image zuruecksetzen.
|
||||
4. Bei Shared/Nextcloud den vor dem Cutover kopierten Datenpfad zurueckkopieren.
|
||||
5. Redis und App starten, `redis-cli INFO server` und App-Smoke pruefen.
|
||||
|
||||
### PostgreSQL 18 Major-Upgrade / Rollback
|
||||
|
||||
Produktive PostgreSQL-18-Cluster verwenden das Docker-Image-Layout mit Host-Mount auf `/var/lib/postgresql` und `PGDATA=/var/lib/postgresql/18/docker`.
|
||||
|
||||
Aktive Datenpfade:
|
||||
|
||||
- Shared PostgreSQL: `/mnt/user/appdata/postgresql18`
|
||||
- Mealie PostgreSQL: `/mnt/user/appdata/mealie/postgres18`
|
||||
- Nextcloud PostgreSQL: `/mnt/user/appdata/nextcloud/postgres18`
|
||||
|
||||
Rollback-Altstaende, bis zur separaten Loeschfreigabe nicht entfernen:
|
||||
|
||||
- Shared PostgreSQL 17: `/mnt/user/appdata/postgresql17`
|
||||
- Mealie PostgreSQL 17: `/mnt/user/appdata/mealie/postgres`
|
||||
- Nextcloud PostgreSQL 17: `/mnt/user/appdata/nextcloud/postgres`
|
||||
|
||||
Restore-Reihenfolge fuer den Shared-Cluster:
|
||||
|
||||
1. Frischen PostgreSQL-18-Cluster starten.
|
||||
2. Globals aus `pg_dumpall --globals-only` einspielen.
|
||||
3. Den bekannten Bootstrap-Konflikt fuer `CREATE ROLE mailarchiver;` gezielt tolerieren bzw. herausfiltern, danach `ALTER ROLE mailarchiver ...` dennoch einspielen.
|
||||
4. Datenbanken anlegen und Custom-Format-Dumps mit `pg_restore` einspielen.
|
||||
5. Restore-Logs auf echte `ERROR`, `FATAL` und `PANIC` pruefen.
|
||||
|
||||
Immich ist bewusst nicht Teil dieses PostgreSQL-18-Laufs: Die produktive DB bleibt auf PostgreSQL 14 und nutzt das Immich-Postgres-Image mit VectorChord/pgvector. VectorChord-Backups brauchen zum Restore ein Image mit VectorChord; der alte pgvecto.rs-Datenpfad `/mnt/user/appdata/immich_postgres` bleibt bis zur separaten Loeschfreigabe als Rollback-Altstand erhalten.
|
||||
|
||||
### Hermes Agent
|
||||
|
||||
Hermes nutzt einen lokalen Build und hostseitige Runtime-Daten.
|
||||
|
||||
@@ -11,7 +11,7 @@ Schliesst die Audit-Luecke aus F-11: Immich ist der groesste Datentopf (Familien
|
||||
|
||||
| Datei | Zweck |
|
||||
|---|---|
|
||||
| `ops/restore-tests/immich-compose.test.yml` | isoliertes Test-Compose: pgvecto-rs Postgres + Redis + Immich-Server, ML weggelassen, `127.0.0.1:12283` |
|
||||
| `ops/restore-tests/immich-compose.test.yml` | isoliertes Test-Compose: Immich-Postgres mit VectorChord + Redis + Immich-Server, ML weggelassen, `127.0.0.1:12283` |
|
||||
| `ops/restore-tests/immich-restore-test.sh` | Host-Bash-Skript fuer den Lauf, mit `--what-if` und `--keep-data` Flags |
|
||||
| `ops/restore-tests/immich-restore-test.ps1` | Plan-Scaffold fuer Windows-Operator-Sicht (kein Live-Run) |
|
||||
| `ops/restore-tests/immich-plan.md` | Fachlicher Plan: Quellen, Schutzregeln, Smoke-Test-Kriterien, bekannte Risiken |
|
||||
@@ -20,7 +20,7 @@ Schliesst die Audit-Luecke aus F-11: Immich ist der groesste Datentopf (Familien
|
||||
## Was der Test abdeckt
|
||||
|
||||
- Extraktion von `local/borg-dumps/latest/immich.dump` aus dem aktuellsten Borg-Archiv
|
||||
- Import in eine isolierte `tensorchord/pgvecto-rs:pg14-v0.2.0` Postgres-Instanz mit demselben Digest wie Produktion
|
||||
- Import in eine isolierte `ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0` Postgres-Instanz mit demselben Digest wie Produktion
|
||||
- Start eines isolierten Immich-Server-Containers mit demselben Digest wie Produktion, **ohne** ML-Container und **ohne** Traefik
|
||||
- Smoke-Test: Login-Seite erreichbar, `asset`- und `"user"`-Tabelle lesbar
|
||||
- Markdown-Report unter `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md`
|
||||
@@ -57,7 +57,7 @@ Der Test deckt **Stufe 4 (kritische Anwendungen)** aus `docs/DISASTER_RECOVERY.m
|
||||
## Schutzregeln
|
||||
|
||||
- Skript greift ausschliesslich auf den Restore-Lab-Pfad und den Borg-Extract-Cache zu.
|
||||
- Produktive Pfade unter `/mnt/user/photos/*` und `/mnt/user/appdata/immich_postgres/` werden nicht angefasst.
|
||||
- Produktive Pfade unter `/mnt/user/photos/*`, `/mnt/user/appdata/immich_postgres_vectorchord/` und dem Rollback-Altstand `/mnt/user/appdata/immich_postgres/` werden nicht angefasst.
|
||||
- Produktive Container `immich_server`, `immich_postgres`, `immich_redis`, `immich_machine_learning` werden nicht gestoppt, nicht beruehrt.
|
||||
- Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und nicht in Reports, Logs oder Doku geschrieben.
|
||||
- Test-Container publishen nur auf `127.0.0.1:12283`, nicht auf LAN- oder Tailscale-Interface.
|
||||
@@ -66,8 +66,8 @@ Der Test deckt **Stufe 4 (kritische Anwendungen)** aus `docs/DISASTER_RECOVERY.m
|
||||
## Risiken (aus `ops/restore-tests/immich-plan.md`)
|
||||
|
||||
- Dump-Groesse und erster `pg_restore`-Lauf sind gemessen: `immich.dump` 66M, echter Smoke-Test erfolgreich am 2026-05-27.
|
||||
- pgvecto-rs Extension-Mismatch bei Image-Drift moeglich; Compose pinnt denselben Digest wie Produktion.
|
||||
- Immich v2 meldet pgvecto-rs als deprecated; VectorChord-Migration ist ein kuenftiger Immich-Upgrade-Punkt, nicht Teil dieses Restore-Tests.
|
||||
- VectorChord-/pgvector-Extension-Mismatch bei Image-Drift moeglich; Compose pinnt denselben Digest wie Produktion.
|
||||
- Immich nutzt nach der VectorChord-Migration `vchord 0.4.3` und `vector 0.8.1`; Restore-Tests muessen ein Image mit VectorChord verwenden.
|
||||
- Immich-Server-Migrations koennen Startup nach Restore verzoegern; Skript pollt 120 s.
|
||||
- Bei Schema-Drift (z. B. nach Major-Update) koennen einzelne DB-Queries abweichen; das Skript versucht Immich-v2-Singular-Tabellen und aeltere Plural-Fallbacks.
|
||||
|
||||
|
||||
+4
-7
@@ -87,7 +87,7 @@ Script: bash /mnt/user/services/homelab-infra/ops/renovate/run-renovate.sh
|
||||
|---|---|---|
|
||||
| Major-Updates | `groupName: major-updates`, `automerge: false` | Eine gesammelte PR pro Lauf mit allen Major-Updates, manueller Merge |
|
||||
| Minor + Patch + Digest fuer Docker-Compose | `groupName: minor-and-patch-updates`, `automerge: false` | Eine gesammelte PR; Operator merged manuell |
|
||||
| Tier-1-Datenhalter (Postgres, Mongo, Redis, pgvecto-rs) | `groupName: null`, eigener Label | Einzelne PRs ohne Group, hoehere Sichtbarkeit |
|
||||
| Tier-1-Datenhalter (Postgres, Mongo, Redis, Immich-Postgres) | `groupName: null`, eigener Label | Einzelne PRs ohne Group, hoehere Sichtbarkeit |
|
||||
| Komodo-Major-Updates | `enabled: false` fuer matchPackageNames + matchUpdateTypes major | Komodo bleibt auf `:2`, wird nicht versehentlich auf `:3` migriert |
|
||||
| Lock-File-Maintenance | `lockFileMaintenance.enabled: false` | Renovate macht keine reinen Lock-File-Refreshs |
|
||||
| Schedule | `extends ["schedule:weekly"]` | Renovate-Engine prueft, aber PRs/Updates folgen Wochen-Profilen wo sinnvoll |
|
||||
@@ -105,20 +105,17 @@ Erstlauf 2026-05-29 erfolgreich: Renovate erzeugte das Dependency Dashboard und
|
||||
- `renovate/mongo-7.x`
|
||||
- `renovate/postgres-17.x`
|
||||
|
||||
Kontrolllauf 2026-05-31 13:24 MESZ: `rc=0`, Dashboard aktualisiert, keine Minor-/Patch-Nachzuegler offen. Offen bleiben nur Major-PRs:
|
||||
Stand nach den 2026-05-31-Migrationen: PostgreSQL 18, Redis 8 und Immich-Postgres mit VectorChord sind produktiv ausgerollt und in `renovate.json` per `allowedVersions` auf die jeweiligen Major-/Image-Schienen begrenzt. Die Renovate-PRs #9 `renovate/postgres-18.x` und #10 `renovate/redis-8.x` wurden deshalb am 2026-05-31 geschlossen statt gemerged. Offen bleibt als bewusste separate Entscheidung:
|
||||
|
||||
- #7 `renovate/major-major-updates`: Grafana 13
|
||||
- #8 `renovate/mongo-8.x`: Mongo 8 fuer Komodo-Mongo
|
||||
- #9 `renovate/postgres-18.x`: Postgres 18 fuer `postgresql17`, Mealie und Nextcloud
|
||||
- #10 `renovate/redis-8.x`: Redis 8 fuer Immich, Nextcloud und shared Redis
|
||||
|
||||
Diese Major-PRs sind reine Entscheidungsvorlagen und werden nicht automatisch gemerged. Die Komodo-Core-/Periphery-Major-Sperre wurde verifiziert: `komodo-core` und `komodo-periphery` tauchen in keinem Major-PR-Diff auf.
|
||||
Dieser Major-PR ist eine reine Entscheidungsvorlage und wird nicht automatisch gemerged. Komodo-Mongo laeuft bereits auf der erlaubten MongoDB-8.0-Schiene; ein offener Mongo-8-Renovate-PR ist aktuell nicht vorhanden.
|
||||
|
||||
## Erwartete erste PRs (historisch)
|
||||
|
||||
Beim Erstlauf wird Renovate vermutlich PRs fuer einige der digest-gepinnten Images oeffnen, weil diese Digests seit Wochen nicht erneuert wurden. Reihenfolge der Sichtpruefung:
|
||||
|
||||
1. **Stateful Tier-1 zuerst, einzeln**: Postgres, Redis, Mongo, pgvecto-rs - jeder eigener PR, einzeln pruefen und mergen. Smoke-Test nach Merge ueber Komodo-Webhook-Deploy beobachten.
|
||||
1. **Stateful Tier-1 zuerst, einzeln**: Postgres, Redis, Mongo, Immich-Postgres - jeder eigener PR, einzeln pruefen und mergen. Smoke-Test nach Merge ueber Komodo-Webhook-Deploy beobachten.
|
||||
2. **Gruppe minor-and-patch-updates**: Alle anderen Docker-Compose-Images zusammen. Wenn der Diff vernuenftig aussieht, mergen.
|
||||
3. **Gruppe major-updates**: Erst nach Operator-Sichtpruefung pro Image, ggf. zurueckstellen oder manuell entscheiden.
|
||||
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
# Repository Map
|
||||
|
||||
Stand: 2026-05-23
|
||||
Stand: 2026-05-31
|
||||
|
||||
Diese Datei ist eine technische Landkarte des Repositories. Sie wurde aus Markdown-Dokumenten, `docker-compose.yml`-Dateien, Env-Beispielen, Traefik-Dynamic-Configs, Komodo/Periphery-Dateien und Skripten abgeleitet. Sie beschreibt den Repo-Sollzustand, nicht zwingend den Live-Zustand auf dem Host.
|
||||
|
||||
@@ -102,11 +102,11 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
| Stack | Compose | Services / Images | Traefik Hosts | Networks | Ports | Abhaengigkeiten |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Gitea | `core/gitea/docker-compose.yml` | `gitea` -> `docker.gitea.com/gitea:1.25.4@sha256:...` | `git.kaleschke.info` | `frontend_net` | `222:22/tcp` | SQLite in `/data`; SSH-Port ist dokumentierte Ausnahme; `github.com` ist als Mirror-Ziel erlaubt und externe DNS-Resolver sind gesetzt |
|
||||
| Authelia | `security/authelia/docker-compose.yml` | `authelia` -> `authelia/authelia:latest@sha256:...` | `auth.kaleschke.info` | `frontend_net`, `backend_net` | keine | PostgreSQL 17 Storage, Traefik ForwardAuth; bewusst ohne Redis-Session-Backend |
|
||||
| Authelia | `security/authelia/docker-compose.yml` | `authelia` -> `authelia/authelia:latest@sha256:...` | `auth.kaleschke.info` | `frontend_net`, `backend_net` | keine | PostgreSQL 18 Storage im historisch benannten `postgresql17`-Container, Traefik ForwardAuth; bewusst ohne Redis-Session-Backend |
|
||||
| Vaultwarden | `security/vaultwarden/docker-compose.yml` | `vaultwarden` -> `vaultwarden/server:latest@sha256:...` | `vault.kaleschke.info` | `frontend_net` | keine | Datei-Persistenz, `ADMIN_TOKEN_FILE` |
|
||||
| ddns-updater | `infra/ddns-updater/docker-compose.yml` | `ddns-updater` -> `ghcr.io/qdm12/ddns-updater:latest@sha256:...` | keine | `frontend_net` | keine | Cloudflare/API-Internetbedarf |
|
||||
| PostgreSQL 17 | `infra/postgresql17/docker-compose.yml` | `postgresql17` -> `postgres:17.9@sha256:...` | keine | `backend_net` | keine | shared DB-Cluster |
|
||||
| Redis | `infra/redis/docker-compose.yml` | `Redis` -> `redis:7.4-alpine@sha256:...` | keine | `backend_net` | keine | primaer Paperless-Redis (App-Cache); historisch als "shared" angelegt, faktisch nur von Paperless genutzt; Passwort-Datei |
|
||||
| PostgreSQL 18 | `infra/postgresql17/docker-compose.yml` | `postgresql17` -> `postgres:18.4@sha256:8ff36f3c66371cba71d20ceedccfc3de9669a68737607888c4ef0af93abe8e39` | keine | `backend_net` | keine | shared DB-Cluster; Service-Name bleibt historisch `postgresql17` |
|
||||
| Redis | `infra/redis/docker-compose.yml` | `Redis` -> `redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1` | keine | `backend_net` | keine | primaer Paperless-Redis (App-Cache); historisch als "shared" angelegt, faktisch nur von Paperless genutzt; Passwort-Datei |
|
||||
|
||||
### Host Services
|
||||
|
||||
@@ -169,7 +169,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
| Network | Typ / Status | Nutzer |
|
||||
|---|---|---|
|
||||
| `frontend_net` | external bridge | Web-/Proxy-Netz fuer Traefik und alle gerouteten UIs |
|
||||
| `backend_net` | external/internal laut Architektur | PostgreSQL 17, Redis, Authelia, Paperless, Mail Archiver, Traefik |
|
||||
| `backend_net` | external/internal laut Architektur | PostgreSQL 18 (`postgresql17`), Redis 8, Authelia, Paperless, Mail Archiver, Traefik |
|
||||
| `dns_net` | App-/Host-Netz | AdGuard Home und Unbound |
|
||||
| `immich_default` | Compose-intern, `internal: true` | Immich Server, ML, Postgres, Redis |
|
||||
| `mealie_internal` | Compose-intern; Laufzeitname mit Compose-Projektpraefix typischerweise `mealie_mealie_internal` | Mealie und Mealie Postgres |
|
||||
@@ -189,13 +189,13 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
| Gitea | `/mnt/user/services/gitea/data` |
|
||||
| Authelia | `/mnt/user/appdata/authelia/config`, Authelia Secret-Dateien |
|
||||
| Vaultwarden | `/mnt/user/appdata/vaultwarden`, Admin-Token-Datei |
|
||||
| PostgreSQL 17 | `/mnt/user/appdata/postgresql17`, `postgres_password.txt` |
|
||||
| PostgreSQL 18 | `/mnt/user/appdata/postgresql18`, Rollback-Altstand `/mnt/user/appdata/postgresql17`, `postgres_password.txt` |
|
||||
| Redis | `/mnt/user/appdata/redis`, `redis_password.txt` |
|
||||
| Paperless | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/scans_inbox` |
|
||||
| Immich | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`, `/mnt/user/appdata/immich_postgres`, `model-cache` |
|
||||
| Mealie | `/mnt/user/appdata/mealie/data`, `/mnt/user/appdata/mealie/postgres` |
|
||||
| Immich | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`, `/mnt/user/appdata/immich_postgres_vectorchord`, Rollback-Altstand `/mnt/user/appdata/immich_postgres`, `model-cache` |
|
||||
| Mealie | `/mnt/user/appdata/mealie/data`, `/mnt/user/appdata/mealie/postgres18`, Rollback-Altstand `/mnt/user/appdata/mealie/postgres` |
|
||||
| Mail Archiver | `/mnt/user/appdata/mailarchiver/data-protection-keys` |
|
||||
| Nextcloud | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data`, `/mnt/user/appdata/nextcloud/postgres`, `/mnt/user/appdata/nextcloud/redis` |
|
||||
| Nextcloud | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data`, `/mnt/user/appdata/nextcloud/postgres18`, Rollback-Altstand `/mnt/user/appdata/nextcloud/postgres`, `/mnt/user/appdata/nextcloud/redis` |
|
||||
| Plex | `/mnt/user/appdata/plex/config`, `/mnt/user/appdata/plex/transcode`, `/mnt/user/media`, `/mnt/user/photos` |
|
||||
| ntfy | `/mnt/user/appdata/ntfy` |
|
||||
| Paperless-GPT | `/mnt/user/appdata/paperless-gpt/data`, `/mnt/user/appdata/paperless-gpt/prompts` |
|
||||
@@ -219,7 +219,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
||||
| Traefik | `cloudflare_dns_api_token` als Docker Secret / `CF_DNS_API_TOKEN_FILE` |
|
||||
| Authelia | JWT, Session, Storage Encryption, Postgres Password via `_FILE` |
|
||||
| Vaultwarden | `ADMIN_TOKEN_FILE` |
|
||||
| PostgreSQL 17 | `POSTGRES_PASSWORD_FILE` |
|
||||
| PostgreSQL 18 | `POSTGRES_PASSWORD_FILE` |
|
||||
| Redis | Passwort-Datei und Startkommando |
|
||||
| Paperless | `PAPERLESS_DBPASS`, `PAPERLESS_REDIS` als Komodo Stack ENV |
|
||||
| Immich | `IMMICH_DB_PASSWORD` Stack ENV; `immich_postgres_password.txt` fuer Postgres |
|
||||
@@ -251,7 +251,7 @@ Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei An
|
||||
- Authelia `configuration.yml` ist Repo-Baseline fuer nicht geheime Einstellungen, wird aber nicht automatisch von Komodo auf den Host kopiert. Die produktive Host-Datei kann zusaetzliche OIDC-/Secret-Konfiguration enthalten; Aenderungen muessen manuell gemerged und validiert werden.
|
||||
- `backend_net` ist in der Architektur als `internal: true` beschrieben; einzelne Compose-Dateien referenzieren es external. Live-Netz-Attribute bei Drift-Fragen pruefen.
|
||||
- Einige Images bleiben trotz Digest-Pin semantisch auf mutable Tags (`latest@sha256`, `release@sha256`). Das ist bewusst dokumentiert, aber bei Updates gesondert pruefen.
|
||||
- Stateful Datenhalter sind seit 2026-05-05 bevorzugt mit Minor-/Patch-Tag plus Digest gepinnt; Redis-Caches wurden im Hardening-Sprint 2026-05-16 auf `redis:7.4-alpine@sha256:...` vereinheitlicht.
|
||||
- Stateful Datenhalter sind seit 2026-05-05 bevorzugt mit Minor-/Patch-Tag plus Digest gepinnt; PostgreSQL-17-Datenhalter wurden am 2026-05-31 per Dump/Restore auf PostgreSQL 18 gehoben, Redis-Caches auf Redis 8.8, Immich-Postgres bleibt auf PG14 mit VectorChord.
|
||||
- `scrutiny` bleibt `privileged: true`; dokumentierte Ausnahme, aber weiterhin pruefenswert.
|
||||
- `tailscale` nutzt Host-Netz, `NET_ADMIN`, `NET_RAW` und `/dev/net/tun` als dokumentierte VPN-Ausnahme.
|
||||
- `monitoring-influxdb3-core` laeuft aktuell als `user: "0"`; UID/GID-Hardening nur als eigener Sprint.
|
||||
|
||||
+16
-8
@@ -30,9 +30,9 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`.
|
||||
| Traefik | Share / Borg | `/mnt/user/appdata/traefik`, besonders `dynamic/`, `letsencrypt`, `secrets` | keine eigene DB | `cloudflare_dns_api_token` | `frontend_net`, `backend_net` | `https://traefik.kaleschke.info` erreichbar, Dashboard ueber Authelia |
|
||||
| AdGuard Home | Share / Borg | `/mnt/user/appdata/adguard/conf` | keine | keine zusaetzlichen Repo-Secrets dokumentiert | `dns_net`, `frontend_net` | DNS-Aufloesung funktioniert |
|
||||
| Tailscale | Share / Borg | `/mnt/user/appdata/tailscale` | keine | Tailscale-State im Pfad | Host-Netz | Tailscale verbunden |
|
||||
| PostgreSQL 17 | Share + Dumps | `/mnt/user/appdata/postgresql17` | `postgresql17-globals.sql`, `postgresql17-mailarchiver.dump`, `postgresql17-paperless.dump`, optional `postgresql17-authelia.dump` | `postgres_password.txt` | `backend_net` | DB startet, Ziel-Datenbanken vorhanden |
|
||||
| Redis | Share / Host | `/mnt/user/appdata/redis` | keine | `redis_password.txt` | `backend_net` | Redis startet, Apps verbinden sich |
|
||||
| Authelia | Borg | `/mnt/user/appdata/authelia/config`, `/mnt/user/appdata/secrets/*authelia*` | Shared PostgreSQL, optional Dump `postgresql17-authelia.dump` | JWT/Session/Storage/Postgres-/SMTP-Secret-Dateien | PostgreSQL 17, Traefik, GMX SMTP | Login-Seite und ForwardAuth funktionieren; SMTP-Notifier startet; aktive Sessions werden nach Restart neu aufgebaut |
|
||||
| PostgreSQL 18 | Share + Dumps | `/mnt/user/appdata/postgresql18` (Rollback-Altstand: `/mnt/user/appdata/postgresql17`) | `postgresql17-globals.sql`, `postgresql17-mailarchiver.dump`, `postgresql17-paperless.dump`, optional `postgresql17-authelia.dump` | `postgres_password.txt`, App-Rollen-Passwoerter aus den jeweiligen Stack-ENV/Secret-Dateien | `backend_net` | DB startet, Ziel-Datenbanken vorhanden; `SHOW data_checksums` ist `on` |
|
||||
| Redis 8 | Share / Host | `/mnt/user/appdata/redis`; Rollback-Backup unter `/mnt/user/backups/borg/dumps/latest/shared-redis-pre-redis8-<ts>` | RDB/AOF-Dateien im Datenpfad | `redis_password.txt` | `backend_net` | Redis startet, `redis_version` ist 8.x, Apps verbinden sich |
|
||||
| Authelia | Borg | `/mnt/user/appdata/authelia/config`, `/mnt/user/appdata/secrets/*authelia*` | Shared PostgreSQL 18, optional Dump `postgresql17-authelia.dump` | JWT/Session/Storage/Postgres-/SMTP-Secret-Dateien | PostgreSQL 18, Traefik, GMX SMTP | Login-Seite und ForwardAuth funktionieren; SMTP-Notifier startet; aktive Sessions werden nach Restart neu aufgebaut |
|
||||
| Gitea | GitHub-Mirror + Gitea-Bundles fuer Repo-Bootstrap, Borg + Dump fuer Gitea-Appstate | `/mnt/user/services/gitea/data`, `/mnt/user/backups/git-bundles/gitea` | `gitea.sqlite.dump`, Bundle-Report `latest-report.md` | `borg_repo_passphrase.txt` fuer Restore-Tests; GitHub-Push-Mirror-PAT liegt nur in Gitea-Mirror-Settings | Traefik | Web-UI erreichbar, Repo sichtbar, SSH-Port reagiert; Bundle laesst sich klonen und `git fsck` ist sauber; GitHub-Push-Mirror synchronisiert ohne `last_error`; Mini-Restore nach `/mnt/user/backups/restore-lab/gitea` am 2026-05-07 erfolgreich validiert |
|
||||
| Komodo | Borg / Share | `/mnt/user/appdata/komodo/core`, `/mnt/user/appdata/komodo/periphery`, `/mnt/user/services/stacks` | `komodo-mongo.archive.gz` falls verifiziert | `komodo_mongo_password.txt`, `KOMODO_*` Stack ENV | Traefik, Mongo, Gitea | UI erreichbar, Periphery verbunden |
|
||||
| GitOps Host Automation | Borg / Git | `/mnt/user/services/homelab-infra`, `/mnt/user/services/posture-check` | keine eigene DB | keine | Gitea, Komodo, Unraid User Scripts | `posture-check` laeuft vom Host-Pfad und liefert `warning_count: 0` im bekannten Uebergangszustand |
|
||||
@@ -44,11 +44,11 @@ Sie ist die fachliche Ergaenzung zu `docs/DISASTER_RECOVERY.md`.
|
||||
|
||||
| Dienst | Fuehrende Quelle | Datei-Restore | Dump / DB | Secrets / ENV | Abhaengigkeiten | Smoke-Test |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Paperless-ngx | Borg + Dumps | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/paperless/export`, `/mnt/user/documents/scans_inbox` | `postgresql17-paperless.dump` | `PAPERLESS_DBPASS`, `PAPERLESS_REDIS`, `borg_repo_passphrase.txt` fuer Restore-Tests | PostgreSQL 17, Redis, Traefik | Web-UI startet, Dokumente vorhanden; Mini-Restore nach `/mnt/user/backups/restore-lab/paperless` am 2026-05-07 erfolgreich validiert |
|
||||
| Mealie | Borg + Dump | `/mnt/user/appdata/mealie/data`, optional `/mnt/user/appdata/mealie/postgres` bei lokalem Share-Weiterbetrieb | `mealie.dump` | `mealie_postgres_password.txt` | `mealie-postgres`, Traefik | UI startet, Rezepte vorhanden |
|
||||
| Immich | Borg + Dump | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive` | `immich.dump` | `IMMICH_DB_PASSWORD`, `immich_postgres_password.txt`, `borg_repo_passphrase.txt` fuer Restore-Tests | `immich_postgres`, `immich_redis`, Traefik | DB- und UI-Smoke gegen produktives Borg-Archiv am 2026-05-27 erfolgreich validiert: `immich.dump` extrahiert, isolierter pgvecto-rs-Postgres importiert, Immich-Loginseite HTTP 200, `11977` Assets und `1` User im Test-DB-Check; Report `/mnt/user/backups/restore-reports/immich-2026-05-27.md`. Voll-Restore der Foto-Dateien bleibt separater DR-Drill |
|
||||
| Mail-Archiver | Borg + Shared Dump | `/mnt/user/appdata/mailarchiver/data-protection-keys` | `postgresql17-mailarchiver.dump` | `MAILARCHIVER_DB_CONNECTION`, `MAILARCHIVER_AUTH_PASSWORD` | PostgreSQL 17, Traefik, Authelia | Authelia-Weiterleitung greift; nach Login startet die Web-UI und das Archiv laesst sich oeffnen |
|
||||
| Nextcloud | Borg + Dump | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data` | `nextcloud.dump` | `nextcloud_admin_user.txt`, `nextcloud_admin_password.txt`, `nextcloud_postgres_password.txt` | `nextcloud-postgres`, `nextcloud-redis`, Traefik | Web-UI startet, Login funktioniert, Dateien sichtbar |
|
||||
| Paperless-ngx | Borg + Dumps | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/paperless/export`, `/mnt/user/documents/scans_inbox` | `postgresql17-paperless.dump` | `PAPERLESS_DBPASS`, `PAPERLESS_REDIS`, `borg_repo_passphrase.txt` fuer Restore-Tests | PostgreSQL 18, Redis, Traefik | Web-UI startet, Dokumente vorhanden; Mini-Restore nach `/mnt/user/backups/restore-lab/paperless` am 2026-05-07 erfolgreich validiert |
|
||||
| Mealie | Borg + Dump | `/mnt/user/appdata/mealie/data`, `/mnt/user/appdata/mealie/postgres18` (Rollback-Altstand: `/mnt/user/appdata/mealie/postgres`) | `mealie.dump` | `mealie_postgres_password.txt` | `mealie-postgres`, Traefik | UI startet, Rezepte vorhanden |
|
||||
| Immich | Borg + Dump | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`, `/mnt/user/appdata/immich_postgres_vectorchord`; Rollback-Altstand: `/mnt/user/appdata/immich_postgres` | `immich.dump`; nach VectorChord braucht ein Restore ein Postgres-Image mit VectorChord | `IMMICH_DB_PASSWORD`, `immich_postgres_password.txt`, `borg_repo_passphrase.txt` fuer Restore-Tests | `immich_postgres`, `immich_redis`, Traefik | DB- und UI-Smoke gegen produktives Borg-Archiv am 2026-05-27 erfolgreich validiert; VectorChord-Migration am 2026-05-31: `11977` Assets, `11107` Smart-Search-Zeilen, `7092` Face-Search-Zeilen, `vchord 0.4.3`, `vector 0.8.1`, HTTP/API-Smoke 200. Voll-Restore der Foto-Dateien bleibt separater DR-Drill |
|
||||
| Mail-Archiver | Borg + Shared Dump | `/mnt/user/appdata/mailarchiver/data-protection-keys` | `postgresql17-mailarchiver.dump` | `MAILARCHIVER_DB_CONNECTION`, `MAILARCHIVER_AUTH_PASSWORD` | PostgreSQL 18, Traefik, Authelia | Authelia-Weiterleitung greift; nach Login startet die Web-UI und das Archiv laesst sich oeffnen |
|
||||
| Nextcloud | Borg + Dump | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data`, `/mnt/user/appdata/nextcloud/postgres18` (Rollback-Altstand: `/mnt/user/appdata/nextcloud/postgres`), `/mnt/user/appdata/nextcloud/redis` | `nextcloud.dump`; Redis-Backup vor Redis-8-Cutover unter `/mnt/user/backups/borg/dumps/latest/nextcloud-redis-pre-redis8-<ts>` | `nextcloud_admin_user.txt`, `nextcloud_admin_password.txt`, `nextcloud_postgres_password.txt`; produktive DB-Rolle laut `config.php` ist `oc_admin` | `nextcloud-postgres`, `nextcloud-redis`, Traefik | Web-UI startet, Login funktioniert, Dateien sichtbar; `occ status` zeigt `maintenance: false` |
|
||||
| Glance | Git / Borg-Repo | Repo-Konfiguration unter `ops/glance/config/glance.yml`; keine kritische Datenpersistenz | keine | `GLANCE_IMMICH_API_KEY`, `GLANCE_ADGUARD_USERNAME`, `GLANCE_ADGUARD_PASSWORD`, `GLANCE_SPEEDTEST_API_KEY` | Traefik, Authelia, optional interne API-Ziele | Dashboard startet, Widgets laden, Docker-Status laeuft nur ueber `glance-docker-socket-proxy` |
|
||||
| ntfy | Borg / Share | `/mnt/user/appdata/ntfy` | keine | keine besonderen Secret-Dateien dokumentiert | Traefik | UI und Push-Endpunkt erreichbar |
|
||||
| Paperless-GPT | Borg / Share | `/mnt/user/appdata/paperless-gpt` | keine eigene DB | `PAPERLESS_API_TOKEN` | Traefik, Paperless | UI startet, Konfiguration vorhanden |
|
||||
@@ -97,6 +97,14 @@ Aktuell relevante Dump-Artefakte unter `/mnt/user/backups/borg/dumps/latest`:
|
||||
|
||||
Die Dump-Erzeugung ist host-seitig ueber `ops/borg-ui/scripts/pre-backup-dumps.sh` vorgesehen.
|
||||
|
||||
### PostgreSQL 18 Restore- und Rollback-Regeln
|
||||
|
||||
- PostgreSQL-18-Container verwenden das Docker-Image-Layout mit Mount auf `/var/lib/postgresql` und `PGDATA=/var/lib/postgresql/18/docker`.
|
||||
- Die alten PostgreSQL-17-Datenpfade bleiben nach dem Major-Upgrade als Rollback-Altstand erhalten und duerfen erst nach separater Freigabe geloescht werden.
|
||||
- Shared-Cluster-Restore: zuerst `pg_dumpall --globals-only` einspielen, dann die einzelnen Custom-Format-Dumps per `pg_restore`. Der Bootstrap-Rollenkonflikt fuer `mailarchiver` ist benign, solange `CREATE ROLE mailarchiver;` gezielt ausgelassen und das folgende `ALTER ROLE mailarchiver ...` eingespielt wird.
|
||||
- Nextcloud-Restore: vor dem Dump `occ maintenance:mode --on`, nach erfolgreichem Restore und `occ status` wieder `occ maintenance:mode --off`. Die Rolle `oc_admin` muss mit dem in `config.php` hinterlegten DB-Passwort existieren.
|
||||
- Rollback: betroffene App(s) und DB stoppen, Compose auf das vorherige PostgreSQL-17-Image und den alten Datenpfad zuruecksetzen, dann DB und App wieder starten.
|
||||
|
||||
---
|
||||
|
||||
## Praktische Restore-Regeln
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb
|
||||
|---|---|---|---|
|
||||
| Vaultwarden | `ADMIN_TOKEN` | `/mnt/user/appdata/secrets/vaultwarden_admin_token.txt` -> `ADMIN_TOKEN_FILE` | aktiv |
|
||||
| Traefik | Cloudflare DNS API Token | `/mnt/user/appdata/traefik/secrets/cloudflare_dns_api_token` -> Docker Secret `cloudflare_dns_api_token` | aktiv |
|
||||
| PostgreSQL 17 | DB Password | `/mnt/user/appdata/secrets/postgres_password.txt` -> `POSTGRES_PASSWORD_FILE` | aktiv |
|
||||
| PostgreSQL 18 | DB Password | `/mnt/user/appdata/secrets/postgres_password.txt` -> `POSTGRES_PASSWORD_FILE` | aktiv |
|
||||
| Redis | Passwort | `/mnt/user/appdata/secrets/redis_password.txt` -> Datei-Mount + Startkommando in `infra/redis/docker-compose.yml` | aktiv |
|
||||
| Mealie | DB Password | `/mnt/user/appdata/secrets/mealie_postgres_password.txt` -> nicht versionierte Stack-`.env` `${MEALIE_POSTGRES_PASSWORD}` -> `POSTGRES_PASSWORD` | aktiv |
|
||||
| mealie-postgres | DB Password | `/mnt/user/appdata/secrets/mealie_postgres_password.txt` -> `POSTGRES_PASSWORD_FILE` | aktiv |
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
# Service Catalog
|
||||
|
||||
Stand: 2026-05-23
|
||||
Stand: 2026-05-31
|
||||
|
||||
Dieser Katalog beschreibt produktive und repo-vorbereitete Dienste aus Sicht von Betrieb, Restore und KI-Kontext. Er basiert auf dem Repo-Sollzustand. Vor produktiven Eingriffen immer den Live-Zustand in Komodo/Docker pruefen.
|
||||
|
||||
@@ -20,33 +20,33 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
|
||||
|
||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| `authelia` | ForwardAuth / zentrale Auth fuer Admin-UIs | `security/authelia/docker-compose.yml`, `security/authelia/configuration.yml` | `https://auth.kaleschke.info` | PostgreSQL 17, Traefik, GMX SMTP | `/mnt/user/appdata/authelia/config`, Authelia Secret-Dateien | Tier 1, config + DB + secrets | ja | Bewusst ohne Redis-Session-Backend; SMTP-Notifier via GMX und `authelia_smtp_password.txt`; explizite DNS-Server fuer SMTP/NTP; Repo-Baseline muss manuell in die Host-Config gemerged werden, OIDC/Secrets bleiben hostseitig; Access-Control und Compose-Middleware bei Aenderungen abgleichen |
|
||||
| `authelia` | ForwardAuth / zentrale Auth fuer Admin-UIs | `security/authelia/docker-compose.yml`, `security/authelia/configuration.yml` | `https://auth.kaleschke.info` | PostgreSQL 18, Traefik, GMX SMTP | `/mnt/user/appdata/authelia/config`, Authelia Secret-Dateien | Tier 1, config + DB + secrets | ja | Bewusst ohne Redis-Session-Backend; SMTP-Notifier via GMX und `authelia_smtp_password.txt`; explizite DNS-Server fuer SMTP/NTP; Repo-Baseline muss manuell in die Host-Config gemerged werden, OIDC/Secrets bleiben hostseitig; Access-Control und Compose-Middleware bei Aenderungen abgleichen |
|
||||
| `vaultwarden` | Passwort-Tresor | `security/vaultwarden/docker-compose.yml` | `https://vault.kaleschke.info` | Traefik, `frontend_net` | `/mnt/user/appdata/vaultwarden` | Tier 1, `vaultwarden.sqlite.dump` + Share | ja | `ADMIN_TOKEN_FILE`; keine direkten Ports |
|
||||
|
||||
## Shared Infrastructure
|
||||
|
||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| `postgresql17` | shared PostgreSQL Cluster | `infra/postgresql17/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/postgresql17`, `postgres_password.txt` | Tier 1; Dumps unter `/mnt/user/backups/borg/dumps/latest` | nein | keine Host-Ports; raw DB nicht primaerer Restore-Weg |
|
||||
| `Redis` | primaer Paperless-Redis (App-Cache); historisch als "shared" angelegt, faktisch nur von Paperless genutzt | `infra/redis/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/redis`, `redis_password.txt` | transiente Daten, bewusst nicht kritisch | nein | Passwort-Datei; optional named volume offen. Immich, Nextcloud und Mealie nutzen jeweils eigene Redis-Instanzen; Authelia laeuft bewusst ohne Redis-Session-Backend. Bei Wegfall ist Paperless der einzige betroffene Stack. |
|
||||
| `postgresql17` | shared PostgreSQL 18 Cluster (historischer Service-Name bleibt fuer DNS/Clients stabil) | `infra/postgresql17/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/postgresql18`, Rollback-Altstand `/mnt/user/appdata/postgresql17`, `postgres_password.txt` | Tier 1; Dumps unter `/mnt/user/backups/borg/dumps/latest` | nein | keine Host-Ports; raw DB nicht primaerer Restore-Weg |
|
||||
| `Redis` | primaer Paperless-Redis (App-Cache); historisch als "shared" angelegt, faktisch nur von Paperless genutzt | `infra/redis/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/redis`, `redis_password.txt` | transiente Daten, bewusst nicht kritisch | nein | Redis 8.8; Passwort-Datei; optional named volume offen. Immich, Nextcloud und Mealie nutzen jeweils eigene Redis-Instanzen; Authelia laeuft bewusst ohne Redis-Session-Backend. Bei Wegfall ist Paperless der einzige betroffene Stack. |
|
||||
| `ddns-updater` | Cloudflare/DDNS Aktualisierung | `infra/ddns-updater/docker-compose.yml` | intern | Internetzugang, `frontend_net` | `/mnt/user/appdata/ddns-updater` | rebuildbar | nein | bleibt bewusst in `frontend_net`, weil `backend_net` internal ist |
|
||||
|
||||
## Public / User Apps
|
||||
|
||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| `paperless-ngx` | Dokumentenmanagement | `apps/paperless/docker-compose.yml` | `https://paperless.kaleschke.info` | PostgreSQL 17, Redis, Traefik | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/scans_inbox` | Tier 2, Borg + `postgresql17-paperless.dump` | ja | DB/Redis Secrets bleiben bewusst Stack ENV |
|
||||
| `paperless-ngx` | Dokumentenmanagement | `apps/paperless/docker-compose.yml` | `https://paperless.kaleschke.info` | PostgreSQL 18, Redis 8, Traefik | `/mnt/user/appdata/paperless-ngx/data`, `/mnt/user/documents/paperless`, `/mnt/user/documents/scans_inbox` | Tier 2, Borg + `postgresql17-paperless.dump` | ja | DB/Redis Secrets bleiben bewusst Stack ENV; Dump-Dateiname behaelt den historischen Cluster-Namen |
|
||||
| `paperless-gpt` | KI-Ergaenzung fuer Paperless | `apps/paperless-gpt/docker-compose.yml` | `https://paperless-gpt.kaleschke.info` | Paperless API, LLM/Ollama, Traefik | `/mnt/user/appdata/paperless-gpt/data`, `/mnt/user/appdata/paperless-gpt/prompts` | Tier 2 | ja + Authelia | API Token als Stack ENV; OCR/LLM-Konfig bei Aenderungen pruefen. **Behalten-Entscheidung 2026-05-28:** Container bleibt aktiv, auch wenn aktuell keine Traefik-Zugriffe in der Woche; Ablouseplanung erst mit Paperless-NGX 3.0 (eigene KI-Features erwartet) - dann neu bewerten. |
|
||||
| `immich_server` | Foto-/Video-App | `apps/immich/docker-compose.yml` | `https://immich.kaleschke.info` | Immich Postgres, Immich Redis, ML, Traefik | `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive` | Tier 2, Borg + `immich.dump` | ja | native App-Auth; externes Fotoarchiv gemountet |
|
||||
| `immich_postgres` | Immich-Datenbank | `apps/immich/docker-compose.yml` | intern | `immich_default` | `/mnt/user/appdata/immich_postgres`, `immich_postgres_password.txt` | Dump `immich.dump` | nein | nie ins `frontend_net` |
|
||||
| `immich_redis` | Immich Cache | `apps/immich/docker-compose.yml` | intern | `immich_default` | kein kritischer Pfad dokumentiert | rebuildbar | nein | Architektur nennt anonymes Volume -> named volume als offenes Thema |
|
||||
| `immich_postgres` | Immich-Datenbank | `apps/immich/docker-compose.yml` | intern | `immich_default` | `/mnt/user/appdata/immich_postgres_vectorchord`, Rollback-Altstand `/mnt/user/appdata/immich_postgres`, `immich_postgres_password.txt` | Dump `immich.dump`; Restore braucht ein Image mit VectorChord/pgvector | nein | PG14 bleibt bewusst; Immich-DB-Image `ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0`; nie ins `frontend_net` |
|
||||
| `immich_redis` | Immich Cache | `apps/immich/docker-compose.yml` | intern | `immich_default` | kein kritischer Pfad dokumentiert | rebuildbar | nein | Redis 8.8; Architektur nennt anonymes Volume -> named volume als offenes Thema |
|
||||
| `immich_machine_learning` | Immich ML | `apps/immich/docker-compose.yml` | intern | `immich_default` | `model-cache` | rebuildbar | nein | intern-only |
|
||||
| `mealie` | Rezeptverwaltung | `apps/mealie/docker-compose.yml` | `https://mealie.kaleschke.info` | `mealie-postgres`, Traefik | `/mnt/user/appdata/mealie/data` | Tier 2, Borg + `mealie.dump` | ja | App + DB in internem Netz getrennt |
|
||||
| `mealie-postgres` | Mealie-Datenbank | `apps/mealie/docker-compose.yml` | intern | `mealie_internal` | `/mnt/user/appdata/mealie/postgres`, `mealie_postgres_password.txt` | Dump `mealie.dump` | nein | interne DB |
|
||||
| `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 17, Internet/IMAP, Traefik, Authelia | `/mnt/user/appdata/mailarchiver/data-protection-keys` | Tier 2, `postgresql17-mailarchiver.dump` | ja + Authelia | Hybrid-Dienst: `frontend_net` fuer Internet, `backend_net` fuer DB; App-eigene Auth bleibt zusaetzliche Schutzschicht |
|
||||
| `mealie-postgres` | Mealie-Datenbank | `apps/mealie/docker-compose.yml` | intern | `mealie_internal` | `/mnt/user/appdata/mealie/postgres18`, Rollback-Altstand `/mnt/user/appdata/mealie/postgres`, `mealie_postgres_password.txt` | Dump `mealie.dump` | nein | interne DB; PostgreSQL 18 |
|
||||
| `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 18, Internet/IMAP, Traefik, Authelia | `/mnt/user/appdata/mailarchiver/data-protection-keys` | Tier 2, `postgresql17-mailarchiver.dump` | ja + Authelia | Hybrid-Dienst: `frontend_net` fuer Internet, `backend_net` fuer DB; App-eigene Auth bleibt zusaetzliche Schutzschicht; Dump-Dateiname behaelt den historischen Cluster-Namen |
|
||||
| `nextcloud` | Datei-/Cloud-Dienst | `apps/nextcloud/docker-compose.yml` | `https://cloud.kaleschke.info` | eigene PostgreSQL, eigene Redis, Traefik | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data` | Tier 2, `nextcloud.dump` + Share | ja | native App-Auth ohne zentrale ForwardAuth; WebDAV/CardDAV beachten |
|
||||
| `nextcloud-postgres` | Nextcloud-Datenbank | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/postgres`, `nextcloud_postgres_password.txt` | `nextcloud.dump`, raw DB nicht primaerer Restore-Weg | nein | interne DB |
|
||||
| `nextcloud-redis` | Nextcloud Cache/Locking | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/redis` | Teil von Nextcloud-Restore | nein | interne Redis |
|
||||
| `nextcloud-postgres` | Nextcloud-Datenbank | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/postgres18`, Rollback-Altstand `/mnt/user/appdata/nextcloud/postgres`, `nextcloud_postgres_password.txt` | `nextcloud.dump`, raw DB nicht primaerer Restore-Weg | nein | interne DB; PostgreSQL 18 |
|
||||
| `nextcloud-redis` | Nextcloud Cache/Locking | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/redis` | Teil von Nextcloud-Restore | nein | interne Redis 8.8 |
|
||||
| `plex` | Medienserver mit LAN-/Client-Discovery | `host-services/plex/docker-compose.yml` | Plex native, **LAN/Tailscale-only**, Remote Access deaktiviert | Host-Netz | `/mnt/user/appdata/plex/config`, `/mnt/user/appdata/plex/transcode`, `/mnt/user/media`, `/mnt/user/photos` | Tier 2, Appdata + Medienpfade im Borg-/Share-Scope | nein | Repo-Compose-Stack; `network_mode: host` bleibt dokumentierte Discovery-Ausnahme. Server geclaimt von `Xeridos` (Reclaim 2026-05-28 nach Preferences-Reset vom 18.05.). Smart-TVs greifen ueber WLAN-LAN per mDNS/Plex-GDM direkt zu. `PublishServerOnPlexOnlineKey=0` (Remote Access aus), `RelayEnabled` ebenfalls aus. |
|
||||
| `ntfy` | Push-Benachrichtigungen | `apps/ntfy/docker-compose.yml` | `https://ntfy.kaleschke.info` | Traefik, upstream mobile push | `/mnt/user/appdata/ntfy` | Tier 2 | ja | `NTFY_BEHIND_PROXY=true`; Problem-Alerts gehen gebuendelt an `homelab-alerts`, optionale Erfolgsmeldungen an `homelab-info` |
|
||||
| `bentopdf` | PDF-Tooling / Ersatz fuer Stirling-PDF | `apps/bentopdf/docker-compose.yml` | `https://pdf.kaleschke.info` | Traefik + Authelia | keine kritische Persistenz im Compose | Tier 3, rebuildbar | ja + Authelia | COOP/COEP per Middleware. **Behalten-Entscheidung 2026-05-28:** Container bleibt aktiv als situatives Tool, auch wenn aktuell keine Traefik-Zugriffe in der Woche. Resource-Footprint vernachlaessigbar (~4 MB RAM). |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
postgresql17:
|
||||
image: postgres:17.10@sha256:0027bef26712baaee437a4ea48fdf3d2d2e2bc5f0d81615374408ca320f3c7e3
|
||||
image: postgres:18.4@sha256:8ff36f3c66371cba71d20ceedccfc3de9669a68737607888c4ef0af93abe8e39
|
||||
container_name: postgresql17
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -9,10 +9,10 @@ services:
|
||||
POSTGRES_USER: mailarchiver
|
||||
POSTGRES_DB: mailarchiver
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
PGDATA: /var/lib/postgresql/18/docker
|
||||
|
||||
volumes:
|
||||
- /mnt/user/appdata/postgresql17:/var/lib/postgresql/data
|
||||
- /mnt/user/appdata/postgresql18:/var/lib/postgresql
|
||||
- /mnt/user/appdata/secrets/postgres_password.txt:/run/secrets/postgres_password:ro
|
||||
|
||||
networks:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
redis:
|
||||
image: redis:7.4-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99
|
||||
image: redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1
|
||||
container_name: Redis
|
||||
restart: unless-stopped
|
||||
command:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Borg Backup Scope for KalliLabcore
|
||||
|
||||
Stand: 2026-05-16
|
||||
Stand: 2026-05-31
|
||||
|
||||
This file defines the target state for replacing Backrest with Borg in this homelab.
|
||||
|
||||
@@ -69,7 +69,7 @@ The live Unraid User Scripts execute repo scripts from `/mnt/user/services/homel
|
||||
|
||||
## Database Dumps Required
|
||||
|
||||
### Shared PostgreSQL (`postgresql17`)
|
||||
### Shared PostgreSQL (`postgresql17`, runtime PostgreSQL 18)
|
||||
|
||||
- `mailarchiver`
|
||||
- `paperless`
|
||||
@@ -91,9 +91,13 @@ The live Unraid User Scripts execute repo scripts from `/mnt/user/services/homel
|
||||
## Explicitly Not Backed Up as Raw Live DB Files
|
||||
|
||||
- `/mnt/user/appdata/postgresql17`
|
||||
- `/mnt/user/appdata/postgresql18`
|
||||
- `/mnt/user/appdata/mealie/postgres`
|
||||
- `/mnt/user/appdata/mealie/postgres18`
|
||||
- `/mnt/user/appdata/immich_postgres`
|
||||
- `/mnt/user/appdata/immich_postgres_vectorchord`
|
||||
- `/mnt/user/appdata/nextcloud/postgres`
|
||||
- `/mnt/user/appdata/nextcloud/postgres18`
|
||||
- `/mnt/user/appdata/komodo/mongo`
|
||||
- `/mnt/user/appdata/redis`
|
||||
- `/mnt/user/appdata/scrutiny/influxdb`
|
||||
|
||||
@@ -278,7 +278,7 @@ main() {
|
||||
need_cmd sha256sum
|
||||
ensure_dirs
|
||||
|
||||
# Shared PostgreSQL 17
|
||||
# Shared PostgreSQL 18 (historischer Containername: postgresql17)
|
||||
if need_container "postgresql17"; then
|
||||
# Use the cluster admin/superuser for all shared-cluster dumps. The
|
||||
# application roles exist, but they can have different passwords from the
|
||||
|
||||
@@ -473,7 +473,7 @@ pages:
|
||||
category: core
|
||||
hide: false
|
||||
postgresql17:
|
||||
name: PostgreSQL 17
|
||||
name: PostgreSQL 18
|
||||
icon: si:postgresql
|
||||
description: Shared DB
|
||||
category: core
|
||||
|
||||
@@ -90,16 +90,16 @@
|
||||
"notes": "ADMIN_TOKEN_FILE; keine direkten Host-Ports"
|
||||
},
|
||||
"postgresql17": {
|
||||
"description": "Shared PostgreSQL Cluster",
|
||||
"description": "Shared PostgreSQL 18 Cluster (historischer Containername)",
|
||||
"tier": 1,
|
||||
"category": "infra",
|
||||
"container_name": "postgresql17",
|
||||
"dependencies": [],
|
||||
"url": null,
|
||||
"dump_file": null,
|
||||
"data_paths": ["/mnt/user/appdata/postgresql17"],
|
||||
"data_paths": ["/mnt/user/appdata/postgresql18"],
|
||||
"first_check": "backend_net Konnektivitaet? Disk-Space auf /mnt/user/appdata? pg_isready im Container?",
|
||||
"notes": "Dumps per Dienst unter dumps/latest; raw DB nicht primaerer Restore-Weg"
|
||||
"notes": "Dumps per Dienst unter dumps/latest; raw DB nicht primaerer Restore-Weg; alter PG17-Pfad bleibt nur Rollback-Altstand"
|
||||
},
|
||||
"komodo-core": {
|
||||
"description": "GitOps UI / API / Stack-Manager",
|
||||
@@ -200,9 +200,9 @@
|
||||
"dependencies": [],
|
||||
"url": null,
|
||||
"dump_file": "immich.dump",
|
||||
"data_paths": ["/mnt/user/appdata/immich_postgres"],
|
||||
"data_paths": ["/mnt/user/appdata/immich_postgres_vectorchord"],
|
||||
"first_check": "immich_default Netz? Disk-Space? pg_isready?",
|
||||
"notes": "nie ins frontend_net; immich_default Netz isoliert"
|
||||
"notes": "PG14 mit VectorChord/pgvector; nie ins frontend_net; immich_default Netz isoliert; alter immich_postgres-Pfad bleibt nur Rollback-Altstand"
|
||||
},
|
||||
"immich_redis": {
|
||||
"description": "Immich Cache",
|
||||
@@ -248,7 +248,7 @@
|
||||
"dependencies": [],
|
||||
"url": null,
|
||||
"dump_file": "mealie.dump",
|
||||
"data_paths": ["/mnt/user/appdata/mealie/postgres"],
|
||||
"data_paths": ["/mnt/user/appdata/mealie/postgres18"],
|
||||
"first_check": "mealie_internal Netz? Disk-Space?",
|
||||
"notes": "interne DB; mealie_internal Netz"
|
||||
},
|
||||
@@ -287,7 +287,7 @@
|
||||
"dependencies": [],
|
||||
"url": null,
|
||||
"dump_file": null,
|
||||
"data_paths": ["/mnt/user/appdata/nextcloud/postgres"],
|
||||
"data_paths": ["/mnt/user/appdata/nextcloud/postgres18"],
|
||||
"first_check": "nextcloud_internal Netz? Disk-Space?",
|
||||
"notes": "interne DB"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# services.yaml — Maschinenlesbare Wissensbasis fuer Hermes Alert Enrichment
|
||||
#
|
||||
# Abgeleitet aus docs/SERVICE_CATALOG.md
|
||||
# Stand: 2026-05-06
|
||||
# Stand: 2026-05-31
|
||||
#
|
||||
# Zweck: Hermes laedt diese Datei beim Alert-Anreichern, um Abhaengigkeiten,
|
||||
# Dump-Zeitstempel und den ersten Diagnoseschritt nachzuschlagen.
|
||||
@@ -128,7 +128,7 @@ services:
|
||||
notes: "ADMIN_TOKEN_FILE; keine direkten Host-Ports"
|
||||
|
||||
postgresql17:
|
||||
description: Shared PostgreSQL Cluster (Authelia, Paperless, Mail-Archiver, Mealie, Komodo indirekt)
|
||||
description: Shared PostgreSQL 18 Cluster (historischer Containername; Authelia, Paperless, Mail-Archiver)
|
||||
tier: 1
|
||||
category: infra
|
||||
container_name: postgresql17
|
||||
@@ -136,9 +136,9 @@ services:
|
||||
url: null
|
||||
dump_file: null
|
||||
data_paths:
|
||||
- /mnt/user/appdata/postgresql17
|
||||
- /mnt/user/appdata/postgresql18
|
||||
first_check: "backend_net Konnektivitaet? Disk-Space auf /mnt/user/appdata? pg_isready im Container?"
|
||||
notes: "Dumps per Dienst unter dumps/latest; raw DB nicht primaerer Restore-Weg"
|
||||
notes: "Dumps per Dienst unter dumps/latest; raw DB nicht primaerer Restore-Weg; alter PG17-Pfad bleibt nur Rollback-Altstand"
|
||||
|
||||
komodo-core:
|
||||
description: GitOps UI / API / Stack-Manager
|
||||
@@ -261,9 +261,9 @@ services:
|
||||
url: null
|
||||
dump_file: immich.dump
|
||||
data_paths:
|
||||
- /mnt/user/appdata/immich_postgres
|
||||
- /mnt/user/appdata/immich_postgres_vectorchord
|
||||
first_check: "immich_default Netz? Disk-Space? pg_isready?"
|
||||
notes: "nie ins frontend_net; immich_default Netz isoliert"
|
||||
notes: "PG14 mit VectorChord/pgvector; nie ins frontend_net; immich_default Netz isoliert; alter immich_postgres-Pfad bleibt nur Rollback-Altstand"
|
||||
|
||||
immich_redis:
|
||||
description: Immich Cache
|
||||
@@ -314,7 +314,7 @@ services:
|
||||
url: null
|
||||
dump_file: mealie.dump
|
||||
data_paths:
|
||||
- /mnt/user/appdata/mealie/postgres
|
||||
- /mnt/user/appdata/mealie/postgres18
|
||||
first_check: "mealie_internal Netz? Disk-Space?"
|
||||
notes: "interne DB; mealie_internal Netz"
|
||||
|
||||
@@ -360,7 +360,7 @@ services:
|
||||
url: null
|
||||
dump_file: null
|
||||
data_paths:
|
||||
- /mnt/user/appdata/nextcloud/postgres
|
||||
- /mnt/user/appdata/nextcloud/postgres18
|
||||
first_check: "nextcloud_internal Netz? Disk-Space?"
|
||||
notes: "interne DB"
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ Ziel:
|
||||
- `immich-restore-test.sh`: hosttauglicher Immich-Restore-Job, erster echter Lauf noch offen
|
||||
- `immich-plan.md`: konkreter Immich-Testplan
|
||||
- `immich-runbook.md`: Operator-Runbook fuer den ersten Immich-Lauf
|
||||
- `immich-compose.test.yml`: isolierte Testinstanz fuer Immich inkl. pgvecto-rs Test-Postgres und Test-Redis
|
||||
- `immich-compose.test.yml`: isolierte Testinstanz fuer Immich inkl. VectorChord/pgvector-Test-Postgres und Test-Redis
|
||||
- `check-restore-freshness.ps1`: woechentlicher Frische-Check fuer Dumps und Reports
|
||||
- `run-restore-checks.ps1`: einfacher Dispatcher fuer Restore-Jobs
|
||||
- `check-restore-freshness.sh`: hosttauglicher Frische-Check
|
||||
@@ -81,10 +81,10 @@ Aktuell ist das erste validierte Muster vorhanden.
|
||||
- echter Vaultwarden-Restore am 2026-05-07 erfolgreich verifiziert
|
||||
- echter Gitea-Restore am 2026-05-07 erfolgreich verifiziert
|
||||
- echter Paperless-Restore am 2026-05-07 erfolgreich verifiziert
|
||||
- Immich-Restore-Test am 2026-05-26 vorbereitet; erster echter Lauf mit Report steht noch aus
|
||||
- Immich-Restore-Test am 2026-05-27 erfolgreich verifiziert; Test-Postgres wurde nach der VectorChord-Migration am 2026-05-31 auf das produktive Immich-Postgres-Image umgestellt
|
||||
- Bash-Dispatcher und Bash-Restore-Jobs am 2026-05-07 erfolgreich hostseitig verifiziert
|
||||
- Restore-Lab und Report-Pfade auf dem Host angelegt
|
||||
- V1-Ablauf weiter ohne `ntfy`, mit Bereinigung nach Erfolg
|
||||
- naechster grosser Kandidat ist der erste echte Immich-Lauf mit Zeitmessung; erst danach in die Rotation aufnehmen
|
||||
- naechster grosser Kandidat ist ein erneuter Immich-Lauf nach VectorChord-Migration mit Zeitmessung; danach in die Rotation aufnehmen
|
||||
|
||||
Vor dem ersten echten Testlauf muessen Zielpfade, Quellpfade und Bereinigungsschritte bewusst freigegeben werden.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
services:
|
||||
restoretest-immich-postgres:
|
||||
# gleiches Image wie Produktion, damit pgvecto-rs / pgvector-Extensions
|
||||
# beim Restore aus immich.dump verfuegbar sind
|
||||
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
|
||||
# Gleiches DB-Image wie Produktion, damit VectorChord/pgvector beim
|
||||
# Restore aus immich.dump verfuegbar sind.
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
|
||||
container_name: restoretest-immich-postgres
|
||||
restart: "no"
|
||||
environment:
|
||||
@@ -11,6 +11,7 @@ services:
|
||||
POSTGRES_DB: immich
|
||||
POSTGRES_PASSWORD: restoretest-immich-db
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
shm_size: 128mb
|
||||
volumes:
|
||||
- /mnt/user/backups/restore-lab/immich/postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
@@ -22,7 +23,7 @@ services:
|
||||
- no-new-privileges:true
|
||||
|
||||
restoretest-immich-redis:
|
||||
image: redis:7.4-alpine
|
||||
image: redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1
|
||||
container_name: restoretest-immich-redis
|
||||
restart: "no"
|
||||
command:
|
||||
|
||||
@@ -8,7 +8,7 @@ Bewusst **nicht** Teil dieses Tests:
|
||||
|
||||
- Wiederherstellung produktiver Foto-Dateien aus `/mnt/user/photos/immich` und `/mnt/user/photos/family_archive`. Der Smoke-Test bleibt DB-/UI-zentriert.
|
||||
- Machine-Learning-Container. Spart Image-Pull-Zeit und Resource-Last; ML-Features sind im Smoke-Test nicht erforderlich.
|
||||
- Echte Browser-Login-Sequenz. Smoke-Test prueft nur, dass die Login-Seite ausgeliefert wird und die DB-Tabellen `assets` und `users` lesbar sind.
|
||||
- Echte Browser-Login-Sequenz. Smoke-Test prueft nur, dass die Login-Seite ausgeliefert wird und die DB-Tabellen `asset` und `"user"` lesbar sind.
|
||||
|
||||
## Quelle
|
||||
|
||||
@@ -27,8 +27,8 @@ Bewusst **nicht** Teil dieses Tests:
|
||||
- `/mnt/user/backups/restore-lab/immich/dumps/latest/immich.dump` (extrahierter Dump)
|
||||
- Testcontainer:
|
||||
- `restoretest-immich-server`
|
||||
- `restoretest-immich-postgres` (`tensorchord/pgvecto-rs:pg14-v0.2.0` - identisch zur Produktion, weil der Dump pgvecto-rs Extension referenziert)
|
||||
- `restoretest-immich-redis` (`redis:7.4-alpine`, rebuildbar)
|
||||
- `restoretest-immich-postgres` (`ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0` - identisch zur Produktion, weil VectorChord-Backups ein Image mit VectorChord brauchen)
|
||||
- `restoretest-immich-redis` (`redis:8.8.0-alpine`, rebuildbar)
|
||||
- Testport Web: `127.0.0.1:12283:2283`
|
||||
- Report-Ziel: `/mnt/user/backups/restore-reports/immich-YYYY-MM-DD.md`
|
||||
|
||||
@@ -46,7 +46,7 @@ Bewusst **nicht** Teil dieses Tests:
|
||||
|
||||
1. Restore-Ziel unter `/mnt/user/backups/restore-lab/immich` vorbereiten (postgres, upload, dumps/latest)
|
||||
2. `local/borg-dumps/latest/immich.dump` aus dem aktuellsten Borg-Archiv extrahieren
|
||||
3. Test-Postgres (`pgvecto-rs`) und Test-Redis mit `ops/restore-tests/immich-compose.test.yml` starten
|
||||
3. Test-Postgres (Immich-Postgres mit VectorChord) und Test-Redis mit `ops/restore-tests/immich-compose.test.yml` starten
|
||||
4. `immich.dump` in Test-Postgres importieren (`pg_restore -Fc --clean --if-exists --no-owner --no-privileges`)
|
||||
5. Testinstanz `restoretest-immich-server` starten
|
||||
6. lokalen Smoke-Test gegen `http://127.0.0.1:12283` ausfuehren und Asset/User-Count aus DB lesen
|
||||
@@ -61,12 +61,12 @@ Minimal erfolgreich:
|
||||
- `pg_restore -Fc` laeuft ohne Fehler durch
|
||||
- Immich-Server liefert HTTP `200`, `302` oder `303` auf `/`
|
||||
- Response enthaelt mindestens einen der Marker `Immich`, `Login`, `Signin`
|
||||
- `select count(*) from assets;` und `select count(*) from users;` sind lesbar
|
||||
- `select count(*) from asset;` und `select count(*) from "user";` sind lesbar
|
||||
|
||||
Optional spaeter:
|
||||
|
||||
- Echte Login-Form via API ansprechen
|
||||
- pgvecto-rs Extension explizit per `\dx` pruefen
|
||||
- VectorChord-/pgvector-Extensions explizit per `\dx` pruefen
|
||||
- Test mit gemountetem **read-only** Foto-Sample-Pfad und Thumbnail-Rendering
|
||||
- Test inkl. ML-Container, sobald genug Test-Ressourcen verfuegbar
|
||||
|
||||
@@ -75,8 +75,8 @@ Optional spaeter:
|
||||
| Risiko | Beschreibung | Mitigation |
|
||||
|---|---|---|
|
||||
| Dump-Groesse unbekannt | `pg_dump -Fc` der Immich-DB kann je nach Asset-/Face-Tabellen mehrere GB sein | Erster Lauf bewusst mit `--what-if`, anschliessend Operator-Test mit Zeitmessung |
|
||||
| `pg_restore`-Dauer unbekannt | Index-/Constraint-Aufbau und pgvecto-rs-Index-Build koennen lange dauern | Test-Postgres mit Health-Polling startet; Lauf nicht abbrechen ohne `pg_restore`-Exit |
|
||||
| pgvecto-rs Extension-Mismatch | Wenn das pgvecto-rs-Image im Test nicht exakt dieselbe Version wie Produktion ist, kann `CREATE EXTENSION vectors` im Restore fehlschlagen | Compose pinnt denselben Digest wie `apps/immich/docker-compose.yml` |
|
||||
| `pg_restore`-Dauer unbekannt | Index-/Constraint-Aufbau und VectorChord-Index-Build koennen lange dauern | Test-Postgres mit Health-Polling startet; Lauf nicht abbrechen ohne `pg_restore`-Exit |
|
||||
| VectorChord-/pgvector-Extension-Mismatch | Wenn das Test-Postgres-Image nicht zu Produktion passt, kann der Restore oder Immich-Start fehlschlagen | Compose pinnt denselben Digest wie `apps/immich/docker-compose.yml` |
|
||||
| Immich-Server-Migrations beim Start | Immich fuehrt beim ersten Start DB-Migrations aus; das kann nach Restore noch laufen, bevor Web-UI antwortet | Smoke-Test pollt HTTP bis zu 120 s, bevor er als Fehler markiert |
|
||||
| Asset-Files fehlen | Der Test mountet kein Foto-Volume; Immich zeigt "missing" auf Asset-Detail-Seiten | Smoke-Test prueft nur Login-Page und DB-Counts, nicht Asset-Rendering |
|
||||
| ML-Endpoint unreachable | Immich-Server kann ML-Endpoint nicht erreichen | `IMMICH_MACHINE_LEARNING_URL` zeigt bewusst auf einen nicht erreichbaren Hostnamen; Login bleibt funktional, ML-Features bleiben deaktiviert |
|
||||
|
||||
@@ -19,8 +19,8 @@ Write-Output "Expected Borg source paths inside archive:"
|
||||
Write-Output " - local/borg-dumps/latest/immich.dump"
|
||||
Write-Output ""
|
||||
Write-Output "Planned isolation:"
|
||||
Write-Output " - Test Postgres: tensorchord/pgvecto-rs:pg14-v0.2.0 (same as production)"
|
||||
Write-Output " - Test Redis: redis:7.4-alpine (rebuildable, no restore needed)"
|
||||
Write-Output " - Test Postgres: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 (same as production)"
|
||||
Write-Output " - Test Redis: redis:8.8.0-alpine (rebuildable, no restore needed)"
|
||||
Write-Output " - Test Server: ghcr.io/immich-app/immich-server:release (pinned digest like production)"
|
||||
Write-Output " - ML container: deliberately omitted"
|
||||
Write-Output " - Test endpoint: 127.0.0.1:12283 (no Traefik, no public domain)"
|
||||
@@ -32,7 +32,7 @@ Write-Output "1. Prepare restore-lab target under /mnt/user/backups/restore-lab/
|
||||
Write-Output "2. Extract immich.dump from current Borg archive into test path"
|
||||
Write-Output ' Template: borg extract "$BORG_REPO" "::ARCHIVE_NAME" local/borg-dumps/latest/immich.dump'
|
||||
Write-Output ' Passphrase source: $(cat /mnt/user/appdata/secrets/borg_repo_passphrase.txt)'
|
||||
Write-Output "3. Start isolated test Postgres (pgvecto-rs) and test Redis"
|
||||
Write-Output "3. Start isolated test Postgres (VectorChord/pgvector) and test Redis"
|
||||
Write-Output "4. Import immich.dump into test Postgres with pg_restore -Fc --clean --if-exists --no-owner --no-privileges"
|
||||
Write-Output "5. Start restoretest-immich-server against isolated DB/Redis (ML omitted)"
|
||||
Write-Output "6. Run smoke checks against http://127.0.0.1:12283 and DB asset count"
|
||||
|
||||
@@ -5,8 +5,8 @@ set -euo pipefail
|
||||
#
|
||||
# Nicht-destruktiver Restore-Smoke-Test fuer Immich.
|
||||
# - liest immich.dump aus dem produktiven Borg-Archiv
|
||||
# - importiert in eine isolierte Test-Postgres-Instanz mit gleichem Image
|
||||
# wie Produktion (tensorchord/pgvecto-rs)
|
||||
# - importiert in eine isolierte Test-Postgres-Instanz mit gleichem
|
||||
# VectorChord-Image wie Produktion
|
||||
# - startet einen isolierten Immich-Server-Container ohne Traefik und
|
||||
# ohne ML-Container
|
||||
# - prueft Login-Page und Asset-Anzahl aus DB
|
||||
@@ -43,8 +43,8 @@ ReportRoot: $REPORT_ROOT
|
||||
Expected Borg source paths:
|
||||
- local/borg-dumps/latest/immich.dump
|
||||
Planned isolation:
|
||||
- Test-Postgres: tensorchord/pgvecto-rs:pg14-v0.2.0
|
||||
- Test-Redis: redis:7.4-alpine (rebuildbar, kein Restore)
|
||||
- Test-Postgres: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
|
||||
- Test-Redis: redis:8.8.0-alpine (rebuildbar, kein Restore)
|
||||
- Test-Server: ghcr.io/immich-app/immich-server:release (Image-Pin wie Produktion)
|
||||
- ML-Container bewusst weggelassen
|
||||
- Test-Upload: leer, unter $RESTORE_ROOT/upload
|
||||
@@ -221,7 +221,7 @@ write_report "$REPORT_FILE" <<EOF
|
||||
- Restore root: \`$RESTORE_ROOT\`
|
||||
- Test containers:
|
||||
- \`restoretest-immich-server\`
|
||||
- \`restoretest-immich-postgres\` (tensorchord/pgvecto-rs:pg14-v0.2.0)
|
||||
- \`restoretest-immich-postgres\` (ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0)
|
||||
- \`restoretest-immich-redis\`
|
||||
- Test endpoint: \`http://127.0.0.1:12283\`
|
||||
- ML container: deliberately omitted
|
||||
|
||||
@@ -22,7 +22,7 @@ Vor dem ersten Lauf muss Operator entscheiden:
|
||||
## Bestaetigter Host-Stand (Soll)
|
||||
|
||||
- produktiver Immich-Server: `immich_server` Container mit Image `ghcr.io/immich-app/immich-server:release@sha256:c15bff75068effb03f4355997d03dc7e0fc58720c2b54ad6f7f10d1bc57efaa5`
|
||||
- produktive Postgres: `immich_postgres` mit `tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52`
|
||||
- produktive Postgres: `immich_postgres` mit `ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23`
|
||||
- produktive Foto-Pfade: `/mnt/user/photos/immich`, `/mnt/user/photos/family_archive`
|
||||
- aktueller Dump-Pfad: `/mnt/user/backups/borg/dumps/latest/immich.dump`
|
||||
- Secret: `/mnt/user/appdata/secrets/immich_postgres_password.txt` (wird vom Test **nicht** gebraucht; Test nutzt eigenes Test-Passwort)
|
||||
@@ -71,7 +71,7 @@ Minimal erwartet im Report:
|
||||
- `Asset count in test DB`: Zahl, oder `n/a` bei Schema-Drift
|
||||
- `User count in test DB`: Zahl, oder `n/a` bei Schema-Drift
|
||||
- Pre-Dump-Hook-Kette (`pg_dump -Fc`) und Restore-Kette (`pg_restore -Fc`) sind kompatibel
|
||||
- pgvecto-rs Extension ist im Restore-DB sichtbar
|
||||
- VectorChord-/pgvector-Extensions sind in der Restore-DB sichtbar
|
||||
|
||||
Manuelle Folgepruefung (optional):
|
||||
|
||||
@@ -82,7 +82,7 @@ docker compose -f /mnt/user/services/homelab-infra/ops/restore-tests/immich-comp
|
||||
restoretest-immich-postgres restoretest-immich-redis restoretest-immich-server
|
||||
|
||||
docker exec restoretest-immich-postgres psql -U immich -d immich -c "\dx"
|
||||
docker exec restoretest-immich-postgres psql -U immich -d immich -tAc "select count(*) from assets;"
|
||||
docker exec restoretest-immich-postgres psql -U immich -d immich -tAc "select count(*) from asset;"
|
||||
docker logs --tail 100 restoretest-immich-server
|
||||
|
||||
docker compose -f /mnt/user/services/homelab-infra/ops/restore-tests/immich-compose.test.yml down
|
||||
@@ -102,7 +102,7 @@ Das Skript bereinigt:
|
||||
|
||||
| Symptom | Ursache | Massnahme |
|
||||
|---|---|---|
|
||||
| `pg_restore: error: could not find extension ... vectors` | Test-Postgres-Image nicht pgvecto-rs | Compose-Pin im Test-Compose pruefen |
|
||||
| `pg_restore: error: could not find extension ... vector/vchord` | Test-Postgres-Image passt nicht zur Produktion | Compose-Pin im Test-Compose pruefen |
|
||||
| HTTP-Timeout nach 120 s | Immich-Migrations laufen noch | Wartezeit im Skript erhoehen oder Logs pruefen |
|
||||
| `pg_isready` nie healthy | Test-Postgres bricht beim Start ab (Datadir-Konflikt) | Restore-Lab vor Lauf vollstaendig leer; `docker logs restoretest-immich-postgres` |
|
||||
| Body matcht keine Marker | Immich UI hat sich versioniert; Marker-Liste anpassen | Marker im Skript erweitern (`grep -qiE`) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
restoretest-paperless-postgres:
|
||||
image: postgres:17.9@sha256:5b96f1a16bd9768b060dd2ffe55cb6225c4d9ef4d214a8b21eb08134869a97e4
|
||||
image: postgres:18.4@sha256:8ff36f3c66371cba71d20ceedccfc3de9669a68737607888c4ef0af93abe8e39
|
||||
container_name: restoretest-paperless-postgres
|
||||
restart: "no"
|
||||
environment:
|
||||
@@ -8,9 +8,9 @@ services:
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_PASSWORD: restoretest-paperless-db
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
PGDATA: /var/lib/postgresql/18/docker
|
||||
volumes:
|
||||
- /mnt/user/backups/restore-lab/paperless/postgres:/var/lib/postgresql/data
|
||||
- /mnt/user/backups/restore-lab/paperless/postgres:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U paperless -d paperless"]
|
||||
interval: 10s
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
- no-new-privileges:true
|
||||
|
||||
restoretest-paperless-redis:
|
||||
image: redis:7-alpine
|
||||
image: redis:8.8.0-alpine@sha256:09160599abd229764c0fb44cb6be640294e1d360a54b19985ab4843dcf2d90f1
|
||||
container_name: restoretest-paperless-redis
|
||||
restart: "no"
|
||||
command:
|
||||
|
||||
+30
-1
@@ -44,7 +44,7 @@
|
||||
"postgres",
|
||||
"mongo",
|
||||
"redis",
|
||||
"tensorchord/pgvecto-rs"
|
||||
"ghcr.io/immich-app/postgres"
|
||||
],
|
||||
"groupName": null,
|
||||
"automerge": false,
|
||||
@@ -57,6 +57,35 @@
|
||||
"matchPackageNames": ["mongo"],
|
||||
"allowedVersions": "/^8\\.0\\.\\d+$/"
|
||||
},
|
||||
{
|
||||
"description": "Produktive PostgreSQL-Cluster bleiben nach Major-Upgrade auf der 18.x-Schiene",
|
||||
"matchManagers": ["docker-compose"],
|
||||
"matchFileNames": [
|
||||
"infra/postgresql17/docker-compose.yml",
|
||||
"apps/mealie/docker-compose.yml",
|
||||
"apps/nextcloud/docker-compose.yml"
|
||||
],
|
||||
"matchPackageNames": ["postgres"],
|
||||
"allowedVersions": "/^18\\.\\d+(?:-.+)?$/"
|
||||
},
|
||||
{
|
||||
"description": "Immich-Postgres bleibt auf PG14 mit VectorChord/pgvector; kein generisches Postgres und kein PG-Major-Sprung",
|
||||
"matchManagers": ["docker-compose"],
|
||||
"matchFileNames": ["apps/immich/docker-compose.yml"],
|
||||
"matchPackageNames": ["ghcr.io/immich-app/postgres"],
|
||||
"allowedVersions": "/^14-vectorchord\\d+\\.\\d+\\.\\d+(?:-pgvectors\\d+\\.\\d+\\.\\d+)?$/"
|
||||
},
|
||||
{
|
||||
"description": "Produktive Redis-Instanzen bleiben nach Major-Upgrade auf der 8.x-Schiene",
|
||||
"matchManagers": ["docker-compose"],
|
||||
"matchFileNames": [
|
||||
"infra/redis/docker-compose.yml",
|
||||
"apps/nextcloud/docker-compose.yml",
|
||||
"apps/immich/docker-compose.yml"
|
||||
],
|
||||
"matchPackageNames": ["redis"],
|
||||
"allowedVersions": "/^8\\.\\d+\\.\\d+-alpine(?:\\d+\\.\\d+)?$/"
|
||||
},
|
||||
{
|
||||
"description": "Komodo Major-Tag (release :2 mit Digest-Pin) wird nicht von Renovate auf :3 hochgesetzt",
|
||||
"matchPackageNames": [
|
||||
|
||||
Reference in New Issue
Block a user