Pro-Domain-Flag crowdsec_trusted (Migration 0048). Ist es gesetzt, rendert der
neue crowdsec-whitelist-Generator den Hostname host-genau in
/etc/crowdsec/parsers/s02-enrich/edgeguard-admin-hosts-whitelist.yaml
(evt.Parsed.http_host) und reloadet crowdsec. Löst das Problem, dass Admin-SPAs
(viele /api/-Requests pro Aktion) http-crawl-non_statics triggern und die
Admin-IP bannen — jetzt im Frontend steuerbar statt manueller Node-Datei.
- Generator internal/crowdsec/whitelist.go (configgen.Generator, no-op ohne
CrowdSec), registriert in edgeguard-ctl render-config + in den Domains-Reloader
komponiert (Domain-Edit → Whitelist re-render). Aus der replizierten DB
gerendert → überlebt Node-Neuaufbau (Ersatz für die manuelle Node-Datei).
- postinst: sudoers reload crowdsec + edgeguard-owned Whitelist-Datei anlegen
(dir root-owned → Generator überschreibt nur die vorab-chownte Datei) +
Initial-Render.
- UI: Switch „Vertrauenswürdiges Admin-Panel" im Domain-Detail.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Domain kann per 301 auf eine andere Domain/URL umgeleitet werden, statt
auf ein Backend zu routen (Use-Case: kvs.netcell-it.de → https://zkm.netcell-it.de,
inkl. HTTPS). Variante (a): immer auf Ziel-Root (`redirect location`), pfad-
unabhängig.
- Migration 0043: domains.redirect_to text NOT NULL DEFAULT ''
- Model + domains-Service (SELECT/INSERT/UPDATE/scan)
- HAProxy-Generator: buildRedirectTo() sanitisiert (nur http(s), kein
Whitespace/Quotes → sonst kein Redirect statt kaputter Config); Template
emittiert `http-request redirect location <url> code 301 if hdr(host)`.
Terminiert vor use_backend → Redirect-Domain routet auf kein Backend.
http→https läuft über den vorhandenen :80-Redirect (zwei Hops, inkl. TLS).
- UI: Feld „Weiterleitung (301) nach" im Domain-Formular (de/en)
- Tests: Render-Zeile + buildRedirectTo-Sanitisierung
Hinweis: Die Redirect-Domain braucht weiterhin ein eigenes TLS-Zert (ACME).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Abgelaufene und fehlerhafte Zertifikate zeigen jetzt beim Hover den
Fehlertext (last_error) aus der DB. TLSCertLite um last_error erweitert.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pattern-Validator lehnt offensichtlich ungültige Adressen (Sonderzeichen,
Leerzeichen) schon im Frontend ab, bevor sie HAProxy-Config-Generierung
zerstören können. Gilt für Backend-Server-Modal und Domain-Quick-Backend.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BackendLite interfaces in Domains list and Detail declared address/port
fields that don't exist on the Backend model (those live on BackendServer).
Every backend tag rendered as "name (undefined:undefined)". Fixed by
replacing the phantom fields with scheme, so tags show e.g. "my-app (https)".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ActionButtons: Edit-Button wird für Viewer wie Delete gesperrt (Tooltip zeigt Reason)
- Domains/Detail: isViewer-Flag an alle Sub-Panels weitergegeben; Save-, TLS-Cert-,
Routing-Rules- und Headers-Buttons für Viewer disabled
- Backends/Detail: Save-Button + ServerPanel Add-Button für Viewer disabled
- i18n: domains.backendUp/backendDown Keys (waren noch hardkodiert)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NTP-Pools, User-Accounts, Backend-Server im Detail-Panel und
Routing-Rules im Domain-Detail-Panel — alle aktiv-Felder sind
jetzt inline schaltbar, kein Modale nötig.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend: force_http1 (bool, default false) — zwingt HAProxy auf der
Backend-Verbindung zu HTTP/1.1 statt h2,http/1.1 zu verhandeln.
Nötig für Legacy-Apps die kein h2 sprechen.
Domain: disable_h3 (bool, default false) — unterdrückt Alt-Svc-
Response-Header für diese Domain. Browser erhalten keinen h3/QUIC-
Hinweis und bleiben auf h2/http1.1.
Migration 0027, Model+Service+HAProxy-Template+UI+i18n.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Statt aller 15+ Felder in einem Modal gibt es jetzt eine eigene Seite
unter /domains/:id. Der Create-Flow bleibt im Modal (Name, Backend, Active,
HTTP→HTTPS), ein Hinweistext führt nach dem Speichern auf die Detailseite
weiter.
Die Detailseite enthält links das vollständige Settings-Formular (HSTS,
Rate-Limit, Maintenance, Max-Body, Notes, WWW-Redirect) und rechts das
HeadersPanel zum Verwalten custom HTTP-Response-Header.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pages auf PageHeader/StatusDot/ActionButtons-Pattern migriert:
* Dashboard — Komplett-Rewrite. KPI-Tiles (Domains, Backends, Iface,
FW-Rules, NAT, WG), Detail-Cards (WireGuard live status, Firewall
zone overview, SSL expiring soon, Cluster nodes, Routing summary,
System info). Polled queries pro Card.
* Domains, Backends, RoutingRules, Networks, IPAddresses, SSL,
Cluster, Settings, Firewall (index) — alle inline Action-Buttons
→ ActionButtons; alle Yes/No-Renders → StatusDot; Add-Button in
DataTable.extraActions; PageHeader oben.
WireGuard
---------
* Neuer /wireguard/status-Endpoint parsed `wg show all dump`,
liefert {iface, peer_pubkey, endpoint, last_handshake_unix, rx, tx}.
Sudoers im postinst um `wg show` erweitert.
* Server-Drawer Peer-Liste zeigt jetzt Live-Status (Online/Offline-
Dot, "vor Xs", Traffic-Counter) per 10s-Polling. Importierte
"Unify Home" peer kann jetzt im UI verifiziert werden.
* Importer-Bug fixed: nextName ("# Unify Home" comment) wurde beim
Sektionswechsel zu früh geresettet — jetzt nur nach echtem
flushPeer.
Routing-Rules
-------------
* Aus Sidebar entfernt. URL bleibt funktional, aber für 90% der
Setups reicht domains.primary_backend_id (das HAProxy ohnehin
als default_backend rendert). Path-basiertes Routing ist ein
Advanced-Feature und kommt später als Domain-Modal-Tab zurück.
* nav.routing-Sidebar-Eintrag + BranchesOutlined-Import entfernt.
Misc
----
* "Firewall (v2)" → "Firewall" im Nav (DE).
* Dashboard-i18n Block in DE+EN.
* Version 1.0.11 → 1.0.12.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Migration 0012: firewall_zones (id, name UNIQUE, description, builtin),
Seed wan/lan/dmz/mgmt/cluster als builtin. CHECK-Constraints auf
network_interfaces.role + firewall_rules.{src,dst}_zone +
firewall_nat_rules.{in,out}_zone gedroppt — Validation lebt jetzt
app-side (Handler prüft Existenz in firewall_zones).
* Backend: firewall.ZonesRepo (CRUD + Exists + References-Lookup),
/api/v1/firewall/zones, builtin geschützt (Name nicht änderbar,
Delete blockiert), Rename eines Custom-Zone aktuell ohne Cascade
(Handler-Sorge bei Rules/NAT/Networks).
* Handler-Validation in CreateRule/UpdateRule/CreateNAT/UpdateNAT +
NetworksHandler: Zone-Existence-Check pro Mutation, 400 bei Tippfehler.
* Frontend: Firewall-Tab "Zonen" (CRUD mit builtin-Schutz). Networks-
Form lädt Rollen aus /firewall/zones (statt hardcoded Liste); Rules-
und NAT-Forms ziehen die Zone-Auswahl ebenfalls aus der API.
* Domain-Form bekommt Primary-Backend-Picker (Field war im Modell,
fehlte im UI). Backends-Tabelle zeigt umgekehrt welche Domains
darauf zeigen — bidirektionale Sicht ohne Schemaänderung.
* HAProxy-Renderer: safeID-FuncMap escaped Server-Namen mit Whitespace
("Control Master 1" → "Control_Master_1"). Vorher ist haproxy beim
Reload an Spaces im Backend-Namen kaputt gegangen.
* Version 1.0.3 → 1.0.6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DataTable (components/DataTable.tsx) gibt jeder CRUD-Tabelle drei
Baseline-Features auf einmal:
* Search-Input (Volltext über alle string-Felder, case-insensitive)
* Pagination 25/Seite mit showSizeChanger
* Auto-sorter pro Spalte mit dataIndex (string→localeCompare,
number→subtract, boolean→bool→Number) — Spalten mit eigenem
sorter behalten den.
Sweep aller 13 CRUD-Pages auf <DataTable>: Domains, Backends,
Routing-Rules, Networks, IP-Addresses, SSL, Cluster, sechs Firewall-
Tabs. Kleine Sub-Tabellen (System-Discovered IP-Card) bleiben
auf <Table> — read-only ohne CRUD braucht keine Pagination.
i18n: common.search, common.totalRows.
Version-Bump auf 1.0.0 (User-Direktive: ohne -dev): VERSION-Datei,
Go-Literale in cmd/edgeguard-{api,ctl,scheduler}/main.go,
package.json, Sidebar-Konstante. Live deployed auf 89.163.205.6 als
edgeguard 1.0.0 (api + ui + meta).
Memory: project_versioning.md hält die Patch-Bump-Konvention fest
(Gitea Package Registry 409't bei Doppel-Upload — bei jedem Release
zuerst die VERSION inkrementieren).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scaffold und Core-Infrastruktur 1:1 nach enconf-Pattern (netcell-
webpanel/management-ui), reduziert auf EdgeGuard-Scope (kein reseller/
customer-Roles, keine codemirror/extensions). Stack: React 19 + AntD 6
+ TS strict + Vite + TanStack-Query + zustand + react-i18next.
Layout: AppLayout (Sider+Header+Content), Sidebar (Dashboard/Domains),
Header (User-Dropdown + Logout). i18n mit de/en common.json.
Pages: Login (POST /auth/login), Setup-Wizard (POST /setup/complete),
Dashboard (Health-Polling + Statistics), Domains (volles CRUD via
TanStack-Query gegen /domains-API). UpdateBanner-Komponente
(/system/package-versions, alle 5 min poll, /system/upgrade trigger)
ist von Tag 1 wie vom User gefordert eingebaut.
API-Wiring: cmd/edgeguard-api/main.go mountUI() — gin StaticFS für
/usr/share/edgeguard/ui/ (overridebar via EDGEGUARD_UI_DIR), echte
Files werden direkt geserved, alle nicht-API-Pfade fallen via
NoRoute auf index.html für React-Router-SPA. Wenn dist/ fehlt:
HTML-Placeholder mit Build-Hinweis.
Verifiziert: bun install + npx tsc -b strict (0 errors) + bun run
build (12 chunks). End-to-end gegen /tmp/eg-api: / serviert echte
React-index.html, /domains SPA-Fallback, /api/v1/* JSON, /assets/*
direkt, /api/v1/nonexistent korrekt 404.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>