From 6d9c8565147d13b2b6f4fc1de1c9001b916e72fb Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sun, 16 Aug 2026 12:51:24 -0400 Subject: [PATCH] Open the sync gates when a partnership actually completes, instead of leaving them shut for ever --- Partnership/partnership_onboard.sh | 81 ++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/Partnership/partnership_onboard.sh b/Partnership/partnership_onboard.sh index 35aca04..2440021 100755 --- a/Partnership/partnership_onboard.sh +++ b/Partnership/partnership_onboard.sh @@ -35,6 +35,8 @@ # Step 9c: Media seed — rsync all DAILY_SYNC_SHARES to mirror (--seed) # prevents arrs treating every file as missing after bootstrap # Step 9d: Webhook listener — start listener on mirror (runs continuously, no reboot needed) +# Step 9e: Arm sync gates — open RSYNC/CONF_SYNC/ARR_SYNC in master.conf, which the +# template ships closed so a fresh node cannot sync early # Step 10: Conf push — push master.conf + setup state to all listed hosts # # ============================================================================================== @@ -158,6 +160,11 @@ # Skip starting webhook listener on mirror (Step 9d) # Listener will start automatically on next array restart # +# Partnership/partnership_onboard.sh --no-arm +# Leave RSYNC_ENABLED / CONF_SYNC_ENABLED / ARR_SYNC_ENABLED as they are (Step 9e). +# Use when onboarding a node you want to keep inert — a rebuild test, or a mirror whose +# shares are not populated yet. +# # Partnership/partnership_onboard.sh --phase1-only # OWNER only: SSH key exchange + conf push. Safe to run before HOST2 has Varaverk. # Writes HOST2_PHASE1_DONE=true to varaverk_setup.db. @@ -188,6 +195,7 @@ SKIP_MEDIA_SEED=false SKIP_WEBHOOK_LISTENER=false PHASE1_ONLY=false # OWNER: SSH + conf push only (HOST2 not yet installed) PHASE2_ONLY=false # OWNER: containers/arr/onboard only (triggered by HOST2 after it onboards) +SKIP_ARM=false # leave the sync gates as they are — see Step 9e FILTERED_ARGS=() for arg in "$@"; do @@ -203,6 +211,7 @@ for arg in "$@"; do --skip-webhook-listener) SKIP_WEBHOOK_LISTENER=true ;; --phase1-only) PHASE1_ONLY=true ;; --phase2-only) PHASE2_ONLY=true; SKIP_SSH=true ;; + --no-arm) SKIP_ARM=true ;; *) FILTERED_ARGS+=("$arg") ;; esac done @@ -241,6 +250,33 @@ write_onboard_phase() { platform_push_setup_state } +# ── Helper: set a boolean toggle in master.conf, in place ───────────────────────────────────── +# Booleans only. The value pattern stops at whitespace, so a quoted value containing spaces would +# be truncated — every gate this arms is true/false and nothing else should use it. +# +# Preserves what the line already looks like: leading indent, the existing quoting style, and the +# column the trailing comment sits in. master.conf is hand-aligned and read by a person; an edit +# that reflows a line makes a diff that looks bigger than the change actually is. +_arm_conf_var() { + local key="$1" val="$2" file="$3" cur pad spaces quoted + if ! grep -qE "^[[:space:]]*${key}=" "$file"; then + warn " ${key} is not in master.conf — skipped (add it to the template first)" + return 1 + fi + cur=$(grep -E "^[[:space:]]*${key}=" "$file" | head -1 | sed -E "s|^[[:space:]]*${key}=||; s|[[:space:]]*#.*$||") + quoted=""; [[ "$cur" == \"*\" ]] && quoted='"' + cur="${cur//\"/}" + [[ "$cur" == "$val" ]] && { echo " ${key} already ${val}"; return 0; } + # Pad only when a comment follows — otherwise a shorter value leaves trailing whitespace. + pad=0 + if grep -qE "^[[:space:]]*${key}=[^#]*#" "$file"; then + pad=$(( ${#cur} - ${#val} )); (( pad < 0 )) && pad=0 + fi + spaces=$(printf '%*s' "$pad" '') + sed -i -E "s|^([[:space:]]*)${key}=[^#[:space:]]*([[:space:]]*)(#.*)?$|\1${key}=${quoted}${val}${quoted}${spaces}\2\3|" "$file" + echo " ${key}: ${cur} → ${val}" +} + echo "" echo "━━━ $ICON_FALLBACK Partnership Onboard — $MY_ID ($LOCAL_SERVER_NAME) — $(date '+%Y-%m-%d %H:%M:%S') ━━━" echo "" @@ -732,6 +768,50 @@ else fi unset _listener_script +# ── Step 9e: Arm the sync gates ─────────────────────────────────────────────────────────────── +# master.conf.template ships a fresh node inert — RSYNC_ENABLED, CONF_SYNC_ENABLED and +# ARR_SYNC_ENABLED all false — because a node that has just been seeded has empty shares and no +# verified partner, and those two facts are what make unattended syncing safe to do. +# +# A successful onboard is the event that makes them true. Without this step the defaults were a +# one-way door: the node stayed inert for ever and somebody had to remember to hand-edit three +# toggles, on the machine where forgetting looks exactly like everything working. +# +# Runs before Step 10 on purpose. The push carries the owner's master.conf to every listed host, +# so arming here means both sides come up agreeing about whether sync is on; arming after the +# push would leave the mirror a version behind until the next conf save. +# +# Owner only — the mirror receives these values in the push rather than deciding for itself. +ARM_OK=true +echo "" +echo "━━━ $ICON_GEAR Step 9e — Arm Sync Gates ━━━" + +if [[ "$ONBOARD_OK" == false ]]; then + warn "Skipping — onboard did not complete, leaving the gates closed" + ARM_OK=false +elif [[ "$SKIP_ARM" == true ]]; then + echo " --no-arm — leaving the sync gates as they are" +elif [[ "$AM_OWNER" != true ]]; then + echo " mirror — the owner's push decides these" +elif [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would set RSYNC_ENABLED, CONF_SYNC_ENABLED, ARR_SYNC_ENABLED to true" +else + _master_conf="$SCRIPTS_ROOT/Configurations/master.conf" + if [[ ! -f "$_master_conf" ]]; then + warn "master.conf not found at $_master_conf — gates left closed" + ARM_OK=false + else + cp -a "$_master_conf" "${_master_conf}.bak-arm-$(date +%Y%m%d-%H%M%S)" + for _gate in RSYNC_ENABLED CONF_SYNC_ENABLED ARR_SYNC_ENABLED; do + _arm_conf_var "$_gate" "true" "$_master_conf" || ARM_OK=false + done + # Tier 1 is now open, so say what that actually turned on rather than leaving it implied. + echo " rsync tier 2 gates were left as configured — check them before the first run" + unset _gate + fi + unset _master_conf +fi + # ── Step 10: Push master.conf to all listed hosts ───────────────────────────────────────────── # SSH is now established and all partners have the plugin installed. # Push the authoritative master.conf so every listed host is in sync immediately. @@ -784,6 +864,7 @@ echo " Step 9 — Arr bootstrap: $( [[ "$SKIP_ARR_SYNC" == true || "$ONBOAR echo " Step 9b — Webhook setup: $(_skip "$SKIP_WEBHOOK_SETUP" "$WEBHOOK_SETUP_OK")" echo " Step 9c — Media seed: $( [[ "$SKIP_MEDIA_SEED" == true ]] && echo "skipped" || echo "${MEDIA_SEED_COUNT}/${#DAILY_SYNC_SHARES[@]} shares $(_ok "$MEDIA_SEED_OK")" )" echo " Step 9d — Webhook listener: $(_skip "$SKIP_WEBHOOK_LISTENER" "$WEBHOOK_LISTENER_OK")" +echo " Step 9e — Arm sync gates: $( [[ "$SKIP_ARM" == true ]] && echo "skipped (--no-arm)" || { [[ "$ONBOARD_OK" == false ]] && echo "skipped" || echo "$(_ok "$ARM_OK")"; } )" echo " Step 10 — Conf push: $( [[ "$ONBOARD_OK" == false ]] && echo "skipped" || echo "$(_ok "$MASTER_PUSH_OK")" )" echo ""