Zum Inhalt springen

Datenbank und Schlüssel

AblageKonfigurationGeeignet für
SQLiteDNSE_DB=./dnseditor.db (Vorgabe)Einzelinstanz, Desktop, Test
PostgreSQLDNSE_DB_DSN=postgres://…Produktivbetrieb, Backups per pg_dump
YugabyteDBDNSE_DB_DSN=… und DNSE_DB_YB=onMehrere Knoten, verteilter Betrieb

YugabyteDB spricht das PostgreSQL-Protokoll, braucht aber einen eigenen Treiber. Deshalb genügt der DSN allein nicht — ohne DNSE_DB_YB=on wird die Verbindung als gewöhnliches PostgreSQL behandelt.

Das Schema wird beim Start automatisch migriert. Laufen mehrere Knoten, führt der zuerst gestartete die Migration aus; die übrigen warten, bis das Schema passt.

DNSE_ENCRYPTION_KEY schützt alles, was nicht im Klartext liegen darf: Provider-Zugangsdaten, private Zertifikatsschlüssel, SMTP-Zugangsdaten (Benutzername und Passwort), 2FA-Geheimnisse, die Passwort-Hashes der Benutzerkonten — und die personenbezogenen Daten der Konten selbst: Benutzername, E-Mail-Adresse, Anzeigename sowie die ACME-Konto-Adressen. Die Datenbank enthält davon nur verschlüsselte Formen; API-, Agent- und DynDNS-Tokens liegen zusätzlich grundsätzlich nur als SHA-256-Hashes vor, nie im Klartext.

Damit der Login trotz Verschlüsselung funktioniert, führt der DNS-Editor zu Benutzername und E-Mail einen Blind-Index: einen deterministischen HMAC über den normalisierten Wert (Kleinschreibung, ohne Randleerraum), dessen Schlüssel aus DNSE_ENCRYPTION_KEY abgeleitet ist. Die Datenbank sieht damit weder Namen noch Adressen — Gleichheitssuchen und die Eindeutigkeit der Konten funktionieren aber unverändert, und Logins sind wie bisher unabhängig von Groß-/Kleinschreibung.

Daraus folgen drei Regeln:

  1. Der Schlüssel gehört nicht in dieselbe Sicherung wie die Datenbank. Wer beides zusammen erbeutet, hat alles.
  2. Ein Backup ohne Schlüssel ist wertlos. Vor dem ersten produktiven Start sichern und den Ablageort dokumentieren.
  3. Alle Knoten brauchen denselben Schlüssel. Sonst kann Knoten 2 nicht entschlüsseln, was Knoten 1 geschrieben hat.

Bei PostgreSQL genügt der übliche Weg:

Terminal-Fenster
pg_dump -Fc dnseditor > dnseditor-$(date +%F).dump

Bei SQLite die Datei sichern, während der Dienst steht oder über sqlite3 dnseditor.db ".backup dnseditor-backup.db".

Für Wiederherstellungsproben gilt dasselbe wie überall: Eine Sicherung, die nie zurückgespielt wurde, ist keine.

Mit gesetztem DNSE_BACKUP_DIR schreibt der Dienst zusätzlich einen nächtlichen logischen Export der Organisation (Administration → Sicherung). Dieser Export entschlüsselt die Felder der Datenbank, damit er wiederherstellbar ist — und wird deshalb beim Schreiben wieder versiegelt: AES-256-GCM mit demselben DNSE_ENCRYPTION_KEY. Neue Punkte heißen …jsonl.enc, ältere …jsonl; beide bleiben wiederherstellbar, ein Download liefert Klartext.

Damit gilt für diese Dateien dasselbe wie für die Datenbank: ohne den Schlüssel sind sie nicht wiederherstellbar. Den Schlüssel also getrennt sichern, und wirklich sichern.

Ältere Sicherungen, die noch im Klartext liegen, versiegelt ein einmaliger Lauf nach — ohne Datenbank, ohne laufenden Dienst, wiederholbar:

Terminal-Fenster
DNSE_BACKUP_DIR=… DNSE_ENCRYPTION_KEY=… dnseditor backup-seal

Ob die Sicherungen wirklich lesbar sind, sagt:

Terminal-Fenster
DNSE_BACKUP_DIR=… DNSE_ENCRYPTION_KEY=… dnseditor backup-verify

Der Lauf öffnet jeden Punkt und liest ihn vollständig — ein beschädigter Rahmen oder eine abgeschnittene Datei fällt dabei auf und nicht erst beim Wiederherstellen.