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:
@@ -37,6 +37,10 @@ _DEFAULT_POLL_INTERVALS: dict[str, int] = {
|
||||
"dnsmasq": 10,
|
||||
"networkd": 10,
|
||||
"system": 30,
|
||||
# nginx/acme state derives from config files (and lazy in-place migration
|
||||
# can rewrite them without a mutation); poll so drift self-heals.
|
||||
"nginx": 60,
|
||||
"acme": 300,
|
||||
}
|
||||
|
||||
|
||||
|
||||
+14
-2
@@ -713,7 +713,20 @@ def _parse_bool(val: str) -> bool | str:
|
||||
|
||||
|
||||
def import_nginx() -> bool:
|
||||
"""Parse data/nginx/sites-enabled/*.conf -> config/nginx/config.json."""
|
||||
"""Parse data/nginx/sites-enabled/*.conf -> config/nginx/config.json.
|
||||
|
||||
Bootstraps config.json on hosts that already have rendered sites
|
||||
(repo reinstalled over an existing data/ dir). If the declarative
|
||||
config already exists it wins: sites are vacuum-wall's own generated
|
||||
output ("do not edit manually") and re-parsing them is lossy — backend
|
||||
references get flattened to inline paths, which render empty nginx
|
||||
sites and hide domains from the WebUI.
|
||||
"""
|
||||
cfg_path = PROJECT_DIR / "config" / "nginx" / "config.json"
|
||||
if cfg_path.exists():
|
||||
logger.debug("Skipping nginx: %s already exists", cfg_path)
|
||||
return False
|
||||
|
||||
if not NGINX_SITES_DIR.exists():
|
||||
logger.debug("Skipping nginx: %s not found", NGINX_SITES_DIR)
|
||||
return False
|
||||
@@ -741,7 +754,6 @@ def import_nginx() -> bool:
|
||||
logger.debug("Skipping nginx: no valid site files")
|
||||
return False
|
||||
|
||||
cfg_path = PROJECT_DIR / "config" / "nginx" / "config.json"
|
||||
existing: dict[str, Any] = load_json(cfg_path, {"domains": {}, "ssl": {}})
|
||||
domains_cfg = existing.setdefault("domains", {})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user