5bc30c950c
Move Supabase + LiveKit from the netralax.cloud VPS to a new netralax.de server. Adds the migration runbook (docs/), one-time move scripts (scripts/migrate/), and prod Caddy/LiveKit config templates (infra/). Repoints the desktop publish/changelog URLs and prod ops config to .de. JWT_SECRET + VAPID copied identically so already-installed clients keep working; the new server also serves the legacy .cloud hostnames. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
133 lines
7.0 KiB
Markdown
133 lines
7.0 KiB
Markdown
# Server-Umzug: netralax.cloud -> netralax.de
|
||
|
||
Einmalige Migration des selbst gehosteten Chat-Backends vom **alten VPS**
|
||
(`46.225.156.249`, `*.netralax.cloud`) auf einen **neuen, leeren VPS**
|
||
(`*.netralax.de`). Der neue Server bedient anschliessend **beide** Domains,
|
||
damit bereits installierte Desktop-/Mobile-Clients (die alte Hostnamen und den
|
||
alten anon-JWT fest eingebaut haben) weiterlaufen, bis sie sich selbst
|
||
aktualisieren.
|
||
|
||
> Diese Skripte sind bewusst getrennt von `scripts/prod/`. `scripts/prod/config.sh`
|
||
> kennt nur den jeweils **aktiven** Server; der Umzug braucht **beide** Hosts und
|
||
> hat deshalb seine eigene `scripts/migrate/config.sh`.
|
||
|
||
## Dateien
|
||
|
||
| Datei | Wo ausführen | Zweck |
|
||
|-------|--------------|-------|
|
||
| `config.sh` | – | Gemeinsame Konfiguration (alter + neuer Host, SSH-Helfer). Wird von den anderen Skripten eingebunden. |
|
||
| `01-bootstrap-new-server.sh` | **auf dem neuen VPS** (als root / sudo) | Richtet den leeren Server ein: Docker, ufw, Supabase-Clone, LiveKit-Verzeichnis, Caddy, Update-Host, Deploy-User. |
|
||
| `02-migrate-data.sh` | **auf dem Entwickler-Laptop** | Überträgt Postgres-Daten (pg_dumpall) und die Storage-Objekte (rsync) von alt nach neu. |
|
||
|
||
## Voraussetzungen / Einrichtung (einmalig)
|
||
|
||
1. **Neue Server-IP — bereits eingetragen.** `scripts/migrate/config.sh` hat
|
||
`NEW_HOST="141.95.34.204"` und `NEW_USER="debian"`. (Der `require_new_host`-
|
||
Guard greift nur, falls der Platzhalter wieder drinsteht.)
|
||
|
||
2. **SSH-Zugriff.** Vom Laptop muss `ssh prox@46.225.156.249` (alt) **und**
|
||
`ssh debian@141.95.34.204` (neu) ohne Passwort funktionieren:
|
||
```
|
||
ssh-copy-id prox@46.225.156.249
|
||
ssh-copy-id debian@141.95.34.204
|
||
```
|
||
Für den direkten Storage-Transfer (Server-zu-Server) muss zusätzlich der
|
||
**alte** Server per SSH auf den **neuen** zugreifen können. Klappt das nicht,
|
||
fällt `02-migrate-data.sh` automatisch auf den Umweg über den Laptop zurück.
|
||
|
||
3. **Skripte ausführbar machen:**
|
||
```
|
||
chmod +x scripts/migrate/*.sh
|
||
```
|
||
|
||
## Ablauf (Reihenfolge unbedingt einhalten)
|
||
|
||
1. **Bootstrap auf dem neuen Server.** Skript hochladen und als root ausführen:
|
||
```
|
||
scp scripts/migrate/01-bootstrap-new-server.sh debian@141.95.34.204:/tmp/
|
||
ssh debian@141.95.34.204 'sudo bash /tmp/01-bootstrap-new-server.sh'
|
||
```
|
||
Das Skript ist idempotent (mehrfaches Ausführen schadet nicht) und gibt am
|
||
Ende einen **NEXT STEPS**-Block aus.
|
||
|
||
2. **Secrets eintragen.** `/opt/supabase/.env` auf dem neuen Server befüllen.
|
||
Diese Werte **1:1 vom alten Server kopieren** (sonst brechen eingebaute
|
||
Tokens, Sessions und Web-Push):
|
||
`POSTGRES_PASSWORD`, `JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`,
|
||
`SECRET_KEY_BASE`, `VAULT_ENC_KEY`, `PG_META_CRYPTO_KEY`, alle `SMTP_*`,
|
||
`VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT`,
|
||
`PUSH_FANOUT_SHARED_SECRET`, `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET`.
|
||
Auf die **neue** Domain zeigen:
|
||
`SITE_URL`, `API_EXTERNAL_URL`, `SUPABASE_PUBLIC_URL`, `SUPABASE_URL`
|
||
= `https://supabase.netralax.de`, `LIVEKIT_URL` = `wss://livekit.netralax.de`.
|
||
`ADDITIONAL_REDIRECT_URLS` (komma-getrennt, **ohne Leerzeichen**) muss
|
||
enthalten: `chatapp://auth/callback`, `netralax://auth/callback` sowie
|
||
`https://supabase.netralax.de` und `https://supabase.netralax.cloud`.
|
||
|
||
3. **Server-Konfig platzieren.**
|
||
- `infra/livekit/docker-compose.prod.yml.example` -> `/opt/livekit/docker-compose.yml`
|
||
(Prod-Compose: host-networking, mountet `livekit.yaml` + `coturn.conf` +
|
||
`/etc/letsencrypt`; das Dev-Compose taugt **nicht** für Prod).
|
||
- `infra/livekit/livekit.prod.yaml.example` -> `/opt/livekit/livekit.yaml`
|
||
(`rtc.use_external_ip: true`, **kein** `node_ip: 127.0.0.1`, `keys:`-Block
|
||
identisch zu `LIVEKIT_API_KEY/SECRET` aus der `.env`).
|
||
- `infra/livekit/coturn.prod.conf.example` -> `/opt/livekit/coturn.conf`
|
||
(`external-ip` = öffentliche IP des neuen VPS, TLS-Cert für
|
||
`turn.netralax.de`).
|
||
- `infra/caddy/Caddyfile` -> `/etc/caddy/Caddyfile`, danach
|
||
`systemctl reload caddy`. Caddy bedient **beide** Domains (.de und .cloud).
|
||
|
||
4. **Stacks starten – DB zuerst einmal hochfahren**, damit die Supabase-Init-
|
||
Skripte die Rollen anlegen (vor dem Restore):
|
||
```
|
||
ssh debian@141.95.34.204 'cd /opt/supabase && docker compose up -d db && sleep 20'
|
||
```
|
||
|
||
5. **Schreibzugriffe auf dem ALTEN System einfrieren** (Wartungsmodus). Sonst
|
||
landen während des Umzugs neue Uploads/Zeilen nur auf einer Seite und
|
||
DB + Storage werden inkonsistent.
|
||
|
||
6. **Daten migrieren** (vom Laptop). Erst der Trockenlauf, dann die Migration:
|
||
```
|
||
./scripts/migrate/02-migrate-data.sh --check # nur Pre-Flight, keine Änderung
|
||
./scripts/migrate/02-migrate-data.sh # fragt nach Bestätigung
|
||
```
|
||
Das Skript dumpt den **gesamten** Cluster per `pg_dumpall` und spielt ihn auf
|
||
dem neuen Server ein, danach rsync der Storage-Objekte. `push-migrations.sh`
|
||
**nicht** erneut ausführen – die Migrationen sind bereits im Dump enthalten.
|
||
|
||
7. **DNS umstellen.** A-Records für **beide** Domains auf die neue IP zeigen
|
||
lassen: `supabase.netralax.de` / `.cloud`, `livekit.netralax.de` / `.cloud`,
|
||
`turn.netralax.de`, `update.netralax.de` / `.cloud`.
|
||
|
||
8. **Update-Artefakte spiegeln.** electron-updater-Dateien (`latest.yml`,
|
||
`*.exe`, `changelog.json`) unter `/var/www/updates/windows` ablegen, sodass
|
||
**sowohl** `update.netralax.de` **als auch** `update.netralax.cloud` sie
|
||
ausliefern. Nur so können alte (.cloud-)Clients die Umstiegs-Version ziehen.
|
||
|
||
## Sicherheitshinweise
|
||
|
||
- **`JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`** müssen byteweise identisch
|
||
vom alten Server stammen, **bevor** der erste Client den neuen Server trifft –
|
||
sonst werden alle eingebauten Tokens abgelehnt und alle Sessions fliegen raus.
|
||
- **`POSTGRES_PASSWORD`** muss vor dem Restore identisch gesetzt sein, weil der
|
||
Dump die Rollen-Passwort-Hashes mitbringt. Sonst können sich die internen
|
||
Dienste (auth/rest/storage) nach dem Restore nicht mehr an Postgres anmelden.
|
||
- **VAPID-Schlüsselpaar** identisch übernehmen, sonst sind alle bestehenden
|
||
Web-Push-Abos ungültig.
|
||
- **Medien-/TURN-Ports** müssen in ufw offen sein (7880/7881 tcp, 50000-50100
|
||
udp, coturn 3478 tcp+udp, 5349 tcp, 50200-50300 udp) – sonst haben Anrufe kein
|
||
Audio/Video. Diese Ports laufen **nicht** über Caddy.
|
||
- **TURNS auf 5349** braucht ein eigenes TLS-Zertifikat für `turn.netralax.de`
|
||
auf der Platte (Pfade in `coturn.conf`) – ein reines Caddy-Zertifikat reicht
|
||
nicht.
|
||
- **Alten VPS nicht abschalten**, bevor die `.cloud`-DNS-Einträge auf den neuen
|
||
Server zeigen und alte Clients Zeit zum Auto-Update hatten.
|
||
- Beim Restore werden harmlose `already exists`-Fehler für vorhandene Rollen
|
||
(`supabase_admin`, `postgres` …) ausgegeben – das ist gewollt
|
||
(`ON_ERROR_STOP=0`). `02-migrate-data.sh` scannt die Restore-Ausgabe
|
||
**automatisch** auf echte `ERROR/FATAL/PANIC` und **bricht vor dem Storage-
|
||
rsync ab**, wenn welche übrig bleiben (Override: `FORCE_RESTORE_OK=1`).
|
||
Danach macht es eine Zeilen-Paritätsprüfung (alt vs. neu) über die tragenden
|
||
Tabellen.
|