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>
main v1.1.260
boban 2026-04-25 12:54:11 +02:00
parent d50aedeafb
commit 8ff1aeac2a
1 changed files with 20 additions and 20 deletions

View File

@ -59,7 +59,7 @@ class WizardDomains extends Command
// Das Script erstellt erst die Vhosts (mit ACME-Location), dann certbot --webroot // Das Script erstellt erst die Vhosts (mit ACME-Location), dann certbot --webroot
$helper = '/usr/local/sbin/mailwolt-apply-domains'; $helper = '/usr/local/sbin/mailwolt-apply-domains';
$out = shell_exec(sprintf( $out = shell_exec(sprintf(
'sudo -n %s --ui-host %s --webmail-host %s --mail-host %s --ssl-auto %d 2>&1', 'sudo -n %s --ui-host %s --webmail-host %s --mail-host %s --ssl-auto %d',
escapeshellarg($helper), escapeshellarg($helper),
escapeshellarg($ui), escapeshellarg($ui),
escapeshellarg($webmail), escapeshellarg($webmail),
@ -67,31 +67,31 @@ class WizardDomains extends Command
$ssl ? 1 : 0, $ssl ? 1 : 0,
)); ));
$outStr = (string) $out; // Shell-Script schreibt per-Domain-Status selbst in die State-Dateien.
$helperOk = $out !== null // Fallback: Domains die noch auf running/pending stehen auf error setzen.
&& !str_contains($outStr, '[x]')
&& !str_contains($outStr, 'command not found')
&& !str_contains($outStr, 'No such file')
&& trim($outStr) !== '';
foreach (['ui', 'mail', 'webmail'] as $key) { foreach (['ui', 'mail', 'webmail'] as $key) {
$status = file_get_contents(self::STATE_DIR . "/{$key}"); $status = trim((string) @file_get_contents(self::STATE_DIR . "/{$key}"));
if ($status === 'running' || $status === 'pending') { if ($status === 'running' || $status === 'pending') {
$domain = $domains[$key] ?? ''; file_put_contents(self::STATE_DIR . "/{$key}", 'error');
if ($domain && str_contains($outStr, "[!] {$domain}:")) {
file_put_contents(self::STATE_DIR . "/{$key}", 'noipv6');
} else {
file_put_contents(self::STATE_DIR . "/{$key}", $helperOk ? 'done' : 'error');
}
} }
} }
// Shell-Script schreibt done bereits vor dem nginx-Switch — nicht überschreiben // done-Datei: Shell-Script schreibt "1"/"0"; Fallback wenn Script abstürzte.
$alreadyDone = trim((string) @file_get_contents(self::STATE_DIR . '/done')) === '1'; $doneVal = trim((string) @file_get_contents(self::STATE_DIR . '/done'));
if (!$alreadyDone) { if ($doneVal === '') {
file_put_contents(self::STATE_DIR . '/done', $helperOk ? '1' : '0'); file_put_contents(self::STATE_DIR . '/done', '0');
$doneVal = '0';
} }
Setting::set('ssl_configured', ($helperOk || $alreadyDone) ? '1' : '0');
// ssl_configured anhand tatsächlich ausgestellter LE-Zertifikate bestimmen
$hasAnyCert = false;
foreach ($domains as $domain) {
if ($domain && is_dir("/etc/letsencrypt/live/{$domain}")) {
$hasAnyCert = true;
break;
}
}
Setting::set('ssl_configured', $hasAnyCert ? '1' : '0');
// SESSION_SECURE_COOKIE wird nicht automatisch gesetzt — // SESSION_SECURE_COOKIE wird nicht automatisch gesetzt —
// nginx leitet HTTP→HTTPS weiter, Secure-Flag wird im Admin gesetzt // nginx leitet HTTP→HTTPS weiter, Secure-Flag wird im Admin gesetzt