Datenbank von SQLite auf Postgres umgestellt
Verbindung über KVER_DSN; Tabelle user heißt jetzt account (reserviertes Wort in Postgres). kver import-sqlite übernimmt die alte Datei einmalig in einer Transaktion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c6ab082f8c
commit
2714fdb1a5
+41
-12
@@ -27,8 +27,8 @@ Beim ersten Deployment: DB und Medien einmalig in die Volumes kopieren
|
||||
podman build -t kver .
|
||||
```
|
||||
|
||||
Multi-Stage-Build (`Containerfile`): statisches Go-Binary (CGO aus, modernc-
|
||||
SQLite ist pures Go), Laufzeit-Image ist Alpine mit unprivilegiertem Nutzer.
|
||||
Multi-Stage-Build (`Containerfile`): statisches Go-Binary (CGO aus), Laufzeit-
|
||||
Image ist Alpine mit unprivilegiertem Nutzer.
|
||||
|
||||
Die Warnung `HEALTHCHECK is not supported for OCI image format` ist erwartbar:
|
||||
Podman baut OCI-Images, dort gibt es kein eingebettetes HEALTHCHECK. Der
|
||||
@@ -46,8 +46,9 @@ podman run -d --name kver \
|
||||
kver
|
||||
```
|
||||
|
||||
- `kver-data` hält die SQLite-DB (`/app/data/kver.db`), `kver-media` die
|
||||
hochgeladenen Bilder. Beides Named Volumes → überleben Image-Updates.
|
||||
- Die Daten liegen in Postgres (`KVER_DSN`). `kver-data` hält nur noch die
|
||||
GeoLite2-ASN-DB (und die alte SQLite-Datei), `kver-media` die hochgeladenen
|
||||
Bilder. Beides Named Volumes → überleben Image-Updates.
|
||||
- Port nur an localhost binden; nach außen geht es über den Reverse-Proxy.
|
||||
- Der Container lauscht intern immer auf `:8080`; der externe Port (hier 7777)
|
||||
ist nur das Host-seitige Mapping.
|
||||
@@ -57,7 +58,7 @@ Konfiguration über Umgebungsvariablen:
|
||||
| Variable | Default | Bedeutung |
|
||||
|-------------|---------------------|----------------------|
|
||||
| `KVER_ADDR` | `:8080` | Listen-Adresse im Container |
|
||||
| `KVER_DB` | `/app/data/kver.db` | Pfad zur SQLite-Datei |
|
||||
| `KVER_DSN` | _(Pflicht)_ | Postgres-Verbindung, z. B. `postgres://kver:pw@host:5432/kontrollverlust?sslmode=disable` |
|
||||
| `KVER_GEOIP_ASN` | _(leer)_ | Pfad zur GeoLite2-ASN-`.mmdb`; leer = ASN-Auflösung aus |
|
||||
|
||||
## GeoLite2-ASN-Datenbank (optional)
|
||||
@@ -77,9 +78,40 @@ Dann `KVER_GEOIP_ASN=/app/data/GeoLite2-ASN.mmdb` setzen. Die Datei wird beim St
|
||||
einmalig gemappt; für aktualisierte Daten die Datei ersetzen und den Dienst neu
|
||||
starten.
|
||||
|
||||
## Bestehende Daten übernehmen
|
||||
## Postgres
|
||||
|
||||
DB und Medien einmalig in die Volumes kopieren (Volumes müssen existieren;
|
||||
Die App erwartet eine Datenbank, die ihrem Login-User gehört. Einmalig als
|
||||
Admin:
|
||||
|
||||
```sql
|
||||
CREATE ROLE kver LOGIN PASSWORD '...';
|
||||
CREATE DATABASE kontrollverlust OWNER kver;
|
||||
REVOKE CONNECT, TEMPORARY ON DATABASE kontrollverlust FROM PUBLIC;
|
||||
```
|
||||
|
||||
Tabellen und Indizes legt die App beim Start selbst an (`CREATE ... IF NOT
|
||||
EXISTS`, als `kver` → gehören `kver`). Nicht als Admin anlegen.
|
||||
|
||||
## Umzug SQLite → Postgres (einmalig)
|
||||
|
||||
Dienst stoppen, dann mit dem neuen Image die alte Datei aus dem Volume
|
||||
importieren. Der Import läuft in einer Transaktion, prüft die Zeilenzahlen und
|
||||
bricht ab, wenn in Postgres schon Daten liegen:
|
||||
|
||||
```sh
|
||||
systemctl --user stop kver
|
||||
podman run --rm --env-file /etc/kver/kver.env \
|
||||
-v kver-data:/app/data:ro \
|
||||
kver import-sqlite /app/data/kver.db
|
||||
systemctl --user start kver
|
||||
```
|
||||
|
||||
Der Container braucht dabei (und im Betrieb) dieselbe Netzwerkanbindung an
|
||||
Postgres wie der Dienst selbst.
|
||||
|
||||
## Bestehende Medien übernehmen
|
||||
|
||||
Medien einmalig ins Volume kopieren (Volumes müssen existieren;
|
||||
Container kann laufen oder gestoppt sein):
|
||||
|
||||
```sh
|
||||
@@ -88,14 +120,11 @@ podman volume create kver-media
|
||||
|
||||
# Rootless: podman unshare sorgt dafür, dass die UID ins User-Namespace-
|
||||
# Mapping passt — ohne das bekommt der Container die Dateien nicht zu lesen.
|
||||
podman unshare cp kver.db \
|
||||
"$(podman volume inspect kver-data --format '{{.Mountpoint}}')/"
|
||||
podman unshare cp -r static/media/. \
|
||||
"$(podman volume inspect kver-media --format '{{.Mountpoint}}')/"
|
||||
```
|
||||
|
||||
Danach Container (neu) starten. Die App legt beim ersten Start alle fehlenden
|
||||
Tabellen und Indizes automatisch per `CREATE ... IF NOT EXISTS` an.
|
||||
Danach Container (neu) starten.
|
||||
|
||||
## Reverse-Proxy (TLS) — Caddy
|
||||
|
||||
@@ -201,4 +230,4 @@ systemctl --user restart kver
|
||||
```
|
||||
|
||||
Die App fährt bei SIGTERM sauber herunter (laufende Requests werden zu Ende
|
||||
bedient, WAL-Checkpoint beim DB-Close).
|
||||
bedient, dann wird die DB-Verbindung geschlossen).
|
||||
|
||||
Reference in New Issue
Block a user