Fix: Dashboard zeigt Dienste auch ohne Monit (Fallback auf systemd/tcp-Probes)

- 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>
main v1.1.307
boban 2026-04-26 19:02:51 +02:00
parent a51f271069
commit 3c6325db32
2 changed files with 55 additions and 7 deletions

View File

@ -10,6 +10,7 @@ use App\Models\SandboxRoute;
use App\Models\Setting as SettingModel;
use App\Support\CacheVer;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
@ -20,13 +21,7 @@ class Dashboard extends Component
{
public function render()
{
$cached = Cache::get(CacheVer::k('health:services'), []);
$rows = $cached['rows'] ?? [];
$services = array_map(fn($r) => [
'name' => $r['label'] ?? ucfirst($r['name']),
'type' => $r['hint'] ?? '',
'status' => ($r['ok'] ?? false) ? 'online' : 'offline',
], $rows);
$services = $this->loadServices();
[$cpu, $cpuCores, $cpuMhz] = $this->cpu();
[$ramPercent, $ramUsed, $ramTotal] = $this->ram();
@ -78,6 +73,55 @@ class Dashboard extends Component
}
private function loadServices(): array
{
// 1) Monit-Cache (populated by RunHealthChecks job)
$cached = Cache::get(CacheVer::k('health:services'), []);
$rows = $cached['rows'] ?? [];
// 2) Fallback: use woltguard.php cards with active systemd/tcp probes
if (empty($rows)) {
$cards = config('woltguard.cards', []);
foreach ($cards as $key => $card) {
$isOk = false;
foreach ($card['sources'] as $src) {
if ($this->probeSource($src)) { $isOk = true; break; }
}
$rows[] = ['label' => $card['label'], 'hint' => $card['hint'], 'ok' => $isOk];
}
}
return array_map(fn($r) => [
'name' => $r['label'] ?? ucfirst($r['name'] ?? ''),
'type' => $r['hint'] ?? '',
'status' => ($r['ok'] ?? false) ? 'online' : 'offline',
], $rows);
}
private function probeSource(string $src): bool
{
if (str_starts_with($src, 'systemd:')) {
$unit = substr($src, 8);
$exit = null;
@exec("systemctl is-active --quiet " . escapeshellarg($unit) . " 2>/dev/null", $_, $exit);
return $exit === 0;
}
if (str_starts_with($src, 'tcp:')) {
[, $host, $port] = explode(':', $src, 3);
$fp = @fsockopen($host, (int)$port, $e1, $e2, 1);
if (is_resource($fp)) { fclose($fp); return true; }
return false;
}
if (str_starts_with($src, 'socket:')) {
return @file_exists(substr($src, 7));
}
if ($src === 'db') {
try { \Illuminate\Support\Facades\DB::connection()->getPdo(); return true; }
catch (\Throwable) { return false; }
}
return false;
}
private function ports(): array
{
$check = [25, 465, 587, 110, 143, 993, 995, 80, 443];

View File

@ -64,6 +64,10 @@ return [
],
// Sonstiges
'monit' => [
'label' => 'Monit', 'hint' => 'Prozess-Monitoring',
'sources' => ['systemd:monit', 'tcp:127.0.0.1:2812'],
],
'fail2ban' => [
'label' => 'Fail2Ban', 'hint' => 'SSH / Mail Protection',
'sources' => ['systemd:fail2ban'],