fix(compose): user-files dauerhaft speichern und Betriebshandbuch nachziehen

- docker-compose.yml und docker-compose.prod.yml mounten /app/user-files
  im Dienst api auf ein neues benanntes Volume user-files (Eigentuemerschaft
  uid 1001 folgt aus dem Image, kein Bind-Mount)
- docker-compose.dev.yml bleibt unveraendert (Compose fuehrt Mount-Listen
  ueber das Ziel zusammen)
- Betriebshandbuch Kapitel 6: Speicher als dauerhaft beschrieben, Mount-Zeile
  woertlich zum Kopieren, Hinweis dass /opt/tessera/docker-compose.yml auf
  dem Server separat gepflegt werden muss (Deploy erreicht sie nicht)
- Betriebshandbuch Kapitel 7: Fehlerzeile zu verschwundenen Avataren/Exporten
  an den reparierten Repository-Stand angepasst

WINDOWS #17 bleibt offen, bis die Serverdatei manuell ergaenzt ist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYZcd3SSmo14QTqWx2KKzU
This commit is contained in:
2026-09-09 09:34:15 +02:00
parent 7b49747c72
commit dab72eb1f9
3 changed files with 36 additions and 14 deletions
+30 -14
View File
@@ -270,24 +270,40 @@ Restores stattfinden.
- **PostgreSQL-Daten**: liegen im benannten Docker-Volume `pgdata`
(`docker-compose.prod.yml`, Mount `pgdata:/var/lib/postgresql/data` im
`db`-Container). Dieses Volume ist der einzige daürhafte Datenspeicher, der über
ein `docker volume`-Backup zusätzlich gesichert werden könnte.
`db`-Container). `pgdata` ist eines von zwei dauerhaften Docker-Volumes (siehe
nächster Punkt) und kann zusätzlich über ein `docker volume`-Backup gesichert
werden.
- **Verschlüsselungsschlüssel** `TESSERA_ENCRYPTION_KEY`: liegt nur in `.env` auf
dem Host, **nicht** im Datenbank-Dump. Getrennt sichern (siehe Kapitel 2/3) – ohne
ihn sind alle per `pg_dump` gesicherten verschlüsselten Zugangsdaten wertlos.
- **Hochgeladene Dateien** (Avatare unter `user-files/avatars/`, generierte
DKV-Exporte unter `user-files/`, siehe `apps/api/src/user/user.controller.ts` und
`apps/api/src/dkv/dkv-export.service.ts`): Diese Dateien landen im Verzeichnis
`user-files/` **innerhalb** des `api`-Containers. Weder `docker-compose.yml` noch
`docker-compose.prod.yml` mounten dafür ein Docker-Volume oder ein Host-Verzeichnis
– der Ordner existiert ausschließlich in der beschreibbaren Container-Schicht.
**Das bedeutet: Bei jedem `--force-recreate` von `api` gehen Avatare und DKV-Exporte
verloren**, sofern auf dem Server nicht zusätzlich (außerhalb des Repo-Standes)
ein Bind-Mount ergänzt wurde. Vor einem Redeploy prüfen, ob auf dem Server ein
solcher Mount existiert (`docker inspect tessera-api-1` → `Mounts`); falls
nicht, gelten Avatare/Exporte als nicht persistent und sollten bei Bedarf vorher
manuell aus dem Container kopiert werden (`docker compose cp api:/app/user-files
./user-files-backup`).
`apps/api/src/dkv/dkv-export.service.ts`): Diese Dateien liegen im benannten
Docker-Volume `user-files`, gemountet auf `/app/user-files` im Dienst `api`. Der
Mount ist in `docker-compose.yml` und `docker-compose.prod.yml` eingetragen:
```yaml
# beim Dienst api:
- user-files:/app/user-files
# im Top-Level-Block volumes:
user-files:
```
Damit überstehen Avatare und DKV-Exporte ein `--force-recreate` von `api`. Wie bei
`pgdata` zeigt `docker volume ls` das Volume mit vorangestelltem Projektnamen an
(`<projekt>_user-files`). Gesichert werden die Dateien weiterhin mit
`docker compose cp api:/app/user-files ./user-files-backup`, alternativ über eine
Sicherung des Docker-Volumes selbst (wie bei `pgdata`).
**Wichtig für den Betrieb auf einem bestehenden Server:** `/opt/tessera/docker-compose.yml`
ist keine Arbeitskopie dieses Repositorys – die Datei wurde dort von Hand
bearbeitet und weicht ab. Ein Deploy holt ausschließlich Images und fasst diese
Datei nicht an. Diese Compose-Änderung erreicht eine bereits laufende Installation
deshalb **nicht von selbst**. Wer die Reparatur dort haben will, trägt dieselben
zwei Zeilen selbst in `/opt/tessera/docker-compose.yml` ein (vorher sichern) und
erstellt die Container einmal neu. Bis dahin gilt für die laufende Installation
weiterhin der alte, verlustbehaftete Zustand – prüfbar mit `docker inspect
tessera-api-1` und einem Blick auf `Mounts`.
## 7. Protokolle und Fehlersuche
@@ -313,7 +329,7 @@ protokolliert die durchgelaufenen Prisma-Migrationen sowie zuletzt
| Neue Version scheint nicht anzukommen, obwohl `pull` gelaufen ist | Klassische `up -d`-Falle ohne `--force-recreate` (siehe Kapitel 4) | `StartedAt` des Containers gegen `Created` des Images vergleichen, ggf. `--force-recreate` nachholen. |
| Initialer Admin-Login funktioniert nicht nach Änderung von `TESSERA_ADMIN_PASSWORD` | Seed läuft nur, wenn der Benutzername noch **nicht** existiert; bestehende Accounts werden nicht überschrieben | Passwort über die Anwendung selbst (bzw. direkt in der Datenbank) ändern, nicht über die `.env`-Variable. |
| Mails werden nicht versendet | `TESSERA_SMTP_HOST` leer (Prod-Default) | SMTP-Variablen vollständig setzen und Container neu erstellen. |
| Avatare/DKV-Exporte nach einem Deploy verschwunden | `user-files/` ist nicht als Volume gemountet, siehe Kapitel 6 | Vor `--force-recreate` sichern, langfristig einen Bind-Mount für `user-files/` ergänzen. |
| Avatare/DKV-Exporte nach einem Deploy verschwunden | Die verwendete Compose-Datei mountet `user-files/` nicht als Volume – im Repository-Stand seit dieser Version behoben, betrifft nur eine Installation mit abweichender Compose-Datei | Die zwei Zeilen aus Kapitel 6 in die verwendete Compose-Datei eintragen (auf dem Server: `/opt/tessera/docker-compose.yml`, vorher sichern) und `api` neu erstellen. |
## 8. Abgrenzung zur CI/CD-Pipeline