feat(system): health-Endpoint liefert jetzt hostname + OS + kernel

- /system/health gibt zusätzlich hostname, os (PRETTY_NAME aus
  /etc/os-release) und kernel (/proc/version, ohne Build-Details) zurück
- Settings-Seite: SystemHealth-Interface erweitert, System-Info-Card
  zeigt Hostname, Betriebssystem und Kernel-Version an (conditional,
  nur wenn vorhanden)
- Nützlich beim Verwalten mehrerer Boxen — ohne SSH sofort sehen
  welches System gerade geöffnet ist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-25 06:43:56 +02:00
parent cfb0e9ed01
commit c99b0cef4c
8 changed files with 39 additions and 6 deletions

View File

@@ -1 +1 @@
1.1.97
1.1.98

View File

@@ -60,7 +60,7 @@ import (
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
)
var version = "1.1.97"
var version = "1.1.98"
func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR")

View File

@@ -11,7 +11,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
)
var version = "1.1.97"
var version = "1.1.98"
const usage = `edgeguard-ctl — EdgeGuard CLI

View File

@@ -35,7 +35,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
)
var version = "1.1.97"
var version = "1.1.98"
const (
// renewTickInterval — how often we re-evaluate expiring certs.

View File

@@ -752,10 +752,31 @@ func (h *SystemHandler) ConfigPreview(c *gin.Context) {
}
func (h *SystemHandler) Health(c *gin.Context) {
response.OK(c, gin.H{
resp := gin.H{
"status": "ok",
"version": h.Version,
})
}
if hn, err := os.Hostname(); err == nil {
resp["hostname"] = hn
}
if data, err := os.ReadFile("/proc/version"); err == nil {
// /proc/version: "Linux version 6.x.y (...)" — Kurzform: alles
// bis zum ersten '(' kürzen.
line := strings.TrimSpace(string(data))
if idx := strings.Index(line, " ("); idx > 0 {
line = strings.TrimSpace(line[:idx])
}
resp["kernel"] = line
}
if data, err := os.ReadFile("/etc/os-release"); err == nil {
for _, line := range strings.Split(string(data), "\n") {
if k, v, ok := strings.Cut(line, "="); ok && k == "PRETTY_NAME" {
resp["os"] = strings.Trim(v, `"`)
break
}
}
}
response.OK(c, resp)
}
// PackageVersions reports installed and available versions for the

View File

@@ -517,6 +517,9 @@
"systemInfo": "System",
"version": "Version",
"status": "Status",
"hostname": "Hostname",
"os": "Betriebssystem",
"kernel": "Kernel",
"dbSize": "PostgreSQL-DB-Größe",
"dbSizeTop": "Top-Tabellen",
"upgradeStatusCardTitle": "Letzter Update-Versuch",

View File

@@ -517,6 +517,9 @@
"systemInfo": "System",
"version": "Version",
"status": "Status",
"hostname": "Hostname",
"os": "OS",
"kernel": "Kernel",
"dbSize": "PostgreSQL DB size",
"dbSizeTop": "Top tables",
"upgradeStatusCardTitle": "Last upgrade attempt",

View File

@@ -23,6 +23,9 @@ interface ContactEmailValues {
interface SystemHealth {
status: string
version: string
hostname?: string
kernel?: string
os?: string
}
interface ChangePasswordValues {
@@ -329,6 +332,9 @@ export default function SettingsPage() {
<Descriptions column={1}>
<Descriptions.Item label={t('settings.version')}>{health?.version ?? '—'}</Descriptions.Item>
<Descriptions.Item label={t('settings.status')}>{health?.status ?? '—'}</Descriptions.Item>
{health?.hostname && <Descriptions.Item label={t('settings.hostname')}><code>{health.hostname}</code></Descriptions.Item>}
{health?.os && <Descriptions.Item label={t('settings.os')}>{health.os}</Descriptions.Item>}
{health?.kernel && <Descriptions.Item label={t('settings.kernel')}><code style={{ fontSize: 11 }}>{health.kernel}</code></Descriptions.Item>}
{dbSize && (
<Descriptions.Item label={t('settings.dbSize')}>
<Space direction="vertical" size={2}>