Send the webhook setup to the path the partner actually uses, and arm the sync gates before the seed that depends on them

This commit is contained in:
Gmer4Lfe
2026-08-16 20:32:14 -04:00
parent f363c6cd55
commit 7ed0f5c23b
2 changed files with 114 additions and 79 deletions
+101 -76
View File
@@ -32,11 +32,13 @@
# Step 8: Partnership onboard — configure WebUIs → owner IP, write state, Emby
# Step 9: Arr bootstrap — bidirectional library sync (arr_sync.sh)
# Step 9b: Webhook setup — register download webhook in arrs on both servers
# Step 9c: Media seed — rsync all DAILY_SYNC_SHARES to mirror (--seed)
# Step 9c: Arm sync gates — open RSYNC/CONF_SYNC/ARR_SYNC in master.conf, which the
# template ships closed so a fresh node cannot sync early.
# Ahead of the seed because the seed is itself an rsync and
# Tier 1 stops every rsync, including that one
# Step 9d: 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 9e: Webhook listener — start listener on mirror (runs continuously, no reboot needed)
# Step 10: Conf push — push master.conf + setup state to all listed hosts
#
# ==============================================================================================
@@ -153,15 +155,15 @@
# Skip webhook registration in arrs (Step 9b)
#
# Partnership/partnership_onboard.sh --skip-media-seed
# Skip initial media share rsync to mirror (Step 9c)
# Skip initial media share rsync to mirror (Step 9d)
# Use when mirror already has files or you want to seed manually
#
# Partnership/partnership_onboard.sh --skip-webhook-listener
# Skip starting webhook listener on mirror (Step 9d)
# Skip starting webhook listener on mirror (Step 9e)
# 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).
# Leave RSYNC_ENABLED / CONF_SYNC_ENABLED / ARR_SYNC_ENABLED as they are (Step 9c).
# Use when onboarding a node you want to keep inert — a rebuild test, or a mirror whose
# shares are not populated yet.
#
@@ -196,7 +198,7 @@ SKIP_WEBHOOK_LISTENER=false
PHASE1_ONLY=false # OWNER: SSH + conf push only (HOST2 not yet installed)
# MIRROR: SSH key install only, no owner notification
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
SKIP_ARM=false # leave the sync gates as they are — see Step 9c
FILTERED_ARGS=()
for arg in "$@"; do
@@ -799,67 +801,7 @@ else
fi
unset _webhook_script
# ── Step 9c: Seed media shares on mirror ─────────────────────────────────────────────────────
# arr_sync.sh bootstrapped the databases — mirror's arrs now know about all content but
# have no files on disk. Without this rsync, every imported item looks missing and arrs
# will immediately queue searches. --seed skips the empty-remote guard and does a clean push.
echo ""
echo "━━━ Step 9c — Media Share Seed ━━━"
if [[ "$SKIP_MEDIA_SEED" == true ]]; then
warn "Skipping (--skip-media-seed)"
elif [[ "${#DAILY_SYNC_SHARES[@]}" -eq 0 ]]; then
warn "DAILY_SYNC_SHARES empty for $MY_ID — skipping media seed"
warn "Configure HOST${MY_ID: -1}_DAILY_SYNC_SHARES in host${MY_ID: -1}.conf and run Rsync/rsync.sh --seed manually"
else
echo " Seeding ${#DAILY_SYNC_SHARES[@]} share(s) to $MIRROR — this may take a while"
_rsync_script="$SCRIPTS_ROOT/Rsync/rsync.sh"
_seed_flags=(--seed)
[[ "$DRY_RUN" == true ]] && _seed_flags+=(--dry-run)
[[ "$ENABLE_LOGGING" == true ]] && _seed_flags+=(--log)
for _share in "${DAILY_SYNC_SHARES[@]}"; do
echo " Seeding: $_share"
if bash "$_rsync_script" "$_share" "${_seed_flags[@]}"; then
(( MEDIA_SEED_COUNT++ )) || true
else
warn " Seed failed for $_share — re-run: Rsync/rsync.sh $_share --seed"
fi
done
if [[ "$MEDIA_SEED_COUNT" -gt 0 ]]; then
echo "Media seed complete — ${MEDIA_SEED_COUNT}/${#DAILY_SYNC_SHARES[@]} share(s) ✅"
MEDIA_SEED_OK=true
else
warn "Media seed: no shares completed — check errors above"
fi
unset _rsync_script _seed_flags _share
fi
# ── Step 9d: Start webhook listener on mirror ─────────────────────────────────────────────────
# Listener is in ARRAY_START_SCRIPTS so it starts on next boot, but the mirror's array is
# already running — kick it now so events are captured immediately after onboard.
echo ""
echo "━━━ Step 9d — Webhook Listener (Mirror) ━━━"
_listener_script="$SCRIPTS_ROOT/Arrs_Stack/start_webhook_listener.sh"
if [[ "$SKIP_WEBHOOK_LISTENER" == true ]]; then
warn "Skipping (--skip-webhook-listener)"
elif [[ "${WEBHOOK_PORT:-0}" -eq 0 ]]; then
warn "WEBHOOK_PORT=0 — webhook disabled, skipping"
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would start webhook listener on $MIRROR"
WEBHOOK_LISTENER_OK=true
elif timeout "$SSH_TIMEOUT" ssh -i "$MIRROR_SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$MIRROR_IP" \
"nohup bash '$_listener_script' > /var/log/varaverk/upgrade_webhook.log 2>&1 & echo started" \
2>/dev/null | grep -q started; then
echo "Webhook listener started on $MIRROR"
WEBHOOK_LISTENER_OK=true
else
warn "Could not start listener on $MIRROR — it will start automatically on next array restart"
fi
unset _listener_script
# ── Step 9e: Arm the sync gates ───────────────────────────────────────────────────────────────
# ── Step 9c: 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.
@@ -868,14 +810,19 @@ unset _listener_script
# 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.
# Ahead of the media seed, which it used to follow. The seed calls Rsync/rsync.sh, and Tier 1
# stops *every* rsync — so with the gates still closed all of it exited cleanly having moved
# nothing, and, because a clean exit is exit 0, the seed counted each share as a success and
# reported "14/14 shares ✅" over an empty mirror.
#
# Still ahead of Step 10 on purpose. The push carries the owner's master.conf to every listed
# host, so arming before it 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 ━━━"
echo "━━━ $ICON_GEAR Step 9c — Arm Sync Gates ━━━"
if [[ "$ONBOARD_OK" == false ]]; then
warn "Skipping — onboard did not complete, leaving the gates closed"
@@ -903,6 +850,82 @@ else
unset _master_conf
fi
# ── Step 9d: Seed media shares on mirror ─────────────────────────────────────────────────────
# arr_sync.sh bootstrapped the databases — mirror's arrs now know about all content but
# have no files on disk. Without this rsync, every imported item looks missing and arrs
# will immediately queue searches. --seed skips the empty-remote guard and does a clean push.
echo ""
echo "━━━ Step 9d — Media Share Seed ━━━"
# Read the gate back off disk rather than trusting the value sourced at startup: Step 9c has
# just rewritten master.conf, and each rsync.sh below is a separate process that will source
# the file fresh. A closed gate here means every share would exit 0 having moved nothing, so
# say so once and skip, instead of counting fourteen no-ops as fourteen successes.
#
# The trailing comment is cut before the value is read. master.conf writes this gate as
# RSYNC_ENABLED=true # Tier 1 — global gate, overrides everything below
# so stopping at `cut -d= -f2` and squeezing whitespace yields "true#Tier1—globalgate,…",
# which is not "true" — and the seed would then skip itself on every single run, including
# the ones where the gate is open.
_rsync_gate=$(grep -m1 -E '^[[:space:]]*RSYNC_ENABLED=' "$SCRIPTS_ROOT/Configurations/master.conf" 2>/dev/null \
| cut -d= -f2- | cut -d'#' -f1 | tr -d '"'"'" | tr -d '[:space:]')
if [[ "$SKIP_MEDIA_SEED" == true ]]; then
warn "Skipping (--skip-media-seed)"
elif [[ "$DRY_RUN" == false && "$_rsync_gate" != "true" ]]; then
warn "RSYNC_ENABLED is '$_rsync_gate' — skipping media seed, rsync.sh would move nothing"
warn "Arm it and re-run: Rsync/rsync.sh <share> --seed"
elif [[ "${#DAILY_SYNC_SHARES[@]}" -eq 0 ]]; then
warn "DAILY_SYNC_SHARES empty for $MY_ID — skipping media seed"
warn "Configure HOST${MY_ID: -1}_DAILY_SYNC_SHARES in host${MY_ID: -1}.conf and run Rsync/rsync.sh --seed manually"
else
echo " Seeding ${#DAILY_SYNC_SHARES[@]} share(s) to $MIRROR — this may take a while"
_rsync_script="$SCRIPTS_ROOT/Rsync/rsync.sh"
_seed_flags=(--seed)
[[ "$DRY_RUN" == true ]] && _seed_flags+=(--dry-run)
[[ "$ENABLE_LOGGING" == true ]] && _seed_flags+=(--log)
for _share in "${DAILY_SYNC_SHARES[@]}"; do
echo " Seeding: $_share"
if bash "$_rsync_script" "$_share" "${_seed_flags[@]}"; then
(( MEDIA_SEED_COUNT++ )) || true
else
warn " Seed failed for $_share — re-run: Rsync/rsync.sh $_share --seed"
fi
done
if [[ "$MEDIA_SEED_COUNT" -gt 0 ]]; then
echo "Media seed complete — ${MEDIA_SEED_COUNT}/${#DAILY_SYNC_SHARES[@]} share(s) ✅"
MEDIA_SEED_OK=true
else
warn "Media seed: no shares completed — check errors above"
fi
unset _rsync_script _seed_flags _share
fi
# ── Step 9e: Start webhook listener on mirror ─────────────────────────────────────────────────
# Listener is in ARRAY_START_SCRIPTS so it starts on next boot, but the mirror's array is
# already running — kick it now so events are captured immediately after onboard.
echo ""
echo "━━━ Step 9e — Webhook Listener (Mirror) ━━━"
_listener_script="$SCRIPTS_ROOT/Arrs_Stack/start_webhook_listener.sh"
if [[ "$SKIP_WEBHOOK_LISTENER" == true ]]; then
warn "Skipping (--skip-webhook-listener)"
elif [[ "${WEBHOOK_PORT:-0}" -eq 0 ]]; then
warn "WEBHOOK_PORT=0 — webhook disabled, skipping"
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would start webhook listener on $MIRROR"
WEBHOOK_LISTENER_OK=true
elif timeout "$SSH_TIMEOUT" ssh -i "$MIRROR_SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$MIRROR_IP" \
"nohup bash '$_listener_script' > /var/log/varaverk/upgrade_webhook.log 2>&1 & echo started" \
2>/dev/null | grep -q started; then
echo "Webhook listener started on $MIRROR"
WEBHOOK_LISTENER_OK=true
else
warn "Could not start listener on $MIRROR — it will start automatically on next array restart"
fi
unset _listener_script
# ── 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.
@@ -953,9 +976,11 @@ echo " Step 7 — Services stack: $( [[ "$SKIP_SERVICES_STACK" == true ]] &&
echo " Step 8 — Onboard: $(_ok "$ONBOARD_OK")"
echo " Step 9 — Arr bootstrap: $( [[ "$SKIP_ARR_SYNC" == true || "$ONBOARD_OK" == false ]] && echo "skipped" || echo "$(_ok "$ARR_SYNC_OK")" )"
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 9c — Arm sync gates: $( [[ "$SKIP_ARM" == true ]] && echo "skipped (--no-arm)" || { [[ "$ONBOARD_OK" == false ]] && echo "skipped" || echo "$(_ok "$ARM_OK")"; } )"
echo " Step 9d — Media seed: $( [[ "$SKIP_MEDIA_SEED" == true ]] && echo "skipped" \
|| { [[ "$DRY_RUN" == false && "${_rsync_gate:-}" != "true" ]] && echo "skipped (rsync gate closed)" \
|| echo "${MEDIA_SEED_COUNT}/${#DAILY_SYNC_SHARES[@]} shares $(_ok "$MEDIA_SEED_OK")"; } )"
echo " Step 9e — Webhook listener: $(_skip "$SKIP_WEBHOOK_LISTENER" "$WEBHOOK_LISTENER_OK")"
echo " Step 10 — Conf push: $( [[ "$ONBOARD_OK" == false ]] && echo "skipped" || echo "$(_ok "$MASTER_PUSH_OK")" )"
echo ""