env('MTA_SUB') und env('BASE_DOMAIN') liefern null bei config:cache.
Jetzt: Setting::get('mail_domain') als primäre Quelle, config() als Fallback.
MTA_SUB in mailpool.php als config-Key ergänzt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
applyDomains + syncSysmailDomain geben Fehler zurück statt Toasts zu dispatchen.
saveDomains zeigt am Ende einen Toast: grün wenn alles ok, orange mit Details bei Problemen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DomainObserver: DKIM-install-Fehler wird geloggt statt Domain-Create zu blockieren
- saveDomains: nur noch 1 Toast, alle Zwischen-Toasts (Nginx, DNS, Sysmail) entfernt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
War auf Live-Server noch 'example.com' weshalb sysmail nie angelegt wurde.
mx.pxo.at → BASE_DOMAIN=pxo.at, MTA_SUB=mx automatisch gesetzt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Leitet BASE_DOMAIN aus config → env → mail_domain-Setting ab.
Gibt Toast-Meldung aus wenn Seeder fehlschlägt, statt still zu scheitern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Beim Speichern der Domains wird geprüft ob sysmail.<BASE_DOMAIN> bereits stimmt.
Falls nicht vorhanden: anlegen. Falls Domain geändert: alte löschen + neu erstellen.
Falls bereits korrekt: nichts tun.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Absendername und Admin-E-Mail konfigurierbar in Einstellungen
- MAIL_FROM_NAME wird automatisch in .env synchronisiert
- Sysmail-Domain wieder sysmail.<BASE_DOMAIN> (nicht MTA-FQDN)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sysmail.<MTA_FQDN> wird jetzt automatisch beim Ende einer erfolgreichen Installation
angelegt – nicht nachträglich beim Speichern der Domain-Einstellungen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Beim Speichern der Server-Domains in den Einstellungen wird automatisch die
sysmail-Domain (sysmail.<BASE_DOMAIN>) mit DKIM, SPF, DMARC und no-reply Postfach
angelegt, sofern sie noch nicht existiert. Seeder nutzt updateOrCreate für Postfach.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dev-Server zeigte v1.0.137 weil /var/lib/mailwolt/version nie aktualisiert
wurde. git describe --tags liefert immer die korrekte aktuelle Version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Monit-Cache wurde jede Minute neu befüllt mit altem Status.
Optionale Dienste werden jetzt direkt via systemctl geprüft.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dashboard zeigte ClamAV bis zu 5 Min. falsch als online/offline weil
der Monit-Cache veraltet war. Cache wird jetzt sofort invalidiert.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ensure_system() installiert clamav-daemon falls nicht vorhanden,
deaktiviert aber den Dienst. User sieht nur noch Ein/Ausschalten.
Install-Button, $installed-Property und install()-Methode entfernt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prüft /usr/sbin/clamd und systemd unit-Dateien ohne exec().
Zeigt Install-Button wenn ClamAV nicht installiert ist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
systemctl start --no-block kehrt sofort zurück, systemd startet ClamAV
im Hintergrund. runCmd('enable') direkt aufrufen statt Queue-Job.
wire:poll.keep-alive verhindert payload-Fehler in der Browser-Console.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Flag-Datei /tmp/mw-clamav-starting speichert Startzeitpunkt sodass
Spinner + Timer auch nach Seitenreload korrekt weiterläuft.
git_dirty_check filtert jetzt untracked Dateien (??) heraus damit
mailwolt-installer/ und ähnliche nicht fälschlich als dirty gelten.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
wire:poll.3s prüft serviceActive() nach Klick. Zeigt laufenden Spinner
mit Sekundenanzeige (0s, 3s, 6s…) bis ClamAV aktiv ist, dann Erfolgsmeldung.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nohup/shell_exec wird von PHP-FPM-Prozessgroup nach Request-Ende gekillt.
ClamavEnable Job läuft im Queue-Worker und blockiert nicht den Web-Request.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
exec() wartet auch mit & auf Prozessende. shell_exec mit nohup und
stdin-Redirect auf /dev/null stellt echtes Hintergrund-Detaching sicher.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
$starting-Property, pollStatus() und wire:poll entfernt.
enable() startet ClamAV im Hintergrund und zeigt nur eine
Info-Meldung an – kein dauerhafter Spinner.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- enable() startet Dienst via nohup im Hintergrund (kein Request-Timeout)
- $starting=true → wire:poll.3s ruft pollStatus() auf
- Overlay zeigt "ClamAV wird gestartet… lädt Viren-DB / bis 60s"
- pollStatus() erkennt wenn Dienst läuft → Overlay weg, Erfolg-Banner
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Loading-Overlay über Status-Karte beim Aktivieren/Deaktivieren/Installieren
- $lastSuccess Property für grünen Erfolg-Banner (kein Toast nötig)
- runCmd() helper mit Log für Debugging
- Fehler-Text white-space:pre-wrap für mehrzeilige Ausgaben
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neue Seite /security/clamav: Status, Aktivieren/Deaktivieren,
Signatur-Update, RAM-Hinweis, Info-Box
- Optionale Dienste (ClamAV) im Dashboard nur sichtbar wenn aktiv
- mailwolt-clamav sbin-Wrapper + sudoers-Regel in ensure_system
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- loadServices() liest Monit-Cache, fällt zurück auf woltguard.php Karten
mit direkten systemd/tcp-Probes wenn Cache leer ist
- Monit als Dienst in woltguard.php ergänzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Zertifikate einrichten/erneuern nur noch unter Sicherheit → SSL/TLS
- SSL-Seite: Provisioning mit Fortschritt, Ablaufdatum + Tage in Tabelle
- Einstellungen: nur noch read-only Status + Link zu SSL-Seite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- mailwolt-apply-domains: MAIL_HOST wird in ACME-Challenge-Block aufgenommen,
certbot wird auch für die Mail-Domain ausgeführt, Postfix + Dovecot erhalten
danach automatisch das neue Zertifikat
- SslCertificatesTable: certbot-Ausgabe korrekt geparst (Einrückung mit Leerzeichen)
- settings-form: "kein Zertifikat nötig" entfernt (Mail-Domain braucht Zertifikat)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem: state-Datei vom letzten Update zeigte noch 'done'. pollUpdate()
las das direkt nach runUpdate() als "Update fertig" — bevor der neue
Prozess überhaupt startete. displayCurrent war dann noch die alte Version.
Fix:
- runUpdate() setzt state='starting' und löscht rc VOR dem Shell-Aufruf
- runUpdate() setzt rc=null, lowState='starting', postActionsDone=false zurück
- refreshLowLevelState(): Kommentar klärt dass 'starting' als running gilt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- loadSslStatus(): clearstatcache() + renewal-Conf als primärer Existenzcheck
(renewal/ ist immer 755, zuverlässiger als is_dir auf live/ das 750 sein kann)
+ /usr/bin/openssl (voller Pfad für sudoers-Matching)
- restoreSslProvisioningState(): stellt letzten Provisioning-Zustand aus
State-Dateien wieder her, so dass Status nach Page-Reload sichtbar bleibt
- Button zeigt nach Abschluss "Erneut einrichten" statt disabled zu bleiben
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem: /etc/letsencrypt/archive/ ist chmod 700 (root only).
file_exists() auf Symlinks in live/ schlägt fehl weil Symlink-Ziel
in archive/ nicht lesbar ist. is_dir() auf live/domain/ funktioniert
da das Verzeichnis selbst 755 ist.
- SettingsForm: file_exists() → is_dir() für Existenzcheck
- SettingsForm: openssl-Aufruf via sudo -n (archive/ ist root-only)
- installer.sh + update.sh: sudoers-Regel für openssl auf LE-Cert-Pfade
(www-data darf nur exakt diesen openssl-Aufruf, keine anderen Pfade)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neuer Abschnitt "SSL-Zertifikate" in den Einstellungen:
· Zeigt pro Domain (UI, Webmail, Mailserver) ob LE-Cert vorhanden ist,
Ablaufdatum und Status (OK / fehlt / läuft ab / abgelaufen)
· Button "Let's Encrypt Zertifikate einrichten" startet Provisioning
im Hintergrund (nohup, non-blocking)
· Live-Fortschrittsanzeige per wire:poll.2s mit Status-Icons pro Domain
(pending → running → done/error/skip)
- saveDomains() ruft apply-domains jetzt ohne certbot auf (--ssl-auto 0) —
Domains speichern und SSL einrichten sind damit getrennte Aktionen
- loadSslStatus() liest Certbot-Zertifikat-Info direkt aus openssl
- spin-Keyframe für Spinner-Animation in app.css
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neu: scripts/mailwolt-fetch-tags ruft git ls-remote als App-User auf (hat Credentials),
schreibt neuesten Tag nach /var/lib/mailwolt/version_remote
- CheckUpdates.php nutzt jetzt sudo mailwolt-fetch-tags statt direktem git fetch als www-data
(www-data hat keine Git-Credentials für private Repos)
- SettingsForm.php zeigt tatsächliche Fehlerzeilen ([!], error, failed) im Toast statt
generischer "fehlgeschlagen"-Meldung
- installer.sh + update.sh installieren mailwolt-fetch-tags nach /usr/local/sbin/
- update.sh trägt mailwolt-fetch-tags automatisch in sudoers nach (Upgrade-Pfad)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
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>
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>
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>