Skip to content

WebSocket Realtime & Caddy Proxy

Hausmeter nutzt Supabase Realtime für Live-Updates im Frontend. Realtime basiert auf PostgreSQL Logical Replication und der Publication supabase_realtime.

Clients subscriben via Supabase JS SDK:

const channel = supabase
.channel('maintenance')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'maintenance_requests',
}, (payload) => {
console.log('Change received:', payload)
})
.subscribe()

| Tabelle | Seit Migration | Zweck | |---------|---------------|-------| | billing_deadline_alerts | 255 | Fälligkeits-Warnungen | | billing_line_items | 253 | Abrechnungspositionen | | billing_runs | — | Abrechnungsläufe | | charging_sessions | — | Ladesitzungen | | charging_stations | — | Ladestationen-Status | | chat_messages | — | Chat-Nachrichten | | maintenance_analyses | — | Wartungsanalysen | | maintenance_requests | 256 | Wartungsanfragen | | meters | — | Zähler-Status | | notifications | — | Benachrichtigungen | | rfid_cards | — | RFID-Karten | | rfid_learn_queue | — | RFID-Lernmodus |

Browser ──WebSocket──▸ supabase-realtime ──▸ PostgreSQL Logical Replication
(Port 4000) (Publication: supabase_realtime)
  • supabase-realtime Container lauscht auf Änderungen via WAL
  • RLS-Policies gelten auch für Realtime (Row Level Security)
  • Clients erhalten nur Zeilen, die ihre RLS-Policy erlaubt

Caddy leitet WebSocket-Verbindungen an den Supabase Realtime Container weiter. Die Konfiguration in ~/services/caddy/Caddyfile:

realtime.hausmeter.com {
reverse_proxy supabase-realtime:4000
}

WebSocket-Upgrades werden von Caddy automatisch unterstützt — keine zusätzliche Konfiguration nötig.

Die Realtime-Konfiguration liegt in der Supabase Docker Compose: ~/services/supabase/supabase/docker/docker-compose.yml

Relevante Env-Vars im realtime Service:

  • DB_HOST, DB_PORT, DB_USER, DB_PASSWORD
  • SLOT_NAME (Replication Slot)

  • Die Tabelle muss bereits existieren (\d tabellenname in psql)
  • Primary Key muss vorhanden sein (UUID empfohlen)
  • RLS-Policies sollten bereits konfiguriert sein

Erstelle eine neue SQL-Migrationsdatei in ~/hausmeter/migrations/:

-- migrations/NNN_tabellenname_realtime.sql
-- Enable Supabase Realtime for tabellenname
ALTER PUBLICATION supabase_realtime ADD TABLE public.tabellenname;

Namenskonvention: NNN_tabellenname_realtime.sql (NNN = nächste freie Nummer)

Terminal window
docker exec supabase-db psql -U postgres -d postgres \
-c "ALTER PUBLICATION supabase_realtime ADD TABLE public.tabellenname;"
Terminal window
docker exec supabase-db psql -U postgres -d postgres -c "\dRp+ supabase_realtime"

Die Tabelle muss in der Liste unter Tables: erscheinen.

Terminal window
docker exec supabase-db psql -U postgres -d postgres \
-c "SELECT relreplident FROM pg_class WHERE relname = 'tabellenname';"
  • d = default (PK) — reicht für die meisten Fälle
  • f = full — nötig wenn UPDATE-Payloads die alten Werte enthalten sollen

Falls full benötigt:

ALTER TABLE public.tabellenname REPLICA IDENTITY FULL;
import { supabase } from '@/lib/supabase'
const channel = supabase
.channel('mein-channel-name')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'tabellenname',
filter: 'tenant_id=eq.xxx',
}, (payload) => {
// payload.new = neue Daten
// payload.old = alte Daten (nur bei REPLICA IDENTITY FULL)
// payload.eventType = 'INSERT' | 'UPDATE' | 'DELETE'
})
.subscribe()
// Cleanup beim Unmount:
// supabase.removeChannel(channel)
Terminal window
cd ~/hausmeter
git add migrations/NNN_tabellenname_realtime.sql
git commit -m "Enable Supabase Realtime for tabellenname"
  • Migration erstellt und ausgeführt
  • \dRp+ zeigt Tabelle in Publication
  • Replica Identity geprüft (default reicht meistens)
  • RLS-Policies vorhanden (Realtime respektiert RLS)
  • Frontend-Subscription implementiert
  • Git Commit