feat(ntp): Live peer status tab (chronyc sources)

Adds GET /ntp/sources endpoint (runs chronyc sources, parses tabular
output) and a new "Peer status" tab in the NTP page showing all
configured peers with mode, state badge, stratum, poll interval,
reach register, last-rx and offset/error sample.

v1.1.101

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-25 11:57:04 +02:00
parent 57b9cd89b2
commit 4629679ba9
8 changed files with 194 additions and 8 deletions

View File

@@ -808,7 +808,24 @@
"ntp": {
"title": "Zeitserver (Chrony)",
"intro": "Chrony als Time-Sync-Daemon (NTP). Quellen oben, Listen-/Serve-Konfig im Settings-Tab. Wenn 'serve_clients' aktiv und LAN-IPs gebound sind, wird die Box selbst zum NTP-Server für das LAN.",
"tabs": { "pools": "Quellen", "settings": "Settings" },
"tabs": { "pools": "Quellen", "settings": "Settings", "peers": "Peer-Status" },
"sourcesCard": {
"title": "Live Peer-Status (chronyc sources)",
"name": "Name / IP",
"stratum": "Stratum",
"poll": "Poll",
"reach": "Erreichbarkeit",
"lastRx": "Letzter Empfang",
"sample": "Offset ± Fehler",
"reachHint": "8-Bit-Schieberegister (oktal) — 377 = alle 8 letzten Abfragen beantwortet. 0 = nicht erreichbar.",
"empty": "Keine Peer-Daten — läuft chrony?",
"state_synced": "Synchronisiert",
"state_combined": "Kombiniert",
"state_not_combined": "Nicht kombiniert",
"state_unreachable": "Nicht erreichbar",
"state_error": "Fehler",
"state_variable": "Variabel"
},
"statusCard": {
"title": "Sync-Status (chronyc tracking)",
"sync": "Synchronisiert",

View File

@@ -808,7 +808,24 @@
"ntp": {
"title": "Time server (Chrony)",
"intro": "Chrony as time-sync daemon (NTP). Sources on top, listen/serve config on the settings tab. With 'serve_clients' on and LAN-IPs bound, the box itself becomes an NTP server for the LAN.",
"tabs": { "pools": "Sources", "settings": "Settings" },
"tabs": { "pools": "Sources", "settings": "Settings", "peers": "Peer status" },
"sourcesCard": {
"title": "Live peer status (chronyc sources)",
"name": "Name / IP",
"stratum": "Stratum",
"poll": "Poll",
"reach": "Reach",
"lastRx": "Last rx",
"sample": "Offset ± error",
"reachHint": "8-bit shift register (octal) — 377 = all 8 recent polls replied. 0 = unreachable.",
"empty": "No peer data — is chrony running?",
"state_synced": "Synced",
"state_combined": "Combined",
"state_not_combined": "Not combined",
"state_unreachable": "Unreachable",
"state_error": "Error",
"state_variable": "Variable"
},
"statusCard": {
"title": "Sync status (chronyc tracking)",
"sync": "Synchronized",