117 lines
4.0 KiB
PHP
117 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Setting;
|
|
use Illuminate\Console\Command;
|
|
|
|
class WizardDomains extends Command
|
|
{
|
|
protected $signature = 'mailwolt:wizard-domains
|
|
{--ui= : UI-Domain}
|
|
{--mail= : Mail-Domain}
|
|
{--webmail= : Webmail-Domain}
|
|
{--ssl=1 : SSL automatisch (1/0)}';
|
|
|
|
protected $description = 'Wizard: Domains einrichten mit Status-Dateien';
|
|
|
|
private const STATE_DIR = '/var/lib/mailwolt/wizard';
|
|
|
|
public function handle(): int
|
|
{
|
|
$ui = $this->option('ui');
|
|
$mail = $this->option('mail');
|
|
$webmail = $this->option('webmail');
|
|
$ssl = (bool)(int)$this->option('ssl');
|
|
|
|
@mkdir(self::STATE_DIR, 0755, true);
|
|
|
|
foreach (['ui', 'mail', 'webmail'] as $key) {
|
|
file_put_contents(self::STATE_DIR . "/{$key}", 'pending');
|
|
}
|
|
|
|
$domains = ['ui' => $ui, 'mail' => $mail, 'webmail' => $webmail];
|
|
$allOk = true;
|
|
|
|
// DNS prüfen
|
|
foreach ($domains as $key => $domain) {
|
|
if (!$domain) {
|
|
file_put_contents(self::STATE_DIR . "/{$key}", 'skip');
|
|
continue;
|
|
}
|
|
|
|
file_put_contents(self::STATE_DIR . "/{$key}", 'running');
|
|
|
|
$hasDns = checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA');
|
|
if (!$hasDns) {
|
|
file_put_contents(self::STATE_DIR . "/{$key}", 'nodns');
|
|
$allOk = false;
|
|
}
|
|
}
|
|
|
|
if (!$allOk) {
|
|
file_put_contents(self::STATE_DIR . '/done', '0');
|
|
Setting::set('ssl_configured', '0');
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
// Nginx-Vhosts + optionales SSL via mailwolt-apply-domains
|
|
// Das Script erstellt erst die Vhosts (mit ACME-Location), dann certbot --webroot
|
|
$helper = '/usr/local/sbin/mailwolt-apply-domains';
|
|
$out = shell_exec(sprintf(
|
|
'sudo -n %s --ui-host %s --webmail-host %s --mail-host %s --ssl-auto %d',
|
|
escapeshellarg($helper),
|
|
escapeshellarg($ui),
|
|
escapeshellarg($webmail),
|
|
escapeshellarg($mail),
|
|
$ssl ? 1 : 0,
|
|
));
|
|
|
|
// Shell-Script schreibt per-Domain-Status selbst in die State-Dateien.
|
|
// Fallback: Domains die noch auf running/pending stehen auf error setzen.
|
|
foreach (['ui', 'mail', 'webmail'] as $key) {
|
|
$status = trim((string) @file_get_contents(self::STATE_DIR . "/{$key}"));
|
|
if ($status === 'running' || $status === 'pending') {
|
|
file_put_contents(self::STATE_DIR . "/{$key}", 'error');
|
|
}
|
|
}
|
|
|
|
// done-Datei: Shell-Script schreibt "1"/"0"; Fallback wenn Script abstürzte.
|
|
$doneVal = trim((string) @file_get_contents(self::STATE_DIR . '/done'));
|
|
if ($doneVal === '') {
|
|
file_put_contents(self::STATE_DIR . '/done', '0');
|
|
$doneVal = '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 —
|
|
// nginx leitet HTTP→HTTPS weiter, Secure-Flag wird im Admin gesetzt
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function updateEnv(string $path, string $key, string $value): void
|
|
{
|
|
$content = @file_get_contents($path) ?: '';
|
|
$pattern = '/^' . preg_quote($key, '/') . '=[^\r\n]*/m';
|
|
$line = $key . '=' . $value;
|
|
|
|
if (preg_match($pattern, $content)) {
|
|
$content = preg_replace($pattern, $line, $content);
|
|
} else {
|
|
$content .= "\n{$line}";
|
|
}
|
|
|
|
file_put_contents($path, $content);
|
|
}
|
|
}
|