Add custom homelab dashboard stack

This commit is contained in:
2026-04-05 13:43:03 +02:00
parent 450a04a7d3
commit 89b9173c25
38 changed files with 3539 additions and 0 deletions
@@ -0,0 +1 @@
"""Pydantic models for API and domain data."""
@@ -0,0 +1,23 @@
from __future__ import annotations
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, ConfigDict
SourceStatus = Literal["online", "offline", "unsupported"]
OverallStatus = Literal["online", "degraded", "offline"]
HealthStatus = Literal["healthy", "warning", "offline"]
DiskStatus = Literal["online", "warning", "critical", "offline"]
ServiceKind = Literal["core", "service"]
ServiceSource = Literal["home_assistant", "uptime_kuma", "docker", "manual"]
DockerContainerState = Literal["running", "stopped", "unhealthy", "unknown"]
class APIModel(BaseModel):
model_config = ConfigDict(extra="ignore", populate_by_name=True)
class TimestampedResponse(APIModel):
generated_at: datetime
@@ -0,0 +1,44 @@
from __future__ import annotations
from app.models.common import APIModel, OverallStatus, SourceStatus, TimestampedResponse
class OverviewServicesSummary(APIModel):
online: int
degraded: int
offline: int
total: int
class OverviewDockerSummary(APIModel):
running: int
stopped: int
unhealthy: int
total: int
source_status: SourceStatus
class OverviewSystemSummary(APIModel):
cpu_percent: float
ram_percent: float
root_storage_percent: float
network_rx_mbps: float
network_tx_mbps: float
uptime_seconds: int
class OverviewHomeAssistantSummary(APIModel):
status: SourceStatus
label: str
version: str | None = None
response_time_ms: int | None = None
last_checked: str | None = None
class OverviewResponse(TimestampedResponse):
overall_status: OverallStatus
refresh_hint_seconds: int
services: OverviewServicesSummary
docker: OverviewDockerSummary
system: OverviewSystemSummary
home_assistant: OverviewHomeAssistantSummary
@@ -0,0 +1,52 @@
from __future__ import annotations
from app.models.common import (
APIModel,
DockerContainerState,
HealthStatus,
OverallStatus,
ServiceKind,
ServiceSource,
SourceStatus,
TimestampedResponse,
)
class ServicesDockerSummary(APIModel):
running: int
stopped: int
unhealthy: int
total: int
source_status: SourceStatus
class ServicesUptimeKumaSummary(APIModel):
monitors_up: int
monitors_down: int
monitors_paused: int
total: int
source_status: SourceStatus
class ServicesSummary(APIModel):
overall_status: OverallStatus
docker: ServicesDockerSummary
uptime_kuma: ServicesUptimeKumaSummary
class ServiceItem(APIModel):
id: str
name: str
kind: ServiceKind
status: OverallStatus
health: HealthStatus
latency_ms: int | None = None
docker_state: DockerContainerState
url: str | None = None
source: ServiceSource
last_checked: str | None = None
class ServicesResponse(TimestampedResponse):
summary: ServicesSummary
services: list[ServiceItem]
@@ -0,0 +1,85 @@
from __future__ import annotations
from datetime import datetime
from pydantic import Field
from app.models.common import APIModel, DockerContainerState, OverallStatus, SourceStatus
class BeszelDiskMetric(APIModel):
name: str
mount: str
used_gb: float
total_gb: float
free_gb: float
usage_percent: float
class BeszelSystemSnapshot(APIModel):
source_name: str = "beszel"
source_status: SourceStatus = "offline"
host_name: str = "unknown"
agent_name: str = "beszel-agent"
cpu_usage_percent: float = 0.0
cpu_cores: int = 0
load_1: float = 0.0
load_5: float = 0.0
load_15: float = 0.0
memory_used_gb: float = 0.0
memory_total_gb: float = 0.0
memory_available_gb: float = 0.0
memory_usage_percent: float = 0.0
primary_interface: str = "unknown"
network_rx_mbps: float = 0.0
network_tx_mbps: float = 0.0
uptime_seconds: int = 0
platform: str = "unknown"
kernel: str = "unknown"
disks: list[BeszelDiskMetric] = Field(default_factory=list)
class DockerContainerSummary(APIModel):
id: str
name: str
state: DockerContainerState
status_text: str
image: str
health: str | None = None
class DockerSnapshot(APIModel):
source_name: str = "docker"
source_status: SourceStatus = "offline"
running: int = 0
stopped: int = 0
unhealthy: int = 0
total: int = 0
containers: list[DockerContainerSummary] = Field(default_factory=list)
class UptimeKumaMonitor(APIModel):
id: str
name: str
status: OverallStatus
latency_ms: int | None = None
monitor_type: str | None = None
class UptimeKumaSnapshot(APIModel):
source_name: str = "uptime_kuma"
source_status: SourceStatus = "offline"
monitors_up: int = 0
monitors_down: int = 0
monitors_paused: int = 0
total: int = 0
monitors: list[UptimeKumaMonitor] = Field(default_factory=list)
class HomeAssistantSnapshot(APIModel):
source_name: str = "home_assistant"
status: SourceStatus = "offline"
label: str = "Home Assistant"
version: str | None = None
response_time_ms: int | None = None
last_checked: datetime | None = None
@@ -0,0 +1,27 @@
from __future__ import annotations
from app.models.common import APIModel, DiskStatus, OverallStatus, SourceStatus, TimestampedResponse
class StorageSummary(APIModel):
overall_status: OverallStatus
source_status: SourceStatus
critical_disks: int
warning_disks: int
total_disks: int
class StorageDisk(APIModel):
name: str
mount: str
used_gb: float
total_gb: float
free_gb: float
usage_percent: float
status: DiskStatus
class StorageResponse(TimestampedResponse):
summary: StorageSummary
root: StorageDisk
disks: list[StorageDisk]
@@ -0,0 +1,45 @@
from __future__ import annotations
from app.models.common import APIModel, SourceStatus, TimestampedResponse
class SystemSource(APIModel):
name: str
status: SourceStatus
host_name: str
agent_name: str
class SystemCPU(APIModel):
usage_percent: float
cores: int
load_1: float
load_5: float
load_15: float
class SystemMemory(APIModel):
used_gb: float
total_gb: float
available_gb: float
usage_percent: float
class SystemNetwork(APIModel):
primary_interface: str
rx_mbps: float
tx_mbps: float
class SystemHost(APIModel):
uptime_seconds: int
platform: str
kernel: str
class SystemResponse(TimestampedResponse):
source: SystemSource
cpu: SystemCPU
memory: SystemMemory
network: SystemNetwork
host: SystemHost