fix: daemon /run spawn hardening, auth guard before first paint, WS refresh cap, interfaces runtime state

systemd: pre-create volatile /run paths so vacuum-walld's ProtectSystem=strict namespace setup cannot fail with 226/NAMESPACE — RuntimeDirectory=vacuum-wall nginx plus a tmpfiles.d spec (installed to /etc/tmpfiles.d/) covering /run/firewalld and /run/nginx.pid. Drop /run/sudo from ReadWritePaths: NOPASSWD children never need it, and its absence crash-looped restarts after sudo removed /run/sudo.

webui: run the auth session check before mounting the shell so logged-out visitors never flash the sidebar or a protected page; router guard and sidebar now react to auth state, and the login page renders full-bleed.

ws: cap refresh->reconnect episodes at 2 consecutive failures; if the WS path stays dead after a token refresh, abandon reconnection instead of looping refreshAuth forever (UI keeps working via REST until reload).

api: GET /api/network/interfaces now includes loopback and returns per-interface {config, runtime}; dashboard reads runtime.state (carrier counts as up) and the interfaces page filters lo client-side.

daemon: re-collect nginx state after lazy config migration (cached list went stale when the on-disk format changed under it), skip system_import.nginx when config.json already exists (re-parsing vacuum-wall's own generated sites is lossy), and poll nginx (60s) / acme (300s) state so file drift self-heals.
This commit is contained in:
2026-08-19 15:32:36 +00:00
parent 4bd4c374fd
commit 9c9f92ad04
16 changed files with 244 additions and 32 deletions
+5 -2
View File
@@ -53,10 +53,13 @@ export default definePage({
const ifaces = allNames.map(name => {
const fw = fwIfaces.find(f => f.name === name);
const netEntry = netIfaces[name] || {};
// /api/network/interfaces returns {config, runtime} per interface —
// state fields (state, addresses, mac) live under runtime.
const runtime = netEntry.runtime || {};
const traffic = sysTraffic[name] || {};
const ips = fw ? [...(fw.ips || []), ...(fw.ipv6 || [])] : [];
const addrs = netEntry?.addresses || [];
const isUp = ['routable', 'degraded'].some(s => (netEntry.state || '').startsWith(s));
const addrs = runtime.addresses || [];
const isUp = ['routable', 'degraded', 'carrier'].some(s => (runtime.state || '').startsWith(s));
return {
name,
mac: fw?.mac || null,