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:
@@ -18,15 +18,39 @@ Environment=PYTHONUNBUFFERED=1
|
||||
Environment=ACME_HOME={{ PROJECT_DIR }}/data/acme
|
||||
Environment=HOME={{ PROJECT_DIR }}
|
||||
|
||||
# Runtime directory for temp files used during config apply
|
||||
RuntimeDirectory=vacuum-wall
|
||||
# Runtime directories created before namespace setup. ProtectSystem=strict
|
||||
# makes the whole hierarchy read-only, and namespace setup fails
|
||||
# (exit 226/NAMESPACE) if any ReadWritePaths= entry is missing at spawn.
|
||||
# /run is a fresh tmpfs at every boot, so volatile /run paths must be
|
||||
# created up front (RuntimeDirectory= here; /run/firewalld via
|
||||
# system/tmpfiles.d/vacuum-wall.conf and by firewalld itself) rather than
|
||||
# at first use.
|
||||
# vacuum-wall : secure temp files used during config apply
|
||||
# nginx : /run/nginx (listed in ReadWritePaths)
|
||||
RuntimeDirectory=vacuum-wall nginx
|
||||
RuntimeDirectoryMode=0750
|
||||
|
||||
LogsDirectory=vacuum-wall
|
||||
|
||||
# Security hardening
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths={{ PROJECT_DIR }} /tmp /etc/systemd/network /etc/nginx /etc/dnsmasq.d /etc/wireguard /run/vacuum-wall /run/sudo /run/firewalld /run/nginx /run/nginx.pid /var/log/nginx /var/log/vacuum-wall
|
||||
# NOTE: every ReadWritePaths= entry must exist when the unit spawns or namespace
|
||||
# setup fails (226/NAMESPACE). Volatile /run entries are pre-created:
|
||||
# /run/vacuum-wall, /run/nginx → RuntimeDirectory= (above)
|
||||
# /run/firewalld → system/tmpfiles.d/vacuum-wall.conf (and is
|
||||
# present while firewalld runs, which starts
|
||||
# before this unit)
|
||||
# /run/sudo is intentionally NOT listed: the daemon's sudo children use the
|
||||
# NOPASSWD whitelist and never need sudo's session directory (verified with
|
||||
# the directory absent). Listing it made the unit crash-loop whenever it
|
||||
# restarted after the last sudo session had ended and sudo removed /run/sudo.
|
||||
# /run/nginx.pid IS listed: nginx -t opens the pid file for *writing* in
|
||||
# addition to -s/acme reading it, so a read-only mount makes every daemon-side
|
||||
# `nginx -t` (and therefore /nginx/apply) fail with EROFS. The file is
|
||||
# pre-created by system/tmpfiles.d/vacuum-wall.conf so the ReadWritePaths=
|
||||
# entry always exists at spawn (nginx rewrites it on start; nginx -t does
|
||||
# not modify its contents).
|
||||
ReadWritePaths={{ PROJECT_DIR }} /tmp /etc/systemd/network /etc/nginx /etc/dnsmasq.d /etc/wireguard /run/vacuum-wall /run/firewalld /run/nginx /run/nginx.pid /var/log/nginx /var/log/vacuum-wall
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Volatile /run entries that must exist before vacuum-walld spawns.
|
||||
#
|
||||
# vacuum-walld runs with ProtectSystem=strict and lists these paths in
|
||||
# ReadWritePaths=; if a ReadWritePaths= entry is missing at spawn time,
|
||||
# systemd's mount-namespace setup fails (exit 226/NAMESPACE) and the unit
|
||||
# crash-loops without ever creating data/daemon.sock. /run is a fresh tmpfs
|
||||
# at every boot, so every /run path the unit references needs a boot-time
|
||||
# creator. Status per path:
|
||||
#
|
||||
# /run/vacuum-wall, /run/nginx -> unit RuntimeDirectory= (daemon-owned)
|
||||
# /run/firewalld -> this file (the firewalld unit only creates
|
||||
# it while firewalld itself is running)
|
||||
# /run/nginx.pid -> this file (nginx rewrites it on start; the
|
||||
# daemon's `nginx -t` must be able to open
|
||||
# it for writing inside its ProtectSystem=strict
|
||||
# namespace, so it needs both a boot-time
|
||||
# creator and a ReadWritePaths= entry)
|
||||
# /run/sudo -> not referenced by the unit (see
|
||||
# ReadWritePaths note in vacuum-walld.service);
|
||||
# the sudo package ships its own tmpfiles spec
|
||||
#
|
||||
# Applied at early boot by systemd-tmpfiles-setup.service and by the install
|
||||
# script (`systemd-tmpfiles --create`) for existing hosts.
|
||||
d /run/firewalld 0750 root root -
|
||||
f /run/nginx.pid 0644 root root -
|
||||
Reference in New Issue
Block a user