212 lines
12 KiB
Markdown
212 lines
12 KiB
Markdown
# Changelog
|
||
|
||
Alle nennenswerten Änderungen an Clusev. Format nach
|
||
[Keep a Changelog](https://keepachangelog.com), Versionierung nach
|
||
[SemVer](https://semver.org).
|
||
|
||
**Release-Prozess:** Feature-Commits sammeln sich auf dem Branch. Ist ein Stand
|
||
reif, wird er nach `main` gemerged, als `vX.Y.Z` getaggt und hier unter einer
|
||
eigenen Versionsüberschrift dokumentiert. Nutzer beziehen ausschließlich
|
||
getaggte Releases (Kanal `stable`, optional `beta`) — niemals Entwicklungs-Builds.
|
||
|
||
## [Unreleased]
|
||
|
||
_Keine offenen Änderungen — der nächste Stand wird hier gesammelt und als `vX.Y.Z` getaggt._
|
||
|
||
## [0.4.1] - 2026-06-14
|
||
|
||
### Behoben
|
||
- **Verstümmelter Header auf jeder eingeloggten Seite.** Ein Kommentar im `@php`-Block der
|
||
topbar enthielt die literalen Tokens `@php`/`@endphp`; Blades Raw-Block-Matcher nahm das
|
||
`@endphp` im Kommentar als Block-Ende und gab den Rest (inkl. `$title ??= …`) als Klartext im
|
||
`<header>` aus — der Seitentitel blieb zudem leer. Kommentar bereinigt; neue Regel **R17**
|
||
(keine Direktiv-Tokens in Blade-Kommentaren; gerenderte Ausgabe prüfen, nicht nur HTTP 200).
|
||
|
||
### Sicherheit
|
||
- **Realtime-Kanäle sind jetzt privat.** Der Live-Metrik-Broadcast (`MetricsTicked`) läuft über
|
||
einen `PrivateChannel`, autorisiert über `/broadcasting/auth` (im `web`-Group → PanelScheme +
|
||
Session). Damit kann niemand mehr allein mit dem (öffentlich gebündelten) App-Key Infrastruktur-
|
||
Metriken abonnieren — auch nicht über einen alten Caddy-Host nach einem Domain-Wechsel. Neue
|
||
Konvention (CLAUDE.md §3 / `routes/channels.php`): **jeder** Broadcast-Kanal ist privat.
|
||
|
||
## [0.4.0] - 2026-06-14
|
||
|
||
Die Panel-Domain ist wieder aus dem Dashboard änderbar — diesmal sicher: gespeichert wird in der Datenbank, angewendet beim Neustart, das Zertifikat holt Caddy automatisch.
|
||
|
||
### Hinzugefügt
|
||
- **Domain aus dem Dashboard ändern.** Auf der System-Seite lässt sich die Panel-Domain
|
||
eintragen oder leeren. Gespeichert wird als Einstellung (`panel_domain`, übersteuert die
|
||
Installations-Domain `APP_DOMAIN`); nach einem Stack-Neustart leiten sich URL, der
|
||
WebSocket-Endpunkt (Reverb), das TLS-Zertifikat und die Cookie-Sicherheit automatisch davon
|
||
ab. Kein Terminal-Editieren mehr — nur „speichern und neu starten".
|
||
- **Automatisches TLS per On-Demand (Caddy).** Caddy stellt das Zertifikat beim ersten
|
||
HTTPS-Zugriff aus und fragt vorher die App (`/_caddy/ask`), ob für genau diese Domain
|
||
ausgestellt werden darf — so kann keine fremde, auf die IP gezeigte Domain Zertifikate
|
||
erzwingen. Voraussetzung bleibt: die Domain zeigt per DNS auf den Server.
|
||
|
||
### Geändert
|
||
- Der Reverb-Client (Browser) bezieht seinen Endpunkt jetzt zur Laufzeit aus der aktuellen
|
||
Anfrage und läuft über dieselbe Adresse wie das Panel (Proxy/Reverse-Tunnel `/app/*`,
|
||
`/apps/*` — Caddy in Produktion, nginx in Dev). So folgt Realtime jeder Domain-Änderung
|
||
ohne Neu-Bauen der Assets und ohne separat geöffneten Port.
|
||
- Server-seitiges Event-Publishing läuft intern direkt zum `reverb`-Dienst, ist damit
|
||
unabhängig von der öffentlichen Domain/dem Zertifikat.
|
||
|
||
### Sicherheit
|
||
- **Kein Aussperren.** Sicherer-Cookie-Schalter und HTTPS-Redirect richten sich nach der
|
||
tatsächlichen Anfrage (hinter Caddy via `X-Forwarded-*`, das nur in Produktion vertraut
|
||
wird). Der Zugriff per **IP über HTTP bleibt immer als Rückfallweg erreichbar**, falls
|
||
eine neue Domain (DNS/Zertifikat) noch nicht bereit ist.
|
||
- **Nur die aktive Domain liefert das Panel aus.** Bei gesetzter Domain wird das Panel per
|
||
Hostname ausschließlich über genau diese Domain (HTTPS) bedient; eine alte/fremde, auf den
|
||
Server gezeigte Domain wird abgewiesen (404) — auch wenn Caddy ihr Zertifikat noch hält.
|
||
|
||
## [0.3.0] - 2026-06-13
|
||
|
||
Zweisprachige Oberfläche: die gesamte UI gibt es jetzt auf Deutsch und Englisch, frei umschaltbar pro Konto.
|
||
|
||
### Hinzugefügt
|
||
- **Sprache wählbar (Deutsch / Englisch).** Ein DE/EN-Umschalter (oben rechts, sowie auf der
|
||
Login-Seite) stellt die Sprache um; die Wahl wird pro Konto gespeichert und gilt sofort für
|
||
die gesamte Oberfläche. Ohne Wahl greift die Standardsprache (Deutsch).
|
||
- Übersetzungen liegen strukturiert unter `lang/{de,en}/<gruppe>.php` — eine Gruppe je Feature
|
||
plus geteiltes `common`, Schlüssel in beiden Sprachen identisch.
|
||
|
||
### Geändert
|
||
- **Alle sichtbaren Texte sind lokalisiert.** Views, Komponenten und Backend-Services geben
|
||
Text ausschließlich über `__('gruppe.schlüssel')` aus, nie mehr fest verdrahtet — neue,
|
||
verbindliche Regel **R16**. Native Technik-Begriffe (`nginx.service`, `SSH`, `2FA`, Ports)
|
||
bleiben unverändert.
|
||
|
||
### Entfernt
|
||
- Erläuternde „Warum …?"-Texte auf der System-Seite — die Seite zeigt nur noch Funktion und
|
||
Status.
|
||
|
||
## [0.2.1] - 2026-06-13
|
||
|
||
Verfeinerungen an 0.2.0: vollautomatisches TLS ohne sichtbare Konfiguration und einheitliche Buttons.
|
||
|
||
### Geändert
|
||
- **TLS ist vollautomatisch.** Caddy stellt das Zertifikat aus, erneuert es und leitet
|
||
HTTP→HTTPS um — ohne manuelle Schritte. Die System-Seite zeigt nur noch den **Status**
|
||
(Domain, Zugriffsadresse) statt der erzeugten Caddy-Konfiguration und des
|
||
`caddy reload`-Befehls. Die Panel-Domain ist eine **Installations-Entscheidung**
|
||
(`APP_DOMAIN`) und bleibt damit konsistent mit URL, WebSocket (wss) und Cookie-Sicherheit;
|
||
zum Ändern `install.sh` mit der neuen Domain erneut ausführen.
|
||
- Härtungs-Checkliste: alle Aktions-Buttons im selben Stil (einheitlich `secondary`,
|
||
mit Rahmen) statt zustandsabhängig mal mit, mal ohne Rahmen.
|
||
|
||
### Entfernt
|
||
- Laufzeit-Override der App-URL aus der Datenbank und das dashboard-seitige Bearbeiten
|
||
von Domain/E-Mail (konnte URL/WebSocket/Cookies nicht konsistent zur Laufzeit umstellen).
|
||
Eine Migration entfernt die leeren Alt-Einträge; ein real konfigurierter Wert bleibt als
|
||
Verlauf erhalten. **Upgrade-Hinweis:** eine zuvor im Dashboard gesetzte Domain bitte einmalig
|
||
über `install.sh` setzen.
|
||
|
||
## [0.2.0] - 2026-06-13
|
||
|
||
Mehr-Betriebssystem-Verwaltung, echte Firewall- und fail2ban-Steuerung aus dem Dashboard sowie eine Tastatur-/Befehls-Bedienung.
|
||
|
||
### Hinzugefügt
|
||
- **OS-Abstraktion**: Updates, Härtung und Firewall laufen jetzt über **apt, dnf und
|
||
zypper** (Debian/Ubuntu, RHEL/Fedora/Rocky/Alma, openSUSE). Das Betriebssystem wird
|
||
erkannt und auf der Server-Detailseite angezeigt (Paketverwaltung/Firewall). Arch
|
||
und Alpine werden erkannt; nicht unterstützte Funktionen werden mit deutschem
|
||
Hinweis sauber deaktiviert statt fehlzuschlagen.
|
||
- **Firewall-Regeln (UFW)**: Regeln ansehen, hinzufügen und löschen samt
|
||
Standard-Anzeige — mit Aussperr-Schutz (SSH-Regeln/-Port, deny ohne Port). firewalld
|
||
wird nur angezeigt (Laufzeit aller aktiven Zonen inkl. Rich Rules); Regelverwaltung
|
||
bleibt vorerst UFW.
|
||
- **fail2ban-Status**: Jails mit Zählern, **gebannte IPs sehen und entsperren**,
|
||
IP manuell sperren (R5-Dialog, Aussperr-Schutz für Loopback + eigenen Zugang) und
|
||
**Whitelist (ignoreip)** verwalten.
|
||
- **Befehls-Palette (Strg/⌘-K)** + Tastenkürzel: Schnell-Navigation (Leader „g“),
|
||
Seitensuche („/“), Hilfe („?“).
|
||
|
||
### Geändert
|
||
- System-Updates verwenden je Distribution den passenden Paketmanager
|
||
(Audit-Aktion `system.package_upgrade`).
|
||
- fail2ban-Tuning und -Whitelist liegen in getrennten Drop-ins, damit Änderungen sich
|
||
nicht gegenseitig überschreiben; das frühere Einzel-Drop-in wird migriert.
|
||
- Server-Detailseite zeigt erkanntes System, Paketverwaltung und Firewall-Werkzeug.
|
||
- System-Seite erklärt jetzt, warum TLS über Caddy terminiert wird.
|
||
|
||
### Sicherheit
|
||
- Firewall: race-freies Löschen per Regel-Spezifikation (keine Regelnummern),
|
||
Whitelisting gegen Befehls-Injection, firewalld-Lockout-Schutz (Ports vor dem Start
|
||
in der permanenten Konfiguration).
|
||
- fail2ban: kanonischer (inet_pton) Schutz gegen das Sperren des eigenen Zugangs,
|
||
ignoreip wird verbatim erhalten (inkl. Hostnames/Fortsetzungszeilen).
|
||
|
||
## [0.1.1] - 2026-06-13
|
||
|
||
Wartungs-Release: vollständige Code-Auditierung, Entfernung von totem Code und ein behobenes Open-Redirect. Keine funktionalen Änderungen für Nutzer.
|
||
|
||
### Behoben
|
||
- Open-Redirect im Server-Switcher: ein manipulierter `Referer` konnte die
|
||
Weiterleitung nach dem Server-Wechsel auf eine fremde Adresse lenken. Die
|
||
Weiterleitung wird jetzt auf einen **gleich-origin** relativen Pfad reduziert
|
||
(fremde Schemata wie `javascript:`/`data:`, andere Hosts/Ports sowie
|
||
protokoll-relative Tricks `//host` / `/\host` werden abgewiesen).
|
||
- SSH-Zugang: eine Passphrase wurde unabhängig vom Auth-Typ gespeichert; sie wird
|
||
jetzt nur noch bei Schlüssel-Authentifizierung hinterlegt.
|
||
|
||
### Geändert
|
||
- Datei-Manager + Editor verwenden ein eigenes `file`-Symbol statt des
|
||
Audit-Symbols (semantisch korrekt).
|
||
- Code-Hygiene: toten Code entfernt (ungenutzte `FirewallService`-Methoden
|
||
`status/allow/deny`, `Server::auditEvents()`, `SshCredential::scopeActive()`,
|
||
ungenutztes `bell`-Icon), veraltete Doc-Blöcke/Kommentare korrigiert,
|
||
Exceptions sauber importiert, base64-Argument im Sudo-Pfad defensiv gequotet,
|
||
Null-sichere Nutzerabfrage in den Einstellungen. Pint + Codex-Review sauber.
|
||
|
||
## [0.1.0] - 2026-06-13
|
||
|
||
Erste geschnittene Version — die komplette v1-Basis inklusive Server- und Panel-Härtung als ein Release.
|
||
|
||
### Hinzugefügt
|
||
- Dashboard mit Live-Sparklines und poll-getriebenem Dual-Chart (KPIs + Tabelle).
|
||
- Server-Index + Detailseite, Dienste (systemd: Start/Stop/Restart + Journal),
|
||
Datei-Manager (SFTP: Up-/Download, Editor), Audit-Log.
|
||
- SSH-Schicht über phpseclib (exec + SFTP) mit Host-Key-Pinning (TOFU) und
|
||
Multi-Server-Switcher samt Fleet-Kontext.
|
||
- Echte Metriken (CPU/RAM/Disk/Load) inkl. Absolutwerten über Reverb.
|
||
- Authentifizierung + 2FA (TOTP) mit erzwungenem Onboarding.
|
||
- R5-Bestätigungsmodals (wire-elements/modal) für destruktive Aktionen.
|
||
- System-Seite mit Domain & TLS (Caddy Auto-TLS) und Release-Kanal.
|
||
- Echte Versions-Seite, die Version, Build-Hash und dieses Änderungsprotokoll liest.
|
||
- Deploy: `install.sh` + Caddy (Auto-TLS) + Produktions-Härtung.
|
||
- Selbst-gehostete Fonts (kein CDN), Split-Brand Login/2FA.
|
||
|
||
### Geändert
|
||
- Dienst-Steuerung läuft über das hinterlegte Sudo-Passwort (`sudo -S`) statt nur
|
||
passwortlosem sudo — Start/Stop/Restart + Journal funktionieren live.
|
||
- Lazy-Loading der Seiten (Skeletons), normalisierte Buttons + Spinner,
|
||
Detailseiten- und Einstellungs-Redesign, Schlüsselerzeugung.
|
||
- Vollständige Regel-Auditierung (R1–R14), neue Regel R14 (lokale Fonts).
|
||
|
||
### Behoben
|
||
- Datei-Editor: Klick löste einen Alpine-Fehler aus (`@js()` kompiliert nicht in
|
||
Komponenten-Attributen) — auf Index-Lookups umgestellt.
|
||
- Adversarial Review der SSH-Schicht (Escaping, Parser, Host-Key-Pinning).
|
||
- 500 durch `@disabled` auf `<x-btn>`; Modal über dem Backdrop; poll-getriebene
|
||
Metriken (Chart + Gauges) statt fiktiver Fleet-Daten; 2FA-Setup-QR als `<img>`.
|
||
- fail2ban/apt-Härtung schlug fehl, weil der 12s-SSH-Timeout den Paket-Install
|
||
abbrach — langer Timeout für apt-Aktionen.
|
||
|
||
### Sicherheit
|
||
- Server-Härtung aus dem Dashboard (Root-/Passwort-Login, fail2ban, UFW,
|
||
Auto-Updates) mit Befehls-Vorschau, Bestätigung und Aussperr-Schutz.
|
||
- Verwaltung hinterlegter SSH-Zugänge (Name, Sperren, Löschen); der Vault
|
||
verweigert gesperrte Zugänge. Dienst-Steuerung über hinterlegtes Sudo-Passwort.
|
||
- Panel-Selbst-Härtung: Security-Header + umgebungsbewusste CSP, 2FA-Brute-Force-
|
||
Drossel, Session-Cookie-Härtung.
|
||
- Release-/Versionierungsmodell: echte semantische Versionen + Git-Tags, Changelog
|
||
pro Version, Kanäle `stable`/`beta` (kein nutzer-seitiges `dev`).
|
||
|
||
[Unreleased]: https://git.bave.dev/boban/clusev/compare/v0.2.1...HEAD
|
||
[0.2.1]: https://git.bave.dev/boban/clusev/compare/v0.2.0...v0.2.1
|
||
[0.2.0]: https://git.bave.dev/boban/clusev/compare/v0.1.1...v0.2.0
|
||
[0.1.1]: https://git.bave.dev/boban/clusev/compare/v0.1.0...v0.1.1
|
||
[0.1.0]: https://git.bave.dev/boban/clusev/releases/tag/v0.1.0
|