groups: - name: homelab-availability rules: - alert: ExporterDown expr: up{job=~"node|smartctl|pve"} == 0 for: 10m labels: severity: warning annotations: summary: "Exporter unavailable: {{ '{{' }} $labels.job {{ '}}' }} {{ '{{' }} $labels.instance {{ '}}' }}" - alert: CriticalServiceUnavailable expr: probe_success{job="blackbox-vps"} == 0 for: 5m labels: severity: critical annotations: summary: "External or VPN check failed: {{ '{{' }} $labels.probe_name {{ '}}' }}" - alert: RuVpsMonitoringStale expr: time() - homelab_vps_probe_timestamp_seconds > 5 * 60 for: 5m labels: severity: critical annotations: summary: "ru-vps has not pushed monitoring metrics through OpenVPN" - alert: RuVpsMonitoringMissing expr: absent(homelab_vps_probe_timestamp_seconds{job="blackbox-vps"}) for: 10m labels: severity: critical annotations: summary: "ru-vps has no monitoring metrics in Pushgateway" - alert: LanServiceUnavailable expr: probe_success{job=~"blackbox-lan-http|blackbox-lan-tcp"} == 0 for: 10m labels: severity: warning annotations: summary: "LAN service unavailable: {{ '{{' }} $labels.instance {{ '}}' }}" - alert: TLSCertificateExpiringSoon expr: (probe_ssl_earliest_cert_expiry - time()) < 14 * 24 * 3600 for: 1h labels: severity: warning annotations: summary: "TLS certificate expires within 14 days: {{ '{{' }} $labels.instance {{ '}}' }}" - name: homelab-capacity rules: - alert: FilesystemAlmostFull expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) < 0.15 for: 15m labels: severity: warning annotations: summary: "Filesystem is more than 85% full: {{ '{{' }} $labels.instance {{ '}}' }} {{ '{{' }} $labels.mountpoint {{ '}}' }}" - alert: FilesystemWillFillSoon expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 7 * 24 * 3600) < 0 for: 30m labels: severity: warning annotations: summary: "Filesystem may fill within seven days: {{ '{{' }} $labels.instance {{ '}}' }} {{ '{{' }} $labels.mountpoint {{ '}}' }}" - alert: HostMemoryPressure expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.1 for: 20m labels: severity: warning annotations: summary: "Memory pressure on {{ '{{' }} $labels.instance {{ '}}' }}" - alert: SMARTDeviceFailed expr: homelab_smart_device_healthy == 0 for: 5m labels: severity: critical annotations: summary: "SMART health check failed: {{ '{{' }} $labels.instance {{ '}}' }} {{ '{{' }} $labels.device {{ '}}' }}" - alert: NVMECriticalWarning expr: homelab_smart_nvme_critical_warning > 0 for: 5m labels: severity: critical annotations: summary: "NVMe critical warning: {{ '{{' }} $labels.instance {{ '}}' }} {{ '{{' }} $labels.device {{ '}}' }}" - name: homelab-backups rules: - alert: BackupAuditFailed expr: homelab_backup_audit_success == 0 for: 5m labels: severity: critical annotations: summary: "Backup audit failed: {{ '{{' }} $labels.profile {{ '}}' }} on {{ '{{' }} $labels.instance {{ '}}' }}" - alert: BackupAuditStale expr: time() - homelab_backup_audit_timestamp_seconds > 48 * 3600 for: 15m labels: severity: critical annotations: summary: "Backup audit result is stale: {{ '{{' }} $labels.profile {{ '}}' }} on {{ '{{' }} $labels.instance {{ '}}' }}" - alert: BackupAuditMissing expr: absent(homelab_backup_audit_timestamp_seconds{profile="pbs"}) or absent(homelab_backup_audit_timestamp_seconds{profile="gitea"}) or absent(homelab_backup_audit_timestamp_seconds{profile="vaultwarden"}) or absent(homelab_backup_audit_timestamp_seconds{profile="grimmory"}) for: 12h labels: severity: critical annotations: summary: "Expected backup audit metric has not been published" - alert: ResticBackupTooOld expr: homelab_backup_audit_snapshot_age_hours{profile=~"gitea|vaultwarden|grimmory"} > 36 for: 15m labels: severity: critical annotations: summary: "Restic backup is older than 36 hours: {{ '{{' }} $labels.profile {{ '}}' }}" - alert: PBSBackupTooOld expr: homelab_backup_audit_snapshot_age_hours{profile="pbs"} > 48 for: 15m labels: severity: critical annotations: summary: "PBS backup is older than 48 hours: VMID {{ '{{' }} $labels.vmid {{ '}}' }}"