warn('.env nicht gefunden.'); return self::SUCCESS; } $content = file_get_contents($env); // APP_HOST ermitteln: .env → APP_URL → DB-Setting ui_domain $appHost = $this->extractVar($content, 'APP_HOST'); if (!$appHost || preg_match('/^\d+\.\d+\.\d+\.\d+$/', $appHost)) { $appUrl = $this->extractVar($content, 'APP_URL'); $appHost = parse_url($appUrl ?: '', PHP_URL_HOST) ?: ''; } if (!$appHost || preg_match('/^\d+\.\d+\.\d+\.\d+$/', $appHost)) { try { $appHost = (string) \App\Models\Setting::get('ui_domain', ''); } catch (\Throwable) { $appHost = ''; } } if (!$appHost || preg_match('/^\d+\.\d+\.\d+\.\d+$/', $appHost)) { $this->warn('Kein gültiger Hostname gefunden – Migration übersprungen.'); return self::SUCCESS; } $scheme = $this->detectScheme($appHost, $content); $correctPort = $scheme === 'https' ? '443' : '80'; $viteHost = $this->extractVar($content, 'VITE_REVERB_HOST'); $currentPort = $this->extractVar($content, 'REVERB_PORT'); $hostOk = ($viteHost === '${REVERB_HOST}' || $viteHost === $appHost); $portOk = ($currentPort === $correctPort); if ($hostOk && $portOk) { $this->info('REVERB-Werte bereits korrekt.'); return self::SUCCESS; } $port = $correctPort; $fixes = [ 'REVERB_HOST' => '${APP_HOST}', 'REVERB_PORT' => $port, 'REVERB_SCHEME' => $scheme, 'REVERB_PATH' => '/ws', 'REVERB_SERVER_HOST' => '127.0.0.1', 'REVERB_SERVER_PORT' => '8080', 'REVERB_SERVER_SCHEME' => 'http', 'REVERB_SERVER_PATH' => '', 'VITE_REVERB_HOST' => '${REVERB_HOST}', 'VITE_REVERB_PORT' => '${REVERB_PORT}', 'VITE_REVERB_SCHEME' => '${REVERB_SCHEME}', 'VITE_REVERB_PATH' => '${REVERB_PATH}', ]; foreach ($fixes as $key => $val) { if (preg_match("/^{$key}=/m", $content)) { $content = preg_replace("/^{$key}=.*/m", "{$key}={$val}", $content); } else { $content .= "\n{$key}={$val}"; } } // APP_HOST setzen falls fehlend if (!$this->extractVar($content, 'APP_HOST')) { $content .= "\nAPP_HOST={$appHost}"; } file_put_contents($env, $content); $this->info("REVERB .env migriert für Host: {$appHost}"); // Assets neu bauen damit wsHost korrekt eingebacken wird $buildLog = base_path('../mailwolt-frontend-build.log'); exec('cd ' . escapeshellarg(base_path()) . ' && npm run build --silent 2>/dev/null', $out, $rc); if ($rc !== 0) { $this->warn('npm run build fehlgeschlagen – bitte manuell ausführen.'); } else { $this->info('Assets neu gebaut.'); } return self::SUCCESS; } private function detectScheme(string $host, string $envContent): string { // 1. APP_URL in .env bereits https? $appUrl = $this->extractVar($envContent, 'APP_URL'); if (str_starts_with($appUrl, 'https://')) return 'https'; // 2. nginx-Konfiguration prüfen (world-readable) foreach (glob('/etc/nginx/sites-enabled/*') ?: [] as $f) { $c = @file_get_contents($f) ?: ''; if (str_contains($c, $host) && str_contains($c, 'ssl_certificate')) return 'https'; } // 3. letsencrypt-Pfade (falls doch lesbar) if (file_exists("/etc/letsencrypt/renewal/{$host}.conf") || is_dir("/etc/letsencrypt/live/{$host}") || file_exists("/etc/letsencrypt/live/{$host}/fullchain.pem")) { return 'https'; } return 'http'; } private function extractVar(string $content, string $key): string { preg_match("/^{$key}=(.*)$/m", $content, $m); return trim($m[1] ?? '', " \t\"'"); } }