Backend: - Audit-Log: Search-Endpoint mit ILIKE-Filter (actor/action/subject/date) - NTP: /ntp/status via chronyc tracking (Stratum, Offset, Quelle) - System: /service-restart mit Allowlist (haproxy/squid/unbound/chrony/scheduler) - Domain-Response-Headers + Rate-Limit (Migration 0024) - Join-Tokens (Migration 0025), Cluster-mTLS, Aggregator-Fan-Out - apt-Service für Update-Banner (apt-get update + Versionsprüfung) - Backup-Retry mit exponential backoff (retry_apt 3×) - publish.sh fail-fast + cleanup-old.sh (max 10 Versionen) Frontend: - Audit-Log-Page (/audit) mit Filter + Pagination - ErrorBoundary an React-Root + Vite build-target festgenagelt (iOS 15+) - Storage-Schema-Stamp: auto-wipe bei Versions-Mismatch (blank-page-Fix) - EmptyState-Komponente überall ausgerollt - SSL: Aggregate-Karte (total/expiring/expired/errors) - Backups: Aggregate-Karte (letzter Backup/Größe/Fehlschläge 24h) + Backup-Now - NTP: Sync-Status-Karte (chronyc tracking live) - Domains: Backend-UP/DOWN-Chip aus HAProxy-Stats - Backends: HAProxy-Status-Spalte (UP/DEGRADED/DOWN) - Settings: Service-Neustart-Karte (haproxy/squid/unbound/chrony/scheduler) - Settings: Upgrade-Status-Card, Wartungsmodus, Auto-Update, Retention - Dashboard: Recent-Alerts, Cluster-Health, License-Chip, Onboarding-Hint - System-Regeln im Firewall als eigener Tab Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
218 lines
8.8 KiB
Markdown
218 lines
8.8 KiB
Markdown
# ⚠️ GOLDENE REGEL — NIEMALS RATEN. IMMER LESEN.
|
|
|
|
**Nicht verhandelbar. Keine Ausnahmen.**
|
|
|
|
Vor jeder Entscheidung über Feldwerte, API-Shapes, Dateinamen, Funktions-Signaturen, Konfigurationsparameter oder Architektur-Details: **erst Original lesen, dann arbeiten**.
|
|
|
|
- **Referenz-Backend** (Go-Patterns, Migrations, Cluster, Packaging) → `ac_search_code(project_id=6)` oder direkt `/var/www/mail-gateway`
|
|
- **Referenz-UI/Bootstrap** (React/AntD, i18n, Design-System, Install-Onliner) → `ac_search_code(project_id=5)` oder direkt `/var/www/netcell-webpanel`
|
|
- **Alter Docker-Stack** (nur für Feature-Scope-Referenz!) → `ac_search_code(project_id=3)` oder `/var/www/proxy-lb-waf`
|
|
- **Im Zweifel → Rückfrage statt Annahme.**
|
|
|
|
---
|
|
|
|
# EdgeGuard Native (`eg`)
|
|
|
|
> Native Neufassung des Docker-basierten EdgeGuard-Stacks. Kein Docker, kein WAF in v1. Zielplattform: **Debian 13 (Trixie), amd64 + arm64**. Auslieferung als signiertes `.deb`.
|
|
|
|
---
|
|
|
|
## Repository & Server
|
|
|
|
- **Gitea:** https://git.netcell-it.de/projekte/edgeguard-native
|
|
- **SSH-Clone:** `ssh://git@git.netcell-it.de:1922/projekte/edgeguard-native.git`
|
|
- **Lokal (Dev):** `/var/www/edgeguard-native` · `ssh linux@89.163.205.87`
|
|
- **Architect Center:** Projekt ID **8**
|
|
- **Git-Server:** git.netcell-it.de · SSH Port 1922 · `git push origin main`
|
|
|
|
---
|
|
|
|
## MCP-Tools (Architect Center)
|
|
|
|
**project_id: 8** · Session: `$ARCHITECT_SESSION` · MCP-Server: `architect`
|
|
|
|
### Beim Session-Start (PFLICHT)
|
|
```
|
|
ac_recall(query="<aktuelle Aufgabe>", project_id=8, session_name="$(printenv ARCHITECT_SESSION)")
|
|
ac_search_code(query="<Stichworte>", project_id=8, session_name="$(printenv ARCHITECT_SESSION)", limit=6)
|
|
```
|
|
|
|
### Alle Tools
|
|
|
|
| Tool | Wann verwenden |
|
|
|------|----------------|
|
|
| `ac_recall(query, project_id=8, session_name)` | Session-Start — relevante Memories laden |
|
|
| `ac_search_code(query, project_id=8, session_name, limit?)` | Vor JEDEM neuen Code schreiben |
|
|
| `ac_search_code_global(query, session_name, limit?)` | Suche über alle Projekte hinweg |
|
|
| `ac_remember(text, category, project_id=8, session_name)` | Jede neue Erkenntnis / Entscheidung |
|
|
| `ac_create_bug(title, description?, priority?, session_name?)` | Bug gefunden |
|
|
| `ac_create_feature(title, description?, priority?, session_name?)` | Feature-Idee |
|
|
| `ac_create_task(title, description?, priority?, status?, project_id?)` | Follow-up Arbeit |
|
|
| `ac_update_task(id, status?, priority?, title?)` | Task-Status ändern |
|
|
| `ac_add_decision(title, content, category?, project_id?)` | Architekturentscheidung |
|
|
| `ac_notify(message, title?, type?)` | Status-Update senden |
|
|
| `ac_get_project(session_name)` | project_id für Session ermitteln |
|
|
| `ac_research(query, context?)` | Doku / CVE / Libraries recherchieren |
|
|
| `ac_review(code, language?, focus?)` | Code-Review nach Fertigstellung |
|
|
| `ac_analyze(text, question?)` | Logs / Outputs analysieren |
|
|
|
|
**`ac_remember` Kategorien:** `decision` · `pattern` · `bugfix` · `convention` · `architecture` · `general`
|
|
|
|
---
|
|
|
|
## Stack
|
|
|
|
| Schicht | Technologie |
|
|
|---------|-------------|
|
|
| **API** | Go 1.26, Gin, GORM (Queries), goose (Migrations) |
|
|
| **UI** | React 19, TypeScript strict, Vite, Ant Design 6, TanStack Query 5 |
|
|
| **DB** | PostgreSQL 16 (Distro-Paket), goose-Migrations in `migrations/` |
|
|
| **State/HA** | KeyDB Active-Active (Redis-kompatibel) |
|
|
| **Proxy/LB** | HAProxy (Distro) — TLS-Termination, L7-Routing, LB |
|
|
| **VPN** | WireGuard (Kernel-Modul ab 5.6, `wireguard-tools`) |
|
|
| **DNS** | Unbound (Distro) — Forwarder+Cache mit DNSSEC, Cluster-internes Split-Horizon |
|
|
| **FW** | nftables (Distro) |
|
|
| **Forward-Proxy** | Squid (Distro) |
|
|
| **TLS** | certbot + webroot-Plugin |
|
|
| **Packaging** | dpkg-deb (direkt, wie mail-gateway + netcell-webpanel) |
|
|
| **Plattform** | Debian 13 Trixie · amd64 + arm64 |
|
|
|
|
---
|
|
|
|
## Nicht-Ziele (v1)
|
|
|
|
- **Kein Docker** — alle Dienste nativ unter systemd
|
|
- **Kein WAF** (kein Coraza, kein ModSecurity)
|
|
- **Kein IDS/IPS** (kein Suricata, kein CrowdSec)
|
|
- **Kein DHCP-Server** (kein Kea)
|
|
- **Kein RADIUS** (kein FreeRADIUS)
|
|
- **Keine Mail-Verarbeitung** (eigenes Produkt: mail-gateway)
|
|
- **Nur Debian 13** — kein Ubuntu, kein Debian 12, kein RHEL
|
|
|
|
---
|
|
|
|
## Binaries & Ports
|
|
|
|
| Binary | Beschreibung | Bindet | User |
|
|
|--------|-------------|--------|------|
|
|
| `edgeguard-api` | REST Management-API | `127.0.0.1:9443` | `edgeguard` |
|
|
| `edgeguard-scheduler` | Cron-Jobs (ACME-Renew, Backup, Health) | — | `edgeguard` |
|
|
| `edgeguard-ctl` | CLI: `initdb migrate cluster-join promote dump-config` | — | root/edgeguard |
|
|
|
|
HAProxy terminiert TLS auf `:443`, routet per Host-Header an Backends und fällt für Management-FQDN/ACME-Webroot auf `127.0.0.1:9443` (edgeguard-api) zurück. Die Management-UI wird von edgeguard-api ausgeliefert (statisch aus `/usr/share/edgeguard/ui/` oder embedded).
|
|
|
|
---
|
|
|
|
## Build
|
|
|
|
```bash
|
|
make build # Host-Architektur (amd64)
|
|
make test # go test ./...
|
|
make lint # golangci-lint
|
|
make deb # amd64 + arm64 .deb
|
|
make publish # deb + Upload Gitea Package Registry
|
|
make install-local # direkt auf Dev-Server installieren (kein .deb)
|
|
|
|
# UI
|
|
cd management-ui && bun install && bun run build
|
|
```
|
|
|
|
---
|
|
|
|
## Dev-Server Quickstart
|
|
|
|
```bash
|
|
# Abhängigkeiten installieren
|
|
sudo apt-get install -y postgresql-16 haproxy wireguard-tools squid unbound nftables certbot
|
|
|
|
# API starten (ohne systemd, für Entwicklung)
|
|
go run ./cmd/edgeguard-api/
|
|
|
|
# UI Dev-Server
|
|
cd management-ui && bun run dev
|
|
```
|
|
|
|
---
|
|
|
|
## Projektstruktur
|
|
|
|
```
|
|
/var/www/edgeguard-native/
|
|
├── cmd/
|
|
│ ├── edgeguard-api/ # Management-API (Gin, 127.0.0.1:9443)
|
|
│ ├── edgeguard-scheduler/ # Cron-Jobs
|
|
│ └── edgeguard-ctl/ # CLI
|
|
├── internal/
|
|
│ ├── database/ # pgxpool + goose-Runner; migrations/ via go:embed
|
|
│ │ └── migrations/ # SQL (goose-Format) — embedded ins Binary
|
|
│ ├── models/ # GORM-Models
|
|
│ ├── handlers/ # HTTP-Handler (REST)
|
|
│ ├── services/ # Business-Logik
|
|
│ ├── haproxy/ # Config-Generator (TLS + Routing + LB)
|
|
│ ├── squid/ # Config-Generator
|
|
│ ├── wireguard/ # Config-Generator
|
|
│ ├── unbound/ # Config-Generator (Forwarder + Cluster-DNS)
|
|
│ ├── firewall/ # nftables-Generator
|
|
│ ├── cluster/ # Join/Promote/Peer-Discovery
|
|
│ ├── proxy/ # Write-Proxy → Cluster-Primary
|
|
│ ├── aggregator/ # Cluster-View APIs
|
|
│ └── license/ # Lizenz-Validierung
|
|
├── management-ui/ # React 19 + AntD 6 (1:1 enconf-Pattern)
|
|
├── packaging/debian/ # control, postinst, postrm, systemd-Units
|
|
├── deploy/
|
|
│ ├── systemd/ # *.service, *.target, *.timer
|
|
│ ├── haproxy/ # (Templates liegen jetzt neben Renderer in internal/<svc>/)
|
|
│ ├── squid/ # squid.conf.tpl
|
|
│ ├── unbound/ # unbound.conf.tpl
|
|
│ └── nftables/ # ruleset.nft.tpl
|
|
├── scripts/
|
|
│ ├── apt-repo/ # build-package.sh, publish.sh
|
|
│ └── install.sh # Bootstrap curl-Onliner
|
|
├── docs/
|
|
│ └── architecture.md # Vollständige Architektur-Spec
|
|
├── go.mod
|
|
├── Makefile
|
|
├── CLAUDE.md # Diese Datei
|
|
└── agent.md # Agent-Factory Pipeline
|
|
```
|
|
|
|
---
|
|
|
|
## Key Conventions
|
|
|
|
### Go-Code
|
|
- **Migrations:** goose SQL-Dateien in `internal/database/migrations/`, via `//go:embed` ins Binary — NICHT GORM AutoMigrate
|
|
- **ORM:** GORM für Queries, nicht für Schema-Verwaltung
|
|
- **Config-Generierung:** Template-Datei in `deploy/*/`, Generator in `internal/*/`
|
|
- **Config-Reload:** `systemctl reload <service>` nach Config-Schreiben
|
|
- **Cluster-Writes:** immer über `internal/proxy` → Primary-URL aus KeyDB `cluster:pg-primary-url`
|
|
|
|
### Packaging
|
|
- `dpkg-deb` direkt (wie mail-gateway) — kein dh_make/debhelper/fpm
|
|
- postinst: User anlegen → Dirs → initdb (idempotent) → migrate → systemctl
|
|
- postrm purge: nur bei `purge` DB + User entfernen
|
|
|
|
### UI
|
|
- 100% enconf-Pattern (netcell-webpanel/management-ui/) — keine eigenen Design-Entscheidungen
|
|
- `import type` für alle Type-Imports (verbatimModuleSyntax!)
|
|
- AntD 6, kein Tailwind, kein Material UI
|
|
|
|
### Auth
|
|
- JWT-basiert (analog enconf), Secret in `/var/lib/edgeguard/.jwt_fingerprint`
|
|
- Admin-Check: immer aus DB-User-Row, nie aus JWT-Payload
|
|
|
|
---
|
|
|
|
## Vollständige Architektur
|
|
|
|
→ `docs/architecture.md`
|
|
|
|
---
|
|
|
|
## Vor jeder Änderung
|
|
|
|
1. Referenz-Pattern in mail-gateway oder netcell-webpanel lesen
|
|
2. `ac_search_code` vor neuem Code — Pattern existiert meist schon
|
|
3. `make test` nach Backend-Änderungen
|
|
4. `cd management-ui && npx tsc --noEmit` nach Frontend-Änderungen
|