feat(setup): Cluster-Node-Modus im Setup-Wizard + Install-Script-Port-Fix
Setup-Wizard zeigt jetzt beim ersten Aufruf eine Modusauswahl: - "Neuinstallation" → bisheriger Flow (Admin-Account + FQDN + ACME) - "Cluster-Knoten beitreten" → nur FQDN + ACME, kein Admin-Account; nach dem Submit werden die cluster-join-Befehle direkt angezeigt Backend: NodeRequest + Store.CompleteAsNode() + POST /setup/complete-node State: is_cluster_node Flag; login via PG-Replikation vom Primary Install-Script: Setup-URL zeigt jetzt korrekt :3443/setup statt /setup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,52 +63,87 @@
|
||||
"emptyDesc": "Zonen gruppieren Interfaces (lan, wan, dmz). Vordefinierte Zonen sind bereits da; eigene anlegen wenn du z. B. eine separate dmz-Zone oder eine wg-Zone fürs VPN brauchst."
|
||||
},
|
||||
"ao": {
|
||||
"name": "Name", "kind": "Typ", "value": "Wert", "description": "Beschreibung",
|
||||
"add": "Adress-Objekt hinzufügen", "edit": "Adress-Objekt bearbeiten",
|
||||
"name": "Name",
|
||||
"kind": "Typ",
|
||||
"value": "Wert",
|
||||
"description": "Beschreibung",
|
||||
"add": "Adress-Objekt hinzufügen",
|
||||
"edit": "Adress-Objekt bearbeiten",
|
||||
"deleteConfirm": "Adress-Objekt {{name}} wirklich löschen?",
|
||||
"emptyTitle": "Noch keine Adress-Objekte.",
|
||||
"emptyDesc": "Wiederverwendbare benannte IPs/Netze/Ranges für Firewall- und NAT-Regeln (z. B. office-net = 10.0.0.0/24, mailbox-1 = 10.0.1.42)."
|
||||
},
|
||||
"ag": {
|
||||
"name": "Name", "members": "Mitglieder", "description": "Beschreibung",
|
||||
"add": "Adress-Gruppe hinzufügen", "edit": "Adress-Gruppe bearbeiten",
|
||||
"name": "Name",
|
||||
"members": "Mitglieder",
|
||||
"description": "Beschreibung",
|
||||
"add": "Adress-Gruppe hinzufügen",
|
||||
"edit": "Adress-Gruppe bearbeiten",
|
||||
"selectMembers": "Adress-Objekte wählen",
|
||||
"deleteConfirm": "Adress-Gruppe {{name}} wirklich löschen?",
|
||||
"emptyTitle": "Noch keine Adress-Gruppen.",
|
||||
"emptyDesc": "Bündele mehrere Adress-Objekte zu einer Gruppe (z. B. office-locations = [hq-net, branch-1-net, branch-2-net]) — Regeln müssen dann nur eine Gruppe referenzieren."
|
||||
},
|
||||
"svc": {
|
||||
"name": "Name", "proto": "Protokoll", "ports": "Ports",
|
||||
"portStart": "Port (Start)", "portEnd": "Port (Ende)",
|
||||
"description": "Beschreibung", "builtinHint": "Vordefiniert — nicht editierbar",
|
||||
"add": "Service hinzufügen", "edit": "Service bearbeiten",
|
||||
"name": "Name",
|
||||
"proto": "Protokoll",
|
||||
"ports": "Ports",
|
||||
"portStart": "Port (Start)",
|
||||
"portEnd": "Port (Ende)",
|
||||
"description": "Beschreibung",
|
||||
"builtinHint": "Vordefiniert — nicht editierbar",
|
||||
"add": "Service hinzufügen",
|
||||
"edit": "Service bearbeiten",
|
||||
"deleteConfirm": "Service {{name}} wirklich löschen?",
|
||||
"emptyTitle": "Noch keine eigenen Services.",
|
||||
"emptyDesc": "Vordefinierte (HTTP, HTTPS, SSH, …) sind bereits da. Eigene Services für app-spezifische Ports (z. B. mailcow-imaps tcp/993) erleichtern Regeln deutlich."
|
||||
},
|
||||
"sg": {
|
||||
"name": "Name", "members": "Mitglieder", "description": "Beschreibung",
|
||||
"add": "Service-Gruppe hinzufügen", "edit": "Service-Gruppe bearbeiten",
|
||||
"name": "Name",
|
||||
"members": "Mitglieder",
|
||||
"description": "Beschreibung",
|
||||
"add": "Service-Gruppe hinzufügen",
|
||||
"edit": "Service-Gruppe bearbeiten",
|
||||
"selectMembers": "Services wählen",
|
||||
"deleteConfirm": "Service-Gruppe {{name}} wirklich löschen?",
|
||||
"emptyTitle": "Noch keine Service-Gruppen.",
|
||||
"emptyDesc": "Bündele mehrere Services zu einer Gruppe (z. B. web-stack = [HTTP, HTTPS, HTTP/3]) — eine Regel mit der Gruppe ersetzt drei Regeln pro Service."
|
||||
},
|
||||
"rule": {
|
||||
"name": "Name", "priority": "Priority", "enabled": "Aktiv", "log": "Logging",
|
||||
"action": "Aktion", "src": "Quelle", "dst": "Ziel", "service": "Service",
|
||||
"srcZone": "Quell-Zone", "dstZone": "Ziel-Zone",
|
||||
"srcKind": "Quell-Typ", "dstKind": "Ziel-Typ",
|
||||
"object": "Adress-Objekt", "group": "Adress-Gruppe",
|
||||
"serviceKind": "Service-Typ", "serviceGroup": "Service-Gruppe",
|
||||
"name": "Name",
|
||||
"priority": "Priority",
|
||||
"enabled": "Aktiv",
|
||||
"log": "Logging",
|
||||
"action": "Aktion",
|
||||
"src": "Quelle",
|
||||
"dst": "Ziel",
|
||||
"service": "Service",
|
||||
"srcZone": "Quell-Zone",
|
||||
"dstZone": "Ziel-Zone",
|
||||
"srcKind": "Quell-Typ",
|
||||
"dstKind": "Ziel-Typ",
|
||||
"object": "Adress-Objekt",
|
||||
"group": "Adress-Gruppe",
|
||||
"serviceKind": "Service-Typ",
|
||||
"serviceGroup": "Service-Gruppe",
|
||||
"comment": "Kommentar",
|
||||
"hits": "Hits",
|
||||
"add": "Regel hinzufügen", "edit": "Regel bearbeiten",
|
||||
"add": "Regel hinzufügen",
|
||||
"edit": "Regel bearbeiten",
|
||||
"deleteConfirm": "Diese Regel wirklich löschen?",
|
||||
"namePlaceholder": "z.B. SSH von Office erlauben",
|
||||
"cidr": "CIDR",
|
||||
"actions": { "accept": "ACCEPT", "drop": "DROP", "reject": "REJECT" },
|
||||
"kinds": { "any": "Beliebig", "object": "Objekt", "group": "Gruppe", "cidr": "CIDR" },
|
||||
"actions": {
|
||||
"accept": "ACCEPT",
|
||||
"drop": "DROP",
|
||||
"reject": "REJECT"
|
||||
},
|
||||
"kinds": {
|
||||
"any": "Beliebig",
|
||||
"object": "Objekt",
|
||||
"group": "Gruppe",
|
||||
"cidr": "CIDR"
|
||||
},
|
||||
"duplicate": "Regel duplizieren",
|
||||
"duplicated": "Regel dupliziert (deaktiviert, Priorität +1).",
|
||||
"cidrInvalid": "Gültiges CIDR eingeben (z.B. 10.0.0.0/24)",
|
||||
@@ -139,16 +174,27 @@
|
||||
"noResultsHint": "Filter zurücksetzen um alle Regeln zu sehen."
|
||||
},
|
||||
"nat": {
|
||||
"name": "Name", "priority": "Priority", "kind": "Typ", "enabled": "Aktiv",
|
||||
"match": "Match", "target": "Ziel",
|
||||
"inZone": "Eingangs-Zone", "outZone": "Ausgangs-Zone", "proto": "Protokoll",
|
||||
"matchSrcCidr": "Source-CIDR (Match)", "matchDstCidr": "Dest-CIDR (Match)",
|
||||
"name": "Name",
|
||||
"priority": "Priority",
|
||||
"kind": "Typ",
|
||||
"enabled": "Aktiv",
|
||||
"match": "Match",
|
||||
"target": "Ziel",
|
||||
"inZone": "Eingangs-Zone",
|
||||
"outZone": "Ausgangs-Zone",
|
||||
"proto": "Protokoll",
|
||||
"matchSrcCidr": "Source-CIDR (Match)",
|
||||
"matchDstCidr": "Dest-CIDR (Match)",
|
||||
"matchDstCidrHint": "leer = jede dest-IP (z.B. öffentliche IP der Box)",
|
||||
"dportStart": "Port (Start)", "dportEnd": "Port (Ende)",
|
||||
"dportStart": "Port (Start)",
|
||||
"dportEnd": "Port (Ende)",
|
||||
"portRangeError": "End-Port muss ≥ Start-Port sein",
|
||||
"targetAddr": "Ziel-Adresse", "targetPortStart": "Ziel-Port (Start)", "targetPortEnd": "Ziel-Port (Ende)",
|
||||
"targetAddr": "Ziel-Adresse",
|
||||
"targetPortStart": "Ziel-Port (Start)",
|
||||
"targetPortEnd": "Ziel-Port (Ende)",
|
||||
"comment": "Kommentar",
|
||||
"add": "NAT-Regel hinzufügen", "edit": "NAT-Regel bearbeiten",
|
||||
"add": "NAT-Regel hinzufügen",
|
||||
"edit": "NAT-Regel bearbeiten",
|
||||
"deleteConfirm": "Diese NAT-Regel wirklich löschen?",
|
||||
"namePlaceholder": "z.B. HTTP zu Web-Backend weiterleiten",
|
||||
"emptyTitle": "Noch keine NAT-Regeln.",
|
||||
@@ -156,7 +202,10 @@
|
||||
},
|
||||
"sys": {
|
||||
"title": "System-Regeln (immer aktiv)",
|
||||
"chain": "Chain", "match": "Match", "action": "Aktion", "note": "Hinweis",
|
||||
"chain": "Chain",
|
||||
"match": "Match",
|
||||
"action": "Aktion",
|
||||
"note": "Hinweis",
|
||||
"policy": "Default-Policy",
|
||||
"policyValue": "Eingang DROP — alles muss explizit erlaubt werden.",
|
||||
"order": "Auswertung",
|
||||
@@ -266,11 +315,116 @@
|
||||
"licenseKeyHint": "Wenn vorhanden: 30-Tage-Trial wird übersprungen, Features unmittelbar freigeschaltet. Kann auch später unter License nachgereicht werden.",
|
||||
"submit": "Setup abschließen",
|
||||
"successTitle": "Setup abgeschlossen",
|
||||
"successHint": "Du wirst zur Anmeldung weitergeleitet."
|
||||
"successHint": "Du wirst zur Anmeldung weitergeleitet.",
|
||||
"back": "Zurück",
|
||||
"modeSelect": "Wie soll dieser Server eingerichtet werden?",
|
||||
"modeStandalone": "Neuinstallation",
|
||||
"modeStandaloneDesc": "Eigenständiger EdgeGuard oder erster Cluster-Knoten. Erstellt einen Admin-Account auf diesem Server.",
|
||||
"modeNode": "Vorhandenem Cluster beitreten",
|
||||
"modeNodeDesc": "Diesen Server als zweiten Cluster-Knoten hinzufügen. Admin-Zugangsdaten werden automatisch vom Primary repliziert.",
|
||||
"nodeTitle": "Cluster-Knoten einrichten",
|
||||
"nodeIntro": "Trage den FQDN dieses Knotens ein. Es wird kein Admin-Account erstellt — die Zugangsdaten kommen nach der Datenbankreplikation vom Primary.",
|
||||
"nodePreflightTitle": "Vor dem Fortfahren",
|
||||
"nodePreflightDesc": "Stelle sicher, dass EdgeGuard auf dem Primary bereits läuft und du dort einen Join-Token erstellen kannst (Cluster-Seite). Du benötigst ihn im nächsten Schritt.",
|
||||
"nodeSubmit": "Als Cluster-Knoten einrichten",
|
||||
"nodeSuccessTitle": "Knoten konfiguriert",
|
||||
"nodeJoinTitle": "Nächster Schritt: Cluster beitreten",
|
||||
"nodeJoinDesc": "Dieser Server ({{fqdn}}) ist konfiguriert. Führe jetzt den Join-Befehl aus, um ihn mit dem Primary zu verbinden.",
|
||||
"nodeStep1Title": "Join-Token auf dem Primary generieren",
|
||||
"nodeStep1Desc": "Öffne die Cluster-Seite auf deinem Primary-EdgeGuard → Knoten hinzufügen → Join-Token generieren. Token kopieren.",
|
||||
"nodeStep2Title": "Join-Befehl auf diesem Server ausführen",
|
||||
"nodeStep2Desc": "Ersetze <primary-fqdn> mit dem FQDN deines Primarys und <token> mit dem Token aus Schritt 1:",
|
||||
"nodeStep3Title": "API neu starten",
|
||||
"nodeStep3Desc": "Nach erfolgreichem Join-Befehl API neu starten, damit die replizierte Konfiguration übernommen wird:",
|
||||
"nodeLoginNote": "Der Login erfolgt mit den Admin-Zugangsdaten des Primarys. Das funktioniert sobald die Datenbankreplikation aufgebaut wurde (der Join-Befehl richtet das ein)."
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
"welcomeHint": "Übersicht aller laufenden EdgeGuard-Komponenten."
|
||||
"welcomeHint": "EdgeGuard-Übersicht — Health, Counts, Live-Status der wichtigsten Dienste.",
|
||||
"kpi": {
|
||||
"domains": "Domains",
|
||||
"backends": "Backends",
|
||||
"ifaces": "Interfaces",
|
||||
"fwRules": "FW-Regeln",
|
||||
"natRules": "NAT-Regeln",
|
||||
"wg": "WG-Verbindungen"
|
||||
},
|
||||
"wgCard": {
|
||||
"title": "WireGuard",
|
||||
"empty": "Noch kein WG-Tunnel angelegt.",
|
||||
"peersOnline": "{{online}} / {{total}} Peers verbunden"
|
||||
},
|
||||
"firewallCard": {
|
||||
"title": "Firewall",
|
||||
"zones": "Zonen",
|
||||
"activeRules": "{{rules}} aktive Regeln · {{nat}} NAT"
|
||||
},
|
||||
"sslCard": {
|
||||
"title": "SSL-Zertifikate",
|
||||
"total": "Verwaltete Zertifikate",
|
||||
"certExpired": "{{count}} Zertifikat(e) abgelaufen — sofort erneuern",
|
||||
"expiringSoon": "{{count}} läuft bald ab (< 30 Tage)",
|
||||
"allFresh": "Alle Zertifikate haben > 30 Tage Restlaufzeit."
|
||||
},
|
||||
"clusterCard": {
|
||||
"title": "Cluster",
|
||||
"nodes": "Knoten",
|
||||
"modeSingle": "Single-Node",
|
||||
"modeCluster": "Cluster",
|
||||
"drift": "Config-Drift erkannt",
|
||||
"health": {
|
||||
"ok": "OK",
|
||||
"degraded": "degraded",
|
||||
"split-brain": "split-brain"
|
||||
}
|
||||
},
|
||||
"routingCard": {
|
||||
"title": "Routing",
|
||||
"domains": "Domains",
|
||||
"backends": "Backends",
|
||||
"attached": "{{count}}/{{total}} Domains haben einen Primary-Backend"
|
||||
},
|
||||
"systemCard": {
|
||||
"title": "System",
|
||||
"version": "Version",
|
||||
"api": "API",
|
||||
"ifaces": "Interfaces",
|
||||
"wg": "WireGuard"
|
||||
},
|
||||
"alertsCard": {
|
||||
"title": "Aktuelle Alerts",
|
||||
"viewAll": "Alle anzeigen"
|
||||
},
|
||||
"downBackendsAlert": "{{count}} Backend(s) komplett ausgefallen — kein Server UP",
|
||||
"maintenanceAlert": "{{count}} Domain(s) im Wartungs-Modus",
|
||||
"onboardingTitle": "Willkommen bei EdgeGuard",
|
||||
"onboardingIntro": "Frische Box — hier die nächsten Schritte um Customer-Traffic zu routen:",
|
||||
"onboardingStep1": "Backend-Pool anlegen (App-Server hinter HAProxy)",
|
||||
"onboardingStep2": "Domain hinzufügen (FQDN, primary Backend zuweisen)",
|
||||
"onboardingStep3": "TLS-Zertifikat ausstellen (Let's Encrypt HTTP-01)",
|
||||
"servicesCard": {
|
||||
"title": "Service-Status (live, 10s)"
|
||||
},
|
||||
"activityCard": {
|
||||
"title": "Letzte Aktivität (Audit-Log)",
|
||||
"empty": "Noch keine Aktivität — Mutationen werden hier protokolliert."
|
||||
},
|
||||
"haproxyCard": {
|
||||
"title": "HAProxy-Backends (live)",
|
||||
"empty": "Keine Backend-Stats erreichbar (HAProxy down oder admin.sock-permission).",
|
||||
"frontends": "Listener"
|
||||
},
|
||||
"resCard": {
|
||||
"load": "Load",
|
||||
"memory": "Memory",
|
||||
"disk": "Disk /",
|
||||
"free": "frei",
|
||||
"conntrack": "Conntrack",
|
||||
"uptime": "Uptime"
|
||||
},
|
||||
"licenseOk": "Lizenz OK",
|
||||
"licenseTrial": "Trial",
|
||||
"licenseTrialDays": "Trial · {{days}}d"
|
||||
},
|
||||
"domains": {
|
||||
"title": "Domains",
|
||||
@@ -680,7 +834,10 @@
|
||||
"wg": {
|
||||
"title": "WireGuard",
|
||||
"intro": "VPN-Tunnel über WireGuard. Server-Modus = wir lauschen für Peers; Client-Modus = wir verbinden zu einem festen Upstream. Privater Schlüssel liegt verschlüsselt in der DB.",
|
||||
"tabs": { "servers": "Server-Tunnel", "clients": "Client-Tunnel" },
|
||||
"tabs": {
|
||||
"servers": "Server-Tunnel",
|
||||
"clients": "Client-Tunnel"
|
||||
},
|
||||
"serverIntro": "Server-Tunnel hosten ein Peer-Roster — z.B. Mitarbeiter-Geräte oder Niederlassungen. Pro Peer bekommt der Operator eine .conf zum Download (oder QR-Code für Mobile).",
|
||||
"clientIntro": "Client-Tunnel verbinden EdgeGuard zu einem fremden WireGuard-Server (z.B. HQ-Datacenter). Allowed-IPs steuert, welcher Traffic durch den Tunnel geroutet wird.",
|
||||
"iface": {
|
||||
@@ -767,98 +924,14 @@
|
||||
"failed": "Import fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
"welcomeHint": "EdgeGuard-Übersicht — Health, Counts, Live-Status der wichtigsten Dienste.",
|
||||
"kpi": {
|
||||
"domains": "Domains",
|
||||
"backends": "Backends",
|
||||
"ifaces": "Interfaces",
|
||||
"fwRules": "FW-Regeln",
|
||||
"natRules": "NAT-Regeln",
|
||||
"wg": "WG-Verbindungen"
|
||||
},
|
||||
"wgCard": {
|
||||
"title": "WireGuard",
|
||||
"empty": "Noch kein WG-Tunnel angelegt.",
|
||||
"peersOnline": "{{online}} / {{total}} Peers verbunden"
|
||||
},
|
||||
"firewallCard": {
|
||||
"title": "Firewall",
|
||||
"zones": "Zonen",
|
||||
"activeRules": "{{rules}} aktive Regeln · {{nat}} NAT"
|
||||
},
|
||||
"sslCard": {
|
||||
"title": "SSL-Zertifikate",
|
||||
"total": "Verwaltete Zertifikate",
|
||||
"certExpired": "{{count}} Zertifikat(e) abgelaufen — sofort erneuern",
|
||||
"expiringSoon": "{{count}} läuft bald ab (< 30 Tage)",
|
||||
"allFresh": "Alle Zertifikate haben > 30 Tage Restlaufzeit."
|
||||
},
|
||||
"clusterCard": {
|
||||
"title": "Cluster",
|
||||
"nodes": "Knoten",
|
||||
"modeSingle": "Single-Node",
|
||||
"modeCluster": "Cluster",
|
||||
"drift": "Config-Drift erkannt",
|
||||
"health": {
|
||||
"ok": "OK",
|
||||
"degraded": "degraded",
|
||||
"split-brain": "split-brain"
|
||||
}
|
||||
},
|
||||
"routingCard": {
|
||||
"title": "Routing",
|
||||
"domains": "Domains",
|
||||
"backends": "Backends",
|
||||
"attached": "{{count}}/{{total}} Domains haben einen Primary-Backend"
|
||||
},
|
||||
"systemCard": {
|
||||
"title": "System",
|
||||
"version": "Version",
|
||||
"api": "API",
|
||||
"ifaces": "Interfaces",
|
||||
"wg": "WireGuard"
|
||||
},
|
||||
"alertsCard": {
|
||||
"title": "Aktuelle Alerts",
|
||||
"viewAll": "Alle anzeigen"
|
||||
},
|
||||
"downBackendsAlert": "{{count}} Backend(s) komplett ausgefallen — kein Server UP",
|
||||
"maintenanceAlert": "{{count}} Domain(s) im Wartungs-Modus",
|
||||
"onboardingTitle": "Willkommen bei EdgeGuard",
|
||||
"onboardingIntro": "Frische Box — hier die nächsten Schritte um Customer-Traffic zu routen:",
|
||||
"onboardingStep1": "Backend-Pool anlegen (App-Server hinter HAProxy)",
|
||||
"onboardingStep2": "Domain hinzufügen (FQDN, primary Backend zuweisen)",
|
||||
"onboardingStep3": "TLS-Zertifikat ausstellen (Let's Encrypt HTTP-01)",
|
||||
"servicesCard": {
|
||||
"title": "Service-Status (live, 10s)"
|
||||
},
|
||||
"activityCard": {
|
||||
"title": "Letzte Aktivität (Audit-Log)",
|
||||
"empty": "Noch keine Aktivität — Mutationen werden hier protokolliert."
|
||||
},
|
||||
"haproxyCard": {
|
||||
"title": "HAProxy-Backends (live)",
|
||||
"empty": "Keine Backend-Stats erreichbar (HAProxy down oder admin.sock-permission).",
|
||||
"frontends": "Listener"
|
||||
},
|
||||
"resCard": {
|
||||
"load": "Load",
|
||||
"memory": "Memory",
|
||||
"disk": "Disk /",
|
||||
"free": "frei",
|
||||
"conntrack": "Conntrack",
|
||||
"uptime": "Uptime"
|
||||
},
|
||||
"licenseOk": "Lizenz OK",
|
||||
"licenseTrial": "Trial",
|
||||
"licenseTrialDays": "Trial · {{days}}d"
|
||||
},
|
||||
"ntp": {
|
||||
"title": "Zeitserver (Chrony)",
|
||||
"intro": "Chrony als Time-Sync-Daemon (NTP). Quellen oben, Listen-/Serve-Konfig im Settings-Tab. Wenn 'serve_clients' aktiv und LAN-IPs gebound sind, wird die Box selbst zum NTP-Server für das LAN.",
|
||||
"tabs": { "pools": "Quellen", "settings": "Settings", "peers": "Peer-Status" },
|
||||
"tabs": {
|
||||
"pools": "Quellen",
|
||||
"settings": "Settings",
|
||||
"peers": "Peer-Status"
|
||||
},
|
||||
"sourcesCard": {
|
||||
"title": "Live Peer-Status (chronyc sources)",
|
||||
"name": "Name / IP",
|
||||
@@ -934,7 +1007,11 @@
|
||||
"dns": {
|
||||
"title": "DNS (Unbound)",
|
||||
"intro": "Unbound-Resolver auf :53. Lokale Zonen (authoritativ aus DNS-Records) und Forward-Zonen (per stub-zone weiter zu fremden Resolvern). Default-Forwarder für alles andere.",
|
||||
"tabs": { "zones": "Zonen", "settings": "Resolver-Settings", "stats": "Resolver-Stats" },
|
||||
"tabs": {
|
||||
"zones": "Zonen",
|
||||
"settings": "Resolver-Settings",
|
||||
"stats": "Resolver-Stats"
|
||||
},
|
||||
"statsCard": {
|
||||
"title": "Resolver-Statistiken (unbound-control stats_noreset)",
|
||||
"totalQueries": "Abfragen gesamt",
|
||||
@@ -1043,22 +1120,22 @@
|
||||
},
|
||||
"actions": {
|
||||
"allow": "allow — Zugriff erlauben",
|
||||
"deny": "deny — Zugriff blockieren"
|
||||
"deny": "deny — Zugriff blockieren"
|
||||
},
|
||||
"aclTypes": {
|
||||
"src": "src — Quell-IP/CIDR",
|
||||
"dst": "dst — Ziel-IP/CIDR",
|
||||
"dstdomain": "dstdomain — Ziel-Domain (exact)",
|
||||
"srcdomain": "srcdomain — Quell-Domain (rDNS)",
|
||||
"port": "port — Ziel-Port",
|
||||
"proto": "proto — http/https/ftp/...",
|
||||
"method": "method — GET/POST/CONNECT/...",
|
||||
"time": "time — Wochentag/Zeit",
|
||||
"url_regex": "url_regex — kompletter URL-Match",
|
||||
"src": "src — Quell-IP/CIDR",
|
||||
"dst": "dst — Ziel-IP/CIDR",
|
||||
"dstdomain": "dstdomain — Ziel-Domain (exact)",
|
||||
"srcdomain": "srcdomain — Quell-Domain (rDNS)",
|
||||
"port": "port — Ziel-Port",
|
||||
"proto": "proto — http/https/ftp/...",
|
||||
"method": "method — GET/POST/CONNECT/...",
|
||||
"time": "time — Wochentag/Zeit",
|
||||
"url_regex": "url_regex — kompletter URL-Match",
|
||||
"urlpath_regex": "urlpath_regex — Path-Teil",
|
||||
"dstdom_regex": "dstdom_regex — Domain-Regex",
|
||||
"srcdom_regex": "srcdom_regex — Quell-Domain-Regex",
|
||||
"browser": "browser — User-Agent-Regex"
|
||||
"dstdom_regex": "dstdom_regex — Domain-Regex",
|
||||
"srcdom_regex": "srcdom_regex — Quell-Domain-Regex",
|
||||
"browser": "browser — User-Agent-Regex"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -1173,7 +1250,10 @@
|
||||
"intro": "Notification-Channels für kritische Events. Webhook (Slack/Discord/Teams/Generic-HTTP) oder Email (SMTP). Triggers: cert.expiring (<14 d), cert.renew_failed, backup.failed, license.invalid.",
|
||||
"scopeTitle": "Was triggert Alarme?",
|
||||
"scopeDesc": "cert.expiring — TLS-Zertifikat <14 Tage Restzeit (dedupe 12h). cert.renew_failed — ACME-Renewer hat Fails. backup.failed — Scheduled Backup konnte nicht erstellt werden. license.invalid — License-Server liefert valid=false. backend.down — alle Server eines Backend-Pools sind DOWN (2-Min-Check, dedupe 12h). disk.full — Root-Filesystem ≥80% Warnung, ≥90% Critical (stündlich, dedupe 12h). mem.high — RAM-Auslastung ≥85% Warnung, ≥95% Critical (5-Min-Check, dedupe 12h). conntrack.high — Conntrack-Tabelle ≥80% Warnung, ≥90% Critical; bei 100% werden alle neuen Verbindungen lautlos verworfen (2-Min-Check, dedupe 12h). ntp.unsync — chrony hat keine synchronisierte Zeitquelle; Drift führt zu TLS- und JWT-Fehlern (10-Min-Check, dedupe 12h). wg.tunnel.down — WireGuard-Client-Tunnel hat seit >5 Min keinen Handshake; Remote-Traffic wird lautlos verworfen (5-Min-Check, dedupe 12h).",
|
||||
"tabs": { "channels": "Channels", "events": "History" },
|
||||
"tabs": {
|
||||
"channels": "Channels",
|
||||
"events": "History"
|
||||
},
|
||||
"add": "Channel hinzufügen",
|
||||
"addTitle": "Notification-Channel anlegen",
|
||||
"editTitle": "Channel bearbeiten",
|
||||
@@ -1264,11 +1344,21 @@
|
||||
"run": "Ausführen",
|
||||
"runFromBoxTitle": "Tools laufen auf der EdgeGuard-Box",
|
||||
"runFromBoxDesc": "Diese Aufrufe nutzen die Outbound-Connectivity der EdgeGuard — nicht deinen lokalen Rechner. Wenn ping/curl auf der Box scheitert, ist das Box-Network-Layer das Problem (Firewall-Rules, Default-Route, DNS).",
|
||||
"ping": { "intro": "ICMP echo-request × 4, 2s Timeout pro Paket. Misst Loss + RTT." },
|
||||
"trace": { "intro": "Hop-by-Hop-Pfad mit UDP-Probes (max 20 Hops, kein reverse-DNS)." },
|
||||
"dig": { "intro": "DNS-Lookup über unbound (Box-Resolver). Zeigt Antwort + AUTHORITY/ADDITIONAL Section." },
|
||||
"curl": { "intro": "HTTPS-Probe mit -IsSv: TLS-Handshake-Details + Header. Folgt KEINE Redirects." },
|
||||
"tcp": { "intro": "Pure TCP-Connect ohne I/O. Ideal um zu prüfen ob ein Backend-Port erreichbar ist." },
|
||||
"ping": {
|
||||
"intro": "ICMP echo-request × 4, 2s Timeout pro Paket. Misst Loss + RTT."
|
||||
},
|
||||
"trace": {
|
||||
"intro": "Hop-by-Hop-Pfad mit UDP-Probes (max 20 Hops, kein reverse-DNS)."
|
||||
},
|
||||
"dig": {
|
||||
"intro": "DNS-Lookup über unbound (Box-Resolver). Zeigt Antwort + AUTHORITY/ADDITIONAL Section."
|
||||
},
|
||||
"curl": {
|
||||
"intro": "HTTPS-Probe mit -IsSv: TLS-Handshake-Details + Header. Folgt KEINE Redirects."
|
||||
},
|
||||
"tcp": {
|
||||
"intro": "Pure TCP-Connect ohne I/O. Ideal um zu prüfen ob ein Backend-Port erreichbar ist."
|
||||
},
|
||||
"securityTitle": "Sicherheits-Hinweis",
|
||||
"securityDesc": "Endpoints sind hinter Admin-Auth. Targets werden gegen eine strikte Allow-Liste validiert (keine Shell-Metazeichen). curl ist auf http(s) beschränkt — kein file:// / smb:// / data://.",
|
||||
"noOutput": "(kein Output)"
|
||||
@@ -1278,7 +1368,10 @@
|
||||
"intro": "Sicherungen der PostgreSQL-Datenbank + /var/lib/edgeguard (Setup, License, JWT, ACME-Account). Täglicher Auto-Job + manueller Trigger.",
|
||||
"scopeTitle": "Was wird gesichert?",
|
||||
"scopeDesc": "DB-Dump (pg_dump --clean), setup.json, license_key, license.cache, .jwt_fingerprint, acme-account/. Konfig-Dateien (haproxy.cfg, nft, …) sind aus der DB regenerierbar und werden NICHT mitgesichert.",
|
||||
"tabs": { "history": "Sicherungen", "remotes": "Off-Site-Ziele" },
|
||||
"tabs": {
|
||||
"history": "Sicherungen",
|
||||
"remotes": "Off-Site-Ziele"
|
||||
},
|
||||
"statLastSuccess": "Letzte erfolgreiche Sicherung",
|
||||
"statTotal": "Erfolgreiche Sicherungen",
|
||||
"statSize": "Gesamtgröße",
|
||||
|
||||
Reference in New Issue
Block a user