RootGuard

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
Release-Candidate-HinweisRootGuard befindet sich in der Release-Candidate-Phase: Kernpfade, Updates mit Rollback und unveränderliche, attestierte Releases sind produktionsreif. Bis zum finalen 1.0-Release erscheinen nur noch Bugfixes und Dokumentation - halte trotzdem Backups und einen alternativen DNS-Weg bereit, wie bei jeder Netzwerkinfrastruktur.

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.

Linux amd64Nativer automatischer GitHub-Runner
Linux arm64Nativer automatischer GitHub-Runner
Docker DesktopApple Silicon / arm64 am 28.07.2026 erfolgreich

Prüfmatrix und sicheren Wiederholungstest öffnen ↗

03 · Installation

Control Plane starten

Automatische InstallationFür die schnelle Variante mit automatischer Docker-Erkennung/-Installation, automatisch erzeugten Sicherheitsschlüsseln und einer kurzen Abfrage für Benutzername/Passwort siehe den Ein-Befehl-Schnellstart auf der Startseite. Der folgende Weg zeigt jeden Schritt einzeln zum manuellen Nachvollziehen. Ein-Befehl-Schnellstart öffnen ↗
shell
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 -d

Trage 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.

browser
http://localhost:8080/login

04 · Erste Einrichtung

DNS-Stack geführt bereitstellen

  1. 1
    Anmelden

    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.

  2. 2
    Host-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.

  3. 3
    Vorprü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.

  4. 4
    Bereitstellen

    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.

Prüfung von einem Client
dig @192.168.178.10 example.com A
dig +dnssec @192.168.178.10 dnssec-failed.org A

Die 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

DashboardInstallation, DNS-Endpunkt, Dienste, DNSSEC und Verbindungskette sowie echte CPU-/RAM- und aggregierte AdGuard-Kennzahlen auf einen Blick.
EinrichtungNetzwerk-Preflight und persistenter AIO-Bereitstellungsfortschritt.
Stack & UpdatesDienstzustand, sichere Updates und Verlauf bleiben sofort sichtbar; technische Release-Details sind einklappbar und die geschützte Docker-Bereinigung wird erst auf Anforderung geprüft.
BackupsWiederherstellungspunkte, verschlüsselter Export und saubere Vollwiederherstellung. Eine Auswahl führt außerdem direkt zum RootGuard-Unbound-Paket oder zum Import einer vorhandenen unbound.conf.
Logs & DiagnoseZentrale, durchsuchbare Protokolle für alle verwalteten Dienste mit lokaler Filterung, optionaler Aktualisierung und redigiertem Diagnosebericht.
UnboundProfile, geführte Einstellungen, Zonen, Live-Konfiguration und Direktiven in großen Detailansichten, Experteneditor und Rollback.
AdGuard HomeRootGuard-Status und geschützter Zugriff auf die native AdGuard-Oberfläche.

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.

Upstream-SchutzRootGuard erwartet Unbound fest unter 172.29.53.2:5335 und prüft diese Kette nach Start und Update.

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.

Update ab 0.1.0-beta.14 oder älterCore-Versionen bis einschließlich 0.1.0-beta.14 erkennen 1.0.0-rc.1 nicht automatisch als verfügbares Update - die Versionserkennung war fest auf das alte Schema 0.1.0-(alpha|beta).N begrenzt. Bestehende Installationen auf diesem Stand müssen einmalig manuell auf das neue Release zeigen; danach erkennt der aktualisierte Core jedes folgende Release wieder normal automatisch.

Einmalig auf dem Host ausführen, auf dem RootGuard läuft (ROOTGUARD_API_TOKEN ist der Wert aus deiner .env):

shell
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/update
Realer Rollback-TestDie Updater-CI ersetzt echte Core- und WebApp-Testcontainer gemeinsam. Ein absichtlich fehlerhafter WebApp-Kandidat liefert HTTP 503; der Test weist danach beide vorherigen laufenden Image-IDs und den gespeicherten Rollback-Verlauf nach.

Verlauf 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.

Unveränderliche Release-ImagesDer öffentliche Release-Stack kombiniert lesbare Versions-Tags mit geprüften Multi-Arch-Digests. Docker startet damit exakt das veröffentlichte Artefakt, selbst wenn ein Tag später verändert würde.
.env
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:1a54b5af14d3a26a305c1f5aa68c76c4ac7df5b38447132488a0cc73436a9d57

10 · 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
HTTPSRootGuard terminiert bewusst kein eigenes TLS - das übernimmt ein etablierter Reverse Proxy davor. Die Dokumentation deckt die zwei Voraussetzungen (Host-Header-Weiterleitung, X-Forwarded-Proto) und Beispielkonfigurationen für Caddy, Zoraxy, Nginx Proxy Manager und HAProxy ab. HTTPS-Anleitung öffnen ↗

Vollständiges Threat Model öffnen ↗

11 · Betrieb

Nützliche Befehle

shell
# 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 ersetzen

Konfigurations- und Installationszustand liegt in benannten Docker-Volumes. Entferne Volumes nicht mit docker compose down --volumes, solange du keine bewusste Neuinstallation durchführen willst.

Saubere NeuinstallationDer Setup-Controller erzeugt zusätzliche benannte DNS-Volumes außerhalb der Control-Plane-Compose. Ein normales Stoppen löscht keine Daten. Entferne Container und Volumes nur bewusst nach einem Backup und anhand der versionsgleichen Release-Hinweise.

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.

Marke und LogoDie Softwarelizenz erteilt keine Rechte an den Namen RootGuard und Foxly IT oder an den zugehörigen Logos. Forks dürfen ihre Herkunft beschreiben, aber keine offizielle Unterstützung oder Zugehörigkeit vortäuschen.