Commit Graph

261 Commits (72973e3ca5cc80802e1e2b66c69af69dfe166333)

Author SHA1 Message Date
boban 72973e3ca5 Fix: installer.sh — UI_HAS_CERT unbound variable in mailwolt-apply-domains
UI_HAS_CERT/WM_HAS_CERT wurden im Subshell ( ... ) > NGINX_SITE definiert.
Nach dem Subshell waren sie im Outer Scope ungebunden — mit set -euo pipefail
führte das zu "unbound variable" Crash bei der State-Datei-Zuweisung.
Variablen vor den Subshell in den Outer Scope verschoben.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:18:48 +02:00
boban 8ff1aeac2a Fix: Wizard Step 5 — per-Domain-Fortschritt, Cert-Fallback, ssl_configured
- mailwolt-apply-domains schreibt jetzt pro Domain running/done/error/nodns
  in die State-Dateien während certbot läuft (statt alles auf einmal am Ende)
- get_cert_dir() erstellt fullchain.pem/privkey.pem Symlinks auf cert.pem/key.pem
  wenn kein LE-Zertifikat vorhanden — verhindert nginx-t-Fehler und kaputten Redirect
- WizardDomains.php: ssl_configured wird jetzt anhand /etc/letsencrypt/live/ geprüft
  statt per Shell-Output (der wegen exec>>LOG immer leer war)
- Shell-Script schreibt done-Datei selbst; PHP nur noch als Absturz-Fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 12:54:11 +02:00
boban d50aedeafb Fix: nginx http2 Syntax für nginx 1.25+ (listen 443 ssl + http2 on)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 17:16:20 +02:00
boban bc2810eb8a Fix: certbot in sudoers + SSL-Seite zeigt Zertifikate
www-data braucht sudo-Recht auf certbot für SSL-Seite (certificates/renew)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 16:29:57 +02:00
boban 894f753b81 Fix: Wizard SSL-Flow end-to-end sauber gelöst
- pollSetup() macht keinen auto-redirect mehr (port 443 wäre noch nicht offen)
- "Zum Login" ist jetzt ein plain <a href="/login"> ohne Livewire-POST
  → nginx leitet /login nach SSL-Switch automatisch auf HTTPS weiter
- mailwolt-apply-domains schreibt done=1/0 (je nach Cert-Status) VOR nginx-Switch
  + sleep 6s damit Polling noch 3x done lesen kann bevor port 443 öffnet
- done=1 nur wenn mindestens ein LE-Cert erfolgreich ausgestellt wurde

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 16:11:50 +02:00
boban 9d3cbd88b6 Fix: Race Condition SSL-Wizard + fastcgi_param HTTPS on
- mailwolt-apply-domains schreibt State-Dateien (done=1) BEVOR nginx auf HTTPS
  switcht, dann sleep 6s → Browser kann noch über HTTP redirecten
- WizardDomains.php überschreibt done nicht wenn Shell-Script es bereits gesetzt hat
- fastcgi_param HTTPS on in HTTPS-Blocks ergänzt (ohne dies liefert Laravel 404
  weil Request-Schema falsch erkannt wird)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 16:06:25 +02:00
boban 1547302297 Fix: Wizard leitet nach SSL-Setup automatisch auf HTTPS weiter
- SESSION_SECURE_COOKIE wird nicht mehr automatisch gesetzt (verursachte 419 während HTTP-Poll)
- pollSetup() leitet Browser sofort auf https://domain/setup weiter sobald SSL fertig
- verhindert dass Livewire-Polling über HTTP läuft während nginx schon auf HTTPS umgestellt hat

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:54:08 +02:00
boban 68a31e894d Fix: SESSION_DOMAIN=null entfernt aus .env.example
String "null" wird von Laravel nicht als PHP null interpretiert —
Cookie bekommt Domain=null, Browser lehnt ihn ab → 419 auf allen Livewire-Requests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:25:38 +02:00
boban 7833257126 Fix: footer_ok + Monit Nginx-Check bereinigt
- footer_ok: HTTPS/self-signed Zeile entfernt (nginx hat anfangs kein HTTPS mehr)
- Mail-TLS Cert Label ergänzt damit klar ist wofür das Zertifikat ist
- Monit: Port-443-Check für nginx entfernt (kein HTTPS initial → Monit würde nginx in Loop neustarten)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:15:34 +02:00
boban 216e46311b chore: mailwolt-installer in eigenes Repo ausgelagert
Verschoben nach https://git.nexlab.at/boban/mailwolt-installer.git

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:11:39 +02:00
boban f9f7433b98 Fix: Kein Self-signed HTTPS mehr — plain HTTP bis LE-Cert vorhanden
- Nginx initial: nur HTTP-Block (kein 443/self-signed)
- mailwolt-apply-domains: kein self-signed Fallback; ohne LE-Cert
  bleibt nginx HTTP-only, mit LE-Cert wird auf HTTPS umgestellt
- Monit: MariaDB per matching statt pidfile (mysqld.pid oft nicht da)
- ACME-Challenge Location bereits im initialen HTTP-Block vorhanden

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:02:26 +02:00
boban 73bda08244 Fix: Livewire NoModificationAllowedError im Setup-Wizard Step 5
wire:poll Div war bedingt gerendert – beim Entfernen aus dem DOM
versuchte Livewire noch es zu patchen → outerHTML Fehler.
Div bleibt jetzt immer im DOM, pollSetup() kehrt früh zurück wenn fertig.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:55:18 +02:00
boban 660402a32d Fix: storage/backups/ zu .gitignore hinzugefügt
Verhindert Abbruch des Update-Scripts durch Dirty-Check wenn
Backups im storage-Verzeichnis vorhanden sind.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:48:27 +02:00
boban 32f43020d3 Fix: HTTPS-Redirect im Wizard entfernt + nginx HTTP-Block korrigiert
HTTPS→HTTP Redirect war ein Workaround für SESSION_SECURE_COOKIE,
der jetzt durch den Installer-Fix (false initial) nicht mehr nötig ist.
fastcgi_param HTTPS on gehört nur in den 443-Block, nicht in den 80-Block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:43:26 +02:00
boban ed176ec243 Fix: Monit-Config vollständig und robust
- Alle Dienste überwacht: postfix, dovecot, mariadb, redis, rspamd,
  opendkim, opendmarc, nginx, fail2ban, clamav
- rspamd via process-matching statt pidfile (zuverlässiger)
- SSL-Checks mit for 3 cycles (kein Sofort-Restart bei Init)
- /var/run/ → /run/ Pfade korrigiert (moderne Debian-Konvention)
- monit -t vor dem Start (Konfig-Fehler werden sichtbar)
- 5 restarts within 10 cycles alert bei allen Diensten

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:33:57 +02:00
boban 4fd37985b3 Fix: Passwort-Mindestlänge im Wizard auf 6 Zeichen gesenkt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:30:32 +02:00
boban 7d30faa7d7 Fix: SESSION_SECURE_COOKIE verhindert HTTP-Setup (419-Fehler)
Installer setzt SESSION_SECURE_COOKIE=false initial – damit Setup-Wizard
über http://ip erreichbar ist. WizardDomains setzt es auf true nach
erfolgreichem SSL. mount()-Redirect ohne exit (sauberer Return).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:29:13 +02:00
boban 4f3066e225 Fix: Spinner und Text im Login-Button immer nebeneinander
Livewire setzt beim Einblenden display:inline statt inline-flex.
Innerer Wrapper erzwingt inline-flex damit SVG und Text nie stacken.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:14:16 +02:00
boban a30c21a1a9 Fix: Login-Spinner standardmäßig versteckt (display:none)
wire:loading-Span war vor Livewire-Init sichtbar, wodurch Anmelden
und Spinner gleichzeitig angezeigt wurden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:13:08 +02:00
boban 085f27d67c Redesign: Login-Seite an Wizard-Design angepasst
Eigenes HTML-Layout ohne Sidebar, mw-* CSS-Klassen, gleiches Logo
und Karten-Design wie der Setup-Wizard. Icons als Inline-SVG da
app.js (Phosphor) auf der Login-Seite nicht geladen wird.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:11:53 +02:00
boban 3869f6e67f Fix: Login-Redirect nur bei erfolgreichem SSL auf Domain umleiten
ssl_configured=1 → https://{ui_domain}/login
ssl_configured=0 → /login (bleibt auf aktueller IP/Host)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:08:01 +02:00
boban a322aa17ac Fix: goToLogin leitet auf konfigurierte UI-Domain weiter
route('login') nutzt die gecachte Config (alte IP/URL). Stattdessen
direkt auf https://{ui_domain}/login umleiten, da APP_URL erst nach
dem Prozess-Neustart greift.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:06:54 +02:00
boban 0b415c6862 Fix: Setup-Wizard bei HTTPS auf HTTP umleiten
Vor SSL-Zertifikaten schlägt Livewires AJAX über HTTPS fehl.
mount() leitet automatisch auf http:// um damit der Wizard funktioniert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:04:50 +02:00
boban 31f486c753 Fix: SSL-Erstellung nicht von APP_ENV abhängig machen
isProduction()-Check entfernt — SSL wird jetzt allein durch skipSsl gesteuert,
da APP_ENV=local sonst SSL-Zertifikate komplett verhindert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:03:24 +02:00
boban af045b21d5 Fix: Version via git ls-remote statt describe (kein --unshallow nötig)
ls-remote fragt den Remote direkt — funktioniert mit shallow clone ohne
History-Download. Kein --unshallow, kein Fehler mehr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:49:58 +02:00
boban 5b9e486b98 Fix: --unshallow vor --tags fetch damit git describe funktioniert
Shallow clones (--depth=1) kennen keine Tag-Historie. --unshallow
konvertiert zuerst zum vollständigen Clone, danach sind alle Tags erreichbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:46:50 +02:00
boban fbce5dc8ba Fix: update.sh State-Dateien, Lock, Version-Datei + Installer-Integration
update.sh:
- State-Dateien (/var/lib/mailwolt/update/state + rc) werden geschrieben
- Lock-Datei verhindert parallele Update-Prozesse
- write_version_files() aktualisiert auch /var/lib/mailwolt/version
- Kombinierter _cleanup-Trap ersetzt cleanup_maintenance
- LATEST_TAG via git rev-list statt sort -V (zuverlässiger)
- Update-Log nach /var/log/mailwolt-update.log

installer.sh:
- update.sh wird als /usr/local/sbin/mailwolt-update installiert
- Sudoers-Eintrag für mailwolt-update ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:38:27 +02:00
boban f8f30d57f7 Feature: Installer-Spinner + verbesserter Smoke-Test
- Spinner (⠋⠙⠹…) läuft während quietly() auf Abschluss wartet
- stop_spin() in ok/warn/err integriert, EXIT-Trap sichert Cleanup
- Smoke-Test: kein eval, separate Funktionen pro Protokoll (smtp/tls/imap/pop3)
- Service-Namen neben Port, Zusammenfassung X/7 Dienste erreichbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:31:30 +02:00
boban eb16f7d6ad Refactor: Installer-Output auf saubere Schritt-Anzeige umgestellt
- Nur Hauptschritte mit Zeitschätzung sichtbar (~Pakete 2-5 Min, etc.)
- Alle verbose Ausgaben (apt/composer/npm/git) gehen in /var/log/mailwolt-install.log
- Bei Fehler: letzte 20 Log-Zeilen werden angezeigt + Log-Pfad
- quietly()/try_quiet() Helper für stille Ausführung
- Smoke-Test zeigt nur OK/⚠ pro Port ohne verbose openssl-Output
- Node/npm wird nach Git-Clone installiert (package.json bereits vorhanden)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:27:31 +02:00
boban 814776d1ff Fix: Tags nach shallow clone explizit fetchen für Version-Datei
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:20:19 +02:00
boban 01e7db589a Fix: Installer + Wizard Step 5 robuster gegen IPv6/SSL-Fehler
- installer.sh: mailwolt-apply-domains mit 3-Phasen certbot (HTTP → LE → SSL),
  IPv6-Check vor certbot, Zertifikat-Ablauf-Check (10 Tage), Version-Datei schreiben
- WizardDomains: noipv6-Status aus Helper-Output erkennen
- Wizard: retryDomains()-Methode für Wiederholung ohne neuen Wizard-Durchlauf
- Step 5 Blade: Hints pro Fehlerstatus, Retry-Button, "Trotzdem zum Login"
- UpdatePage: Version aus Datei, Fallback auf git describe (kein "dev" mehr)
- UpdatePage: refreshLowLevelState behandelt fehlende State-Datei als idle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 13:16:42 +02:00
boban 3c8eaa16df Fix: Installer bricht bei nicht-kritischen Fehlern nicht mehr ab
- || true für Services (postfix, dovecot, redis, nginx)
- || true für artisan config/route/view:cache
- npm run build: Warnung statt Abbruch, Hinweis zum manuellen Nachholen
- Monit ist bereits aktiviert (systemctl enable --now)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 23:01:06 +02:00
boban e833ab72c6 Fix: WizardDomains übergibt SSL-Handling komplett an mailwolt-apply-domains
- Kein certbot --nginx mehr im Wizard (scheitert an catch-all server_name)
- mailwolt-apply-domains erstellt Vhosts zuerst, dann certbot --webroot
- sudoers-Eintrag für certbot im Installer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:48:47 +02:00
boban d5d5fd819c Fix: mailwolt-apply-domains Helper + sudoers + Monit aktiviert
- mailwolt-apply-domains Script im Installer erstellt
- sudoers-Eintrag für www-data (certbot + apply-domains ohne Passwort)
- Wizard State-Dir Owner www-data
- Monit standardmäßig aktiviert (nicht mehr disabled)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:24:28 +02:00
boban 19618746ba Fix: Installer komplett bereinigt für sauberen Erstdurchlauf
- acl-Paket ergänzt (setfacl)
- DB_NAME/DB_USER Doppel-Assignment entfernt
- VITE_REVERB_HOST nutzt jetzt tatsächliche SERVER_IP
- BROADCAST_CONNECTION=reverb gesetzt
- COMPOSER_ALLOW_SUPERUSER entfernt
- config:cache / route:cache / view:cache nach Migration
- /var/lib/mailwolt/wizard Verzeichnis angelegt
- git safe.directory gesetzt
- Footer zeigt /setup URL statt Login

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:08:42 +02:00
boban 8551a00414 Fix: Setup-Route und Wizard gegen fehlende DB absichern (try/catch)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:03:30 +02:00
boban 94cddb7987 Fix: Pusher-Key-Fehler + wire:model remember + Reverb-Keys im Installer
- connection.js: Echo nur initialisieren wenn VITE_REVERB_APP_KEY gesetzt
- LoginForm: $remember Property ergänzt
- installer.sh: Reverb-Keys automatisch generieren und in .env schreiben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:58:21 +02:00
boban 7c3376bfbc Fix: Setup-Wizard ohne Auth erreichbar, Root-Route prüft setup_completed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:56:05 +02:00
boban 75d1f136a3 Fix: Installer-Cleanup (PHP-FPM-Socket dynamisch, Arg-Parsing oben, APP_PW früh, doppelter setfacl entfernt)
- PHPV-Erkennung vor nginx-Config verschoben, Socket-Pfad dynamisch
- Argument-Parsing (-dev/-stag) ganz an den Anfang
- APP_PW früh generieren damit es überall verfügbar ist
- Doppelten setfacl-Block entfernt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:38:35 +02:00
boban b9c2eb5eef Refactor: Installer-Reihenfolge korrigiert (Git-Clone zuerst, dann .env/composer/migrate)
- composer create-project entfernt (wir klonen das eigene Repo)
- .env wird nach dem Clone auf dem echten Codebase gesetzt
- composer install, key:generate, migrate und storage:link nach Clone
- nodesource curl|bash durch Datei-Download ersetzt (stdin-safe)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:33:53 +02:00
boban a07a0d1a98 Fix: APP_DIR vor git clone leeren wenn kein .git vorhanden
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:19:48 +02:00
boban 8e8dff39c9 Fix: git zu Paketliste hinzugefügt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:16:49 +02:00
boban d271c96828 Fix: trailing > auf Zeile 512 entfernt (BOOTSTRAP_ADMIN_EMAIL redirect)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:14:32 +02:00
boban b8d121f251 Fix: unclosed quote in installer (BOOTSTRAP_EMAIL) verursachte Syntax Error
php-sqlite3 ergänzt um composer post-install migrate-Warning zu vermeiden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:08:01 +02:00
boban 45e762be7f Fix: \$uri escape in Nginx heredoc verhindert set -u Abbruch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:00:23 +02:00
boban 38d22c85ed Feature: API-Key/Webhook responsive div-grid, Sandbox-Icon in Domains, Search-fix
- API-Key-Tabelle: unified CSS-Grid div-layout (kein separates mobile/desktop HTML mehr),
  Scopes auf max. 2 Badges + +N Modal, Lösch-Bestätigung via Livewire-Modal
- Webhook-Tabelle: selbes div-grid Pattern, Status/HTTP inline auf Mobile
- Globale Suche: go()-Methode fixed (forceClose + setTimeout 350ms gegen resetState-Race)
- Domains: Sandbox-Icon ersetzt Globus durch gelbes Warndreieck wenn Sandbox aktiv
- Sandbox: SandboxRoute-Model, SandboxService, Migration, Routen-Verwaltung
- CSS: mw-kl-*/mw-whl-* Grid-Klassen, minmax(0,1fr) Fix für Text-Truncation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 19:48:06 +02:00
boban fc8dbf894a Fix: bash trap entfernt public/hot zuverlässig nach Vite-Stop
trap EXIT/INT/TERM feuert auch bei Ctrl+C — vorheriges node-Cleanup
lief nur beim Start, nicht beim Beenden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 06:22:04 +02:00
boban acab5d4c84 Fix: strictPort:true verhindert Vite auf falschem Port
Wenn Port 5173 belegt ist schlägt npm run dev sofort fehl statt
still auf 5174 zu wechseln — nginx würde dann ins Leere proxyen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 06:20:27 +02:00
boban c1d5ca1988 Refactor: app-webmail.js als eigener Vite-Entry ohne Admin-Websocket
Webmail-Layouts laden jetzt app-webmail.js statt app.js.
websocket.js, ui/command.js und sidebar.js werden im Webmail nicht
mehr geladen — kein /ui/tasks/active Aufruf mehr möglich.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 06:11:50 +02:00
boban 79548c5aa0 Fix: meta-Tag statt window-Variable für Webmail-Context-Erkennung
type=module Scripts haben kein garantiertes Timing mit inline Scripts.
<meta name="mw-context" content="webmail"> im <head> ist vor Modulausführung
garantiert im DOM verfügbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 06:01:45 +02:00