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:
@@ -69,6 +69,22 @@
|
||||
# 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
|
||||
# Installing over the target requires root. --dry-run deliberately does not, so the
|
||||
# change report can be previewed by anyone.
|
||||
@@ -148,6 +164,30 @@ done
|
||||
[[ -f "$TEMPLATE" ]] || { echo "Error: template not found: $TEMPLATE" >&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 ───────────────────────────────────────────────
|
||||
|
||||
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"
|
||||
|
||||
# ── 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
|
||||
echo " Already up to date — no changes needed."
|
||||
echo "────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
@@ -580,7 +580,7 @@
|
||||
HOSTN_OLLAMA_URL="" # e.g. http://localhost:11434 — empty if no local Ollama
|
||||
HOSTN_OLLAMA_CONTAINER="Ollama" # for watchdog / restart lists
|
||||
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
|
||||
|
||||
# ━━━ Authelia ━━━
|
||||
|
||||
+1
-21
@@ -1,26 +1,6 @@
|
||||
# Varaverk AI Integration — Design Notes
|
||||
|
||||
**Status: retrieval is built; integration is not.** As of 2026-08-02 the `AI_*` and
|
||||
`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:
|
||||
|
||||
**Status
|
||||
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
|
||||
3. Cleanup and sync decision aid — closest to destructive, last to be trusted
|
||||
|
||||
Reference in New Issue
Block a user