Add certbot status to dashboard services and sidebar nav indicator

- Add certbot to getDaemonStatus: checks binary availability and version
- Dashboard: add Certificates card to services grid
- Sidebar: show green/red status dot for certbot on Certificates nav item
This commit is contained in:
2026-07-14 12:18:07 +00:00
parent 8dd9e117bc
commit 4500a1a45e
3 changed files with 17 additions and 2 deletions

View File

@@ -550,6 +550,20 @@ func getDaemonStatus() map[string]map[string]any {
} }
result["nftables"] = nftEntry result["nftables"] = nftEntry
// certbot is a CLI tool, not a daemon — check if installed
certbotEntry := map[string]any{"active": false}
if _, err := exec.LookPath("certbot"); err == nil {
certbotEntry["active"] = true
if out, verErr := exec.Command("certbot", "--version").Output(); verErr == nil {
// "certbot 2.11.0"
s := strings.TrimSpace(string(out))
if _, after, found := strings.Cut(s, " "); found {
certbotEntry["version"] = after
}
}
}
result["certbot"] = certbotEntry
return result return result
} }

View File

@@ -105,7 +105,7 @@ export function AppSidebar() {
{ to: '/advanced/crowdsec', icon: ShieldAlert, label: 'CrowdSec', daemon: 'crowdsec' as const }, { to: '/advanced/crowdsec', icon: ShieldAlert, label: 'CrowdSec', daemon: 'crowdsec' as const },
{ to: '/advanced/authelia', icon: KeyRound, label: 'Authelia', daemon: 'authelia' as const }, { to: '/advanced/authelia', icon: KeyRound, label: 'Authelia', daemon: 'authelia' as const },
{ to: '/advanced/ddns', icon: Globe, label: 'DDNS', daemon: undefined }, { to: '/advanced/ddns', icon: Globe, label: 'DDNS', daemon: undefined },
{ to: '/advanced/certificates', icon: ShieldCheck, label: 'Certificates', daemon: undefined }, { to: '/advanced/certificates', icon: ShieldCheck, label: 'Certificates', daemon: 'certbot' as const },
]; ];
return ( return (

View File

@@ -8,7 +8,7 @@ import { Badge } from './ui/badge';
import { import {
LayoutDashboard, Cloud, CheckCircle, XCircle, AlertCircle, Loader2, LayoutDashboard, Cloud, CheckCircle, XCircle, AlertCircle, Loader2,
BookOpen, Globe, Router, RotateCw, Key, KeyRound, BookOpen, Globe, Router, RotateCw, Key, KeyRound,
Shield, Eye, ArrowLeftRight, Lock, Shield, ShieldCheck, Eye, ArrowLeftRight, Lock,
} from 'lucide-react'; } from 'lucide-react';
import { useCloudflare } from '../hooks/useCloudflare'; import { useCloudflare } from '../hooks/useCloudflare';
import { useCentralStatus } from '../hooks/useCentralStatus'; import { useCentralStatus } from '../hooks/useCentralStatus';
@@ -23,6 +23,7 @@ const SERVICES = [
{ key: 'wireguard', label: 'VPN', icon: Lock }, { key: 'wireguard', label: 'VPN', icon: Lock },
{ key: 'crowdsec', label: 'CrowdSec', icon: Eye }, { key: 'crowdsec', label: 'CrowdSec', icon: Eye },
{ key: 'authelia', label: 'Auth', icon: KeyRound }, { key: 'authelia', label: 'Auth', icon: KeyRound },
{ key: 'certbot', label: 'Certificates', icon: ShieldCheck },
]; ];
function formatUptime(totalSeconds: number): string { function formatUptime(totalSeconds: number): string {