Refuse a conf_upgrade that would keep nothing

Merging the raw host.conf.template against a live host conf matched HOSTN_
against HOST1_, classified all 140 real keys as deprecated and would have
removed every credential on the host. Also points the Ollama model default
at a tag that still exists.
This commit is contained in:
Gmer4Lfe
2026-08-02 12:52:49 -04:00
parent e02dc1be15
commit 2d07c7d80e
3 changed files with 60 additions and 22 deletions
+58
View File
@@ -69,6 +69,22 @@
# OPERATIONAL SAFEGUARDS # OPERATIONAL SAFEGUARDS
# ============================================================================================== # ==============================================================================================
# #
# Unsubstituted HOSTN Placeholders Are Refused
# host.conf.template ships HOSTN_ placeholders; a live host conf uses HOST1_ / HOST2_. Key
# matching is literal, so merging the raw template against a real host conf classifies every
# existing key as deprecated — KEPT 0 — and the install drops every credential in the file.
# Verified on HOST1 2026-08-02: it would have removed HOST1_RADARR_API_KEY,
# HOST1_EMBY_API_KEY, HOST1_NPM_PASS and 137 others. The template is checked for HOSTN and
# the target for a HOST<n> slot; if both are present the run aborts and prints the exact sed
# command to substitute. Refused rather than auto-substituted — this rewrites the file holding
# every secret on the host, and inferring the slot is not worth being wrong about.
#
# Total Mismatch Is Refused
# Keeping nothing from a populated conf is never a real upgrade; it means the two files do
# not describe the same thing. KEPT 0 with a non-empty REMOVED list aborts. This is the
# general net behind the HOSTN check — the failure mode is silent and total, so it fires in
# --dry-run as well, putting the warning in the report itself.
#
# Root Required to Write # Root Required to Write
# Installing over the target requires root. --dry-run deliberately does not, so the # Installing over the target requires root. --dry-run deliberately does not, so the
# change report can be previewed by anyone. # change report can be previewed by anyone.
@@ -148,6 +164,30 @@ done
[[ -f "$TEMPLATE" ]] || { echo "Error: template not found: $TEMPLATE" >&2; exit 1; } [[ -f "$TEMPLATE" ]] || { echo "Error: template not found: $TEMPLATE" >&2; exit 1; }
[[ -f "$TARGET" ]] || { echo "Error: target not found: $TARGET" >&2; exit 1; } [[ -f "$TARGET" ]] || { echo "Error: target not found: $TARGET" >&2; exit 1; }
# ── Guard: unsubstituted HOSTN placeholders ──────────────────────────────────────────────────
#
# host.conf.template ships HOSTN_ placeholders; a live host conf uses HOST1_ / HOST2_. Key
# matching below is literal, so merging the raw template against a real host conf classifies
# EVERY existing key as deprecated and every template key as new — KEPT 0, and the install
# would drop every credential in the file. api/setup.php substitutes before writing; a direct
# invocation has no such step. Refused rather than auto-substituted: this rewrites the file
# that holds every secret on the host, and guessing the slot is not worth being wrong about.
if grep -q 'HOSTN' "$TEMPLATE" 2>/dev/null; then
_slot=$(grep -oEm1 '^[[:space:]]*(HOST[0-9]+)_' "$TARGET" 2>/dev/null | grep -oE 'HOST[0-9]+')
if [[ -n "$_slot" ]]; then
_lower=$(echo "$_slot" | tr '[:upper:]' '[:lower:]')
echo "Error: template still contains HOSTN placeholders, but the target uses ${_slot}_." >&2
echo " Merging as-is would classify all ${_slot}_ keys as deprecated and remove" >&2
echo " them — including every credential. Substitute the slot first:" >&2
echo "" >&2
echo " sed -e 's/HOSTN/${_slot}/g' -e 's/hostn/${_lower}/g' \\" >&2
echo " $TEMPLATE > /tmp/${_lower}.conf.template" >&2
echo " $0 --template /tmp/${_lower}.conf.template --target $TARGET --dry-run" >&2
echo "" >&2
exit 1
fi
fi
# ── Parse target → KEY → full definition block ─────────────────────────────────────────────── # ── Parse target → KEY → full definition block ───────────────────────────────────────────────
declare -A HOST_MAP # KEY → complete definition line(s) from user's conf declare -A HOST_MAP # KEY → complete definition line(s) from user's conf
@@ -268,6 +308,24 @@ fi
echo " KEPT ${#KEPT[@]} existing vars — your values preserved" echo " KEPT ${#KEPT[@]} existing vars — your values preserved"
# ── Guard: total mismatch ────────────────────────────────────────────────────────────────────
#
# Keeping nothing from a populated conf is never a real upgrade — it is the signature of the
# two files not describing the same thing (wrong template, wrong target, unsubstituted
# placeholders). The HOSTN check above catches the known cause; this catches the rest, because
# the failure mode is silent and total: every value in the file is replaced by a default.
# Deliberately fires in --dry-run too, so the report itself carries the warning.
if [[ ${#KEPT[@]} -eq 0 && ${#REMOVED[@]} -gt 0 ]]; then
echo "────────────────────────────────────────────────────────────────────────"
echo ""
echo "Error: refusing — this would keep NOTHING and remove all ${#REMOVED[@]} existing keys." >&2
echo " A genuine upgrade preserves values; keeping zero means the template and the" >&2
echo " target do not describe the same conf. Check that --template matches --target" >&2
echo " and that any HOSTN placeholders were substituted for this host's slot." >&2
echo "" >&2
exit 1
fi
if [[ ${#ADDED[@]} -eq 0 && ${#REMOVED[@]} -eq 0 ]]; then if [[ ${#ADDED[@]} -eq 0 && ${#REMOVED[@]} -eq 0 ]]; then
echo " Already up to date — no changes needed." echo " Already up to date — no changes needed."
echo "────────────────────────────────────────────────────────────────────────" echo "────────────────────────────────────────────────────────────────────────"
+1 -1
View File
@@ -580,7 +580,7 @@
HOSTN_OLLAMA_URL="" # e.g. http://localhost:11434 — empty if no local Ollama HOSTN_OLLAMA_URL="" # e.g. http://localhost:11434 — empty if no local Ollama
HOSTN_OLLAMA_CONTAINER="Ollama" # for watchdog / restart lists HOSTN_OLLAMA_CONTAINER="Ollama" # for watchdog / restart lists
HOSTN_OLLAMA_GPU_UUID="" # pins Ollama to one card on multi-GPU hosts HOSTN_OLLAMA_GPU_UUID="" # pins Ollama to one card on multi-GPU hosts
HOSTN_OLLAMA_MODEL="qwen2.5-coder:14b" # generation HOSTN_OLLAMA_MODEL="hf.co/unsloth/Qwen3-14B-GGUF:IQ4_XS" # generation — must fully offload; see README-AI.md
HOSTN_OLLAMA_EMBED_MODEL="nomic-embed-text" # embeddings — the generation model cannot embed HOSTN_OLLAMA_EMBED_MODEL="nomic-embed-text" # embeddings — the generation model cannot embed
# ━━━ Authelia ━━━ # ━━━ Authelia ━━━
+1 -21
View File
@@ -1,26 +1,6 @@
# Varaverk AI Integration — Design Notes # Varaverk AI Integration — Design Notes
**Status: retrieval is built; integration is not.** As of 2026-08-02 the `AI_*` and **Status
`HOST*_OLLAMA_*` variables exist in both confs and both templates, and `AI/` holds a working
index and query path — see the RAG section at the end of this document and `AI/README-AI.md`.
Everything else below remains design only. **No Varaverk script consults AI.** Every
`AI_ASSIST_*` toggle is false, `AI_CONF_WRITE_ENABLED` is false with an empty whitelist, and
host resolution across the mesh is specified but not implemented. Originally captured
2026-08-01 so the reasoning survives.
Ollama itself *is* installed, tuned and verified on HOST1 — `qwen2.5-coder:14b` for
generation, `nomic-embed-text` for embeddings, 16k context, pinned to the RTX 3080. See
Hardware Budget for measured numbers. That is the substrate, not the integration.
**Origin:** the RTX 3080 was freed when the Windows gaming VM was retired. It is bound to the
`nvidia` driver, not `vfio` — not reserved for passthrough, so there is no VM contention to
design around. Two goals at once: somewhere to learn local LLMs, and something Varaverk can
genuinely use.
**Build order** — deliberately lowest-risk first. Each stage must be boring before the next
one starts:
1. Chat assistant / settings helper / onboarding assistant — a wrong answer costs nothing 1. Chat assistant / settings helper / onboarding assistant — a wrong answer costs nothing
2. Watchdog and discovery context — a wrong answer costs a bad suggestion, still gated 2. Watchdog and discovery context — a wrong answer costs a bad suggestion, still gated
3. Cleanup and sync decision aid — closest to destructive, last to be trusted 3. Cleanup and sync decision aid — closest to destructive, last to be trusted