RootGuard Docs
Installation, Betrieb
und Kontrolle.
Von Docker Compose bis zum sicheren Update: Diese Dokumentation beschreibt den aktuellen Release-Candidate-Stand von RootGuard und wird zusammen mit dem Projekt weiterentwickelt.
01 · Überblick
Was RootGuard bereitstellt
RootGuard kombiniert AdGuard Home als Netzwerkfilter mit Unbound als eigenem rekursiven und DNSSEC-validierenden Resolver. WebApp und Core verwalten den Stack; ein separater Updater tauscht Core und WebApp sicher als Paar aus.
Sechs Komponenten, klare Verantwortung
02 · Voraussetzungen
Bevor du beginnst
- Docker Engine oder Docker Desktop mit Docker Compose v2
- Empfohlen mindestens 2 vCPU und 2 GB RAM für den Docker-Host
- Eine feste LAN-IP oder DHCP-Reservierung für den RootGuard-Host
- Freier TCP- und UDP-Port 53 auf der gewählten Host-Adresse
- Git für das Repository
- Ein starkes Admin-Passwort und ein zufälliges internes API-Token
02A · Plattformnachweis
Saubere Installation, gleiche Prüfung
Der öffentliche Release Candidate wird mit demselben geschützten Ende-zu-Ende-Test auf nativen Linux-amd64-/arm64-Runnern und Docker Desktop geprüft. Der Test umfasst Login, AIO-Bereitstellung, rekursive DNS-Auflösung und die Ablehnung einer ungültigen DNSSEC-Kette.
03 · Installation
Control Plane starten
mkdir rootguard && cd rootguard
curl -LO https://raw.githubusercontent.com/foxly-it/rootguard/v1.0.0-rc.5/compose.release.yaml
curl -Lo .env https://raw.githubusercontent.com/foxly-it/rootguard/v1.0.0-rc.5/.env.release.example
# Zwei unabhängige Sicherheitsschlüssel erzeugen
openssl rand -hex 32
openssl rand -hex 32
# .env ausfüllen, dann RootGuard starten
docker compose -f compose.release.yaml up -dTrage zwei getrennt erzeugte Zufallswerte als ROOTGUARD_API_TOKEN und ROOTGUARD_RECOVERY_TOKEN sowie ein eigenes starkes ROOTGUARD_ADMIN_PASSWORD in .env ein. Der Release Candidate lädt versionierte amd64-/arm64-Images aus GHCR; ein Checkout oder lokaler Build der Komponenten ist nicht erforderlich. Die Control Plane startet zuerst, die DNS-Dienste werden anschließend im Setup erzeugt.
http://localhost:8080/login04 · Erste Einrichtung
DNS-Stack geführt bereitstellen
- 1Anmelden
Verwende ROOTGUARD_ADMIN_USER und ROOTGUARD_ADMIN_PASSWORD. Die Sitzung bleibt serverseitig geschützt und läuft nach zwölf Stunden ab. Ab 0.1.0-alpha.2 bietet „Passwort vergessen?“ zusätzlich eine lokale Wiederherstellung mit einem separaten Recovery-Schlüssel.
- 2Host-Adresse wählen
Wähle eine bereits vorhandene LAN-IP. 0.0.0.0 bindet alle Host-Adressen, eine konkrete LAN-IP begrenzt die Erreichbarkeit enger.
- 3Vorprüfung ausführen
RootGuard prüft Adresse, Port, Docker Engine und Compose, bevor Container verändert werden. Belegte DNS-Ports werden zweistufig erkannt: zunächst anhand bereits veröffentlichter Docker-Ports, danach über einen echten Bindungsversuch auf Host-Ebene, der auch Nicht-Docker-Prozesse wie systemd-resolved oder dnsmasq erfasst. Fehler werden mit Ursache, nächstem Schritt sowie einklappbaren technischen Details erklärt.
- 4Bereitstellen
Unbound wird gestartet und geprüft, danach AdGuard Home intern eingerichtet und ausschließlich mit Unbound als Upstream verbunden.
05 · Router & Clients
RootGuard im Netzwerk verwenden
Trage die im Setup angezeigte feste Host-IP als DNS-Server im Router ein. Verwende niemals 127.0.0.1 oder die interne Docker-Adresse 172.29.53.2 auf anderen Geräten. Port 53 muss für TCP und UDP erreichbar sein.
dig @192.168.178.10 example.com A
dig +dnssec @192.168.178.10 dnssec-failed.org ADie erste Abfrage muss eine Adresse liefern. Die zweite muss mit SERVFAIL enden; dadurch wird eine ungültige DNSSEC-Kette korrekt verworfen.
06 · WebGUI
Die Bereiche der Oberfläche
unbound.conf.Live-Kennzahlen
Das Dashboard aggregiert ausschließlich die CPU- und RAM-Nutzung der fünf fest freigegebenen RootGuard-Container. Zusätzlich liest Core über die intern authentifizierte AdGuard-Home-API die Gesamtzahl der DNS-Anfragen und blockierten Anfragen aus und berechnet daraus die Filterquote. Query-Namen und Clientdaten verlassen AdGuard dabei nicht. Die Anzeige aktualisiert sich automatisch alle zehn Sekunden und kennzeichnet nicht verfügbare Messwerte ausdrücklich.
07 · Unbound
Resolver sicher konfigurieren
Profile und Einstellungen
Balanced, Privacy, Resilience und Performance laden ausschließlich einen Entwurf. QNAME-Minimierung, Prefetch, Serve Expired, Cache-TTLs und Threads werden erklärt und vor der Aktivierung als Änderungsvorschau dargestellt.
IPv4 und IPv6
IPv4 ist der kompatible Standard. Dual Stack und IPv6-only werden erst freigegeben, wenn der laufende Unbound-Container einen autoritativen Root-Server über IPv6 erreicht. Core wiederholt diese Prüfung bei der Aktivierung. Client-Zugriffsregeln bleiben bewusst in AdGuard Home, da Netzwerkgeräte nicht direkt mit Unbound sprechen.
Lokale Zonen
Der geführte Assistent erzeugt A-, AAAA- und CNAME-Einträge ohne manuelle Unbound-Syntax. Für eindeutige A-/AAAA-Adressen kann er passende PTR-Einträge ableiten. Er erkennt parallele Änderungen und verwendet dieselbe Checkconf-, Versions- und Rollback-Kette.
Geräte aus der FRITZ!Box importieren
Findet Hosts über die FRITZ!Box (TR-064) oder begrenzte Reverse-DNS-Abfragen in ausgewählten privaten IPv4- oder Unicast-IPv6-Netzen (max. 256 Adressen je Präfix und insgesamt). Zugangsdaten für die FRITZ!Box sind nur nötig, wenn TR-064-Anfragen eine Anmeldung verlangen, werden ausschließlich für diese eine Abfrage verwendet und nie gespeichert. Gefundene Geräte werden vor der Übernahme einzeln ausgewählt und umbenennbar - nichts wird automatisch importiert. Übernommene Hosts durchlaufen dieselbe Vorschau-, Checkconf- und Aktivierungskette wie die geführten lokalen Zonen.
Private Domains und Reverse DNS
Private Domains werden als geprüfte Liste verwaltet. Für 10/8, 172.16/12 und 192.168/16 wählst du getrennt zwischen sicherem NXDOMAIN und transparenter öffentlicher Weiterauflösung. NXDOMAIN ist die Voreinstellung; RootGuard warnt sichtbar, bevor ein privater Rückwärts-Lookup nach außen gelangen kann.
Conditional Forwarding
Mehrere interne Zonen lassen sich an geordnete IPv4- und IPv6-DNS-Server weiterleiten. RootGuard normalisiert Zonennamen und Adressen, blockiert Schleifen und gibt die Aktivierung erst frei, wenn jedes Ziel die konfigurierte Zone mit NOERROR und einem SOA-Eintrag bestätigt. Rekursiver Fallback, unsignierte private Zonen und private RFC1918-Antworten besitzen getrennte, klar erklärte Opt-ins; DNSSEC und Rebinding-Schutz bleiben sonst aktiv.
Expertenmodus und Live-Konfiguration
Der Editor besitzt nur 90-rootguard-custom.conf und blockiert gefährliche Includes, Listener, Remote Control sowie DNSSEC-Umgehungen. Die Live-Ansicht liest die tatsächlich aktiven Dateien read-only aus dem Container.
Konfiguration exportieren und übertragen
Die vollständige Resolver-Konfiguration (geführte Einstellungen und die Expertenkonfiguration zusammen) lässt sich als eine Datei herunterladen und auf einer anderen RootGuard-Instanz wieder hochladen - für Backups oder eine Migration. Der Import durchläuft dieselbe Vorschau- und Checkconf-Prüfung wie jede andere Aktivierung.
Bestehende unbound.conf übernehmen
Eine vorhandene, handgeschriebene unbound.conf lässt sich einfügen oder hochladen. RootGuard klassifiziert jede Direktive gegen das eigene Ownership-Modell (geführt, feste Basis, Experte oder blockiert) und bietet nicht abgebildete Direktiven wie forward-zone oder local-zone vollständig für den Expertenmodus an, statt sie stillschweigend zu verwerfen - dasselbe Ergebnis wie ein manuelles Einfügen in den Expertenmodus.
08 · AdGuard Home
Geschützte native Verwaltung
AdGuard Home erhält keinen öffentlichen Admin-Port. RootGuard führt den offiziellen Einrichtungsablauf intern durch, erzeugt Zugangsdaten im geschützten Core-Volume und stellt die Oberfläche ausschließlich unter /adguard-ui/ über die angemeldete WebApp bereit.
Blockseite
Statt AdGuards generischer Standardantwort zeigt eine eigene, RootGuard-gebrandete Seite an, warum eine Domain blockiert wurde, inklusive Domain, Zeitpunkt und Client-IP sowie einer verständlichen Erklärung der häufigsten Blockierungsgründe. Die Einrichtung aktiviert AdGuards blocking_mode: custom_ip automatisch und ist per Schalter im Setup deaktivierbar; empfohlen bleibt sie aktiv. Da eine DNS-seitige Blockadresse kein gültiges TLS-Zertifikat für beliebige blockierte Domains vorweisen kann, greift die Seite nur bei HTTP - HTTPS-Anfragen zeigen stattdessen die Zertifikatswarnung des Browsers, ein dokumentiertes Verhalten von AdGuard Home selbst.
09 · Updates & Rollback
Zwei getrennte Sicherheitswege
AdGuard Home, Unbound und Blockseite
Core zieht nur konfigurierte Ziel-Images, vergleicht echte Image-IDs, sichert persistente Dienstpfade und ersetzt genau einen Dienst. DNS, DNSSEC und Upstream werden danach geprüft. Bei Fehlern folgen Daten- und Image-Rollback.
Core und WebApp
Der separate Updater bleibt während des Austauschs aktiv. Er aktualisiert Core und WebApp nur gemeinsam, prüft beide Image-IDs und Health-Endpunkte und pinnt bei einem Fehler beide vorherigen Images. Browser-Anfragen können weder Image-Namen noch Compose-Argumente festlegen.
Einmalig auf dem Host ausführen, auf dem RootGuard läuft (ROOTGUARD_API_TOKEN ist der Wert aus deiner .env):
docker exec rootguard-core wget -qO- \
--header="Authorization: Bearer $ROOTGUARD_API_TOKEN" \
--header="Content-Type: application/json" \
--post-data='{"target_images":{"core":"ghcr.io/foxly-it/rootguard-core:1.0.0-rc.5","webapp":"ghcr.io/foxly-it/rootguard-webapp:1.0.0-rc.5"}}' \
http://updater:8082/api/control-plane/updateVerlauf und begrenztes Aufräumen
Das Stack Center bewahrt bis zu 50 Update-, Fehler-, Rollback- und Cleanup-Ereignisse dauerhaft auf. Erst ein ausdrücklicher Klick lädt die manuelle Bestandsaufnahme; sie zeigt nur ältere, selbst protokollierte Image-IDs und ungenutzte Volumes mit dem Label io.rootguard.cleanup=true samt geschätztem freigebbarem Speicher. Vor dem bestätigten Löschen prüft RootGuard die Auswahl erneut; globale Docker-Prune-Befehle werden nie verwendet.
Interne AdGuard- und Unbound-Update-Backups werden getrennt geschützt. Auf der eigenen Backup-Seite sind Anzahl und Speichernutzung sichtbar; pro Dienst bleiben konfigurierbare 2 bis 50 Wiederherstellungspunkte erhalten (Standard 5). RootGuard löscht nur eindeutig per Pfad und Manifest erkannte eigene Backups. Unbekannte Daten und Symlinks werden angezeigt, aber niemals entfernt.
Für externe Sicherungen erstellt die Backup-Seite ein passwortverschlüsseltes age-v1-Vollbackup mit versioniertem Manifest und SHA-256-Prüfsummen. Es enthält RootGuard-Konfiguration sowie persistente AdGuard-/Unbound-Daten, aber keine Browser-Sitzungen oder externen .env-Geheimnisse. Das Passwort wird nicht gespeichert.
Dasselbe verschlüsselte Archiv kann auf einer sauberen RootGuard-Installation geprüft und wiederhergestellt werden. Archivgrenzen, Manifest, Prüfsummen, Zieladresse, Port und vorhandene Docker-Ressourcen werden vor jeder Änderung erneut geprüft; fehlgeschlagene Versuche räumen ihre neu angelegten Ressourcen auf.
Die zentrale Seite Logs & Diagnose liest ausschließlich die fünf fest freigegebenen Dienste. Core begrenzt jede Ausgabe auf die letzten 30 Minuten, 100 Zeilen und 64 KiB, entfernt Steuerzeichen und redigiert häufige Zugangsdatenmuster; der Browser kann keine freien Container- oder Pfadnamen übergeben.
Bei unveränderlich referenzierten Core- und WebApp-Releases prüft RootGuard außerdem den signierten SLSA-Herkunftsnachweis, die erwartete GitHub-Workflowidentität und die Sigstore-Transparenzdaten. Fehlende oder ungültige Nachweise und vorübergehende Netzfehler werden getrennt angezeigt.
ROOTGUARD_CORE_UPDATE_IMAGE=ghcr.io/foxly-it/rootguard-core:1.0.0-rc.5@sha256:fbc7027b097765c2fa2f332306d15996fc9ab23b6c52a124ea9fedbdf9c882eb
ROOTGUARD_WEBAPP_UPDATE_IMAGE=ghcr.io/foxly-it/rootguard-webapp:1.0.0-rc.5@sha256:1a54b5af14d3a26a305c1f5aa68c76c4ac7df5b38447132488a0cc73436a9d5710 · Sicherheit
Vertrauensgrenzen
- WebApp ohne Docker-Socket und ohne frei ausführbare Host-Befehle
- HttpOnly-, SameSite-Strict-Sitzung und Same-Origin-Prüfung für Schreibzugriffe
- Session-Inventar mit gezielter Sitzungs-Beendigung, Rate-Limiting und Audit-Log für Anmeldung und Passwort-Recovery
- Core und Updater nur in internen Docker-Netzen und mit Bearer-Token
- Unbound read-only, non-root, ohne zusätzliche Capabilities
- AdGuard-Administration ohne öffentlichen Port
- Dokumentiertes Threat Model sowie automatisierte Dependency-, Container-, Secret- und Static-Analysis-Scans in der CI
11 · Betrieb
Nützliche Befehle
# Status der Control Plane
docker compose -f compose.release.yaml ps
# Logs
docker compose -f compose.release.yaml logs --tail=200 core webapp updater
# Control Plane neu starten
docker compose -f compose.release.yaml restart core webapp updater
# Gestoppten Stack wieder starten
docker compose -f compose.release.yaml start
# DNS testen
dig @192.168.178.10 example.com A # durch die eigene Host-IP ersetzenKonfigurations- und Installationszustand liegt in benannten Docker-Volumes. Entferne Volumes nicht mit docker compose down --volumes, solange du keine bewusste Neuinstallation durchführen willst.
12 · Fehlerbehebung
Häufige Probleme
Port 53 ist bereits belegt
Die Vorprüfung erkennt das automatisch - auch bei lokalen Resolvern wie systemd-resolved oder dnsmasq, die nicht als Docker-Container sichtbar sind - und benennt die Ursache in der Fehlermeldung. Stoppe den blockierenden Dienst, oder verwende für Tests einen anderen ROOTGUARD_DNS_PORT; Routerbetrieb benötigt üblicherweise Port 53.
Die WebGUI ist erreichbar, aber APIs schlagen fehl
Prüfe docker compose ps und die Logs von Core und Updater. Nach Ablauf einer Sitzung meldest du dich erneut an. Ein 401 bedeutet eine fehlende Sitzung; ein 502 weist typischerweise auf einen internen Dienst hin.
Ich habe das Admin-Passwort vergessen
Wähle ab 0.1.0-alpha.2 „Passwort vergessen?“ und verwende den unabhängigen ROOTGUARD_RECOVERY_TOKEN aus deiner lokalen .env-Datei. Das neue Passwort muss mindestens zwölf Zeichen haben; danach werden alle bestehenden Sitzungen beendet. Ist kein Recovery-Schlüssel eingerichtet, setze ROOTGUARD_ADMIN_PASSWORD lokal neu und erstelle ausschließlich den WebApp-Container kontrolliert neu.
DNS funktioniert nur auf dem Host
Verwende auf Clients die LAN-IP des Hosts, nicht localhost. Prüfe Firewall, TCP/UDP 53 und ob der Router eigene DNS-Vorgaben oder DoH erzwingt.
Ein Update wurde zurückgerollt
Lies die Meldung unter Stack & Updates und prüfe die Helper-/Core-Logs. Ein Rollback ist ein Schutzmechanismus: Die vorherigen Images bleiben aktiv, bis das Ziel-Image oder die Konfiguration korrigiert wurde.
13 · Konfiguration
Wichtige Umgebungsvariablen
ROOTGUARD_API_TOKENInternes Geheimnis zwischen WebApp, Core und Updater.ROOTGUARD_ADMIN_USERBenutzername für die WebGUI; Standard admin.ROOTGUARD_ADMIN_PASSWORDErforderliches starkes Passwort für die WebGUI.ROOTGUARD_RECOVERY_TOKENAb 0.1.0-alpha.2 erforderlicher separater Zufallsschlüssel für lokale Passwort-Recovery; niemals mit Passwort oder API-Token identisch setzen.ROOTGUARD_WEB_PORTHost-Bindung der WebGUI, beispielsweise 127.0.0.1:8080.ROOTGUARD_UNBOUND_IMAGEFreigegebenes Unbound-Image für die Ersteinrichtung.ROOTGUARD_ADGUARD_IMAGEFreigegebenes AdGuard-Image für die Ersteinrichtung.ROOTGUARD_CORE_UPDATE_IMAGEServerseitiges Ziel für Core-Updates.ROOTGUARD_WEBAPP_UPDATE_IMAGEServerseitiges Ziel für WebApp-Updates.14 · Lizenz
GNU AGPL-3.0-or-later
RootGuard ist freie Open-Source-Software unter einer starken Copyleft-Lizenz. Nutzung, Prüfung, Veränderung und Weitergabe sind erlaubt. Wer eine veränderte Version verteilt oder Nutzern über ein Netzwerk bereitstellt, muss den entsprechenden Quellcode und die Lizenzhinweise zugänglich machen.