Record the tailscale grace period as a deadline instead of sleeping six hours inside the offboard
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
# Step 8: Restart mirror — bring up mirror's own parked containers
|
||||
# Step 9: Revocation — Emby admin, SSH keys
|
||||
# Step 10: Write state — INACTIVE locally + pushed to mirror, mirror blocklisted
|
||||
# Tailscale — grace window then device removal (after state written)
|
||||
# Tailscale — grace deadline recorded, device removed after it expires
|
||||
#
|
||||
# MIRROR PATH (8 steps)
|
||||
# Step 1: Stop rsync — halt any running sync
|
||||
@@ -103,9 +103,12 @@
|
||||
# The mirror is added to the partnership blocklist, which rsync.sh checks and refuses on —
|
||||
# stale access cannot survive the offboard.
|
||||
#
|
||||
# Tailscale Grace Window
|
||||
# Tailscale Grace Window Is a Deadline, Not a Sleep
|
||||
# Device removal happens after state is written, not before, so the final state push
|
||||
# cannot be cut off by removing its own transport.
|
||||
# cannot be cut off by removing its own transport. The grace period itself is recorded to
|
||||
# STATE_DIR/tailscale_removal_due.db and the offboard returns. It used to sleep
|
||||
# PARTNERSHIP_GRACE_HOURS inline — six hours by default — holding the lock and its job record
|
||||
# open the whole time, reporting "running", and blocking any re-onboard behind it.
|
||||
#
|
||||
# Dry Run Support
|
||||
# --dry-run walks the full sequence reporting each step without executing any.
|
||||
@@ -603,21 +606,46 @@ fi
|
||||
if [[ "${PARTNERSHIP_REMOVE_TAILSCALE:-true}" == true ]]; then
|
||||
echo ""
|
||||
echo "━━━ $ICON_NET Tailscale Separation ━━━"
|
||||
if [[ "$MIRROR_REACHABLE" == true ]]; then
|
||||
grace_seconds=$(( ${PARTNERSHIP_GRACE_HOURS:-6} * 3600 ))
|
||||
warn "Waiting ${PARTNERSHIP_GRACE_HOURS:-6}hr grace — mirror can collect backups..."
|
||||
# The grace period is recorded as a deadline, not slept through.
|
||||
#
|
||||
# This used to `sleep $((PARTNERSHIP_GRACE_HOURS * 3600))` inline — six hours by default —
|
||||
# holding the offboard's lock and its job record open the whole time, showing "running" to
|
||||
# every status reader, and blocking any re-onboard behind the lock. Worse, the sleep ran
|
||||
# even when removal was going to be a no-op: TAILSCALE_API_KEY and TAILSCALE_TAILNET are
|
||||
# both empty here, so the six hours bought nothing at all.
|
||||
#
|
||||
# The offboard's own work is finished by this point. Writing the deadline lets the teardown
|
||||
# complete now and leaves the removal to whoever reads the file — and makes the wait
|
||||
# visible and cancellable instead of buried in a sleeping process.
|
||||
_grace_h="${PARTNERSHIP_GRACE_HOURS:-6}"
|
||||
if [[ "$_grace_h" -gt 0 ]] && [[ "$MIRROR_REACHABLE" == true ]]; then
|
||||
_due=$(( $(date +%s) + _grace_h * 3600 ))
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
trap 'warn "Offboard interrupted during grace sleep"; exit 0' SIGTERM SIGINT
|
||||
sleep "$grace_seconds"
|
||||
trap - SIGTERM SIGINT
|
||||
printf 'host=%s\ndue=%s\ndue_human=%s\nreason=%s\n' \
|
||||
"$MIRROR" "$_due" "$(date -d "@$_due" '+%Y-%m-%d %H:%M:%S')" "$REASON" \
|
||||
> "${STATE_DIR}/tailscale_removal_due.db"
|
||||
fi
|
||||
warn "Grace period: $MIRROR stays on the tailnet until $(date -d "@$_due" '+%Y-%m-%d %H:%M') — recorded, not slept"
|
||||
# No CLI entry point removes it yet, and there is deliberately no invented one here:
|
||||
# remove_tailscale_device() is a partnership_manager.sh function with no --mode of its
|
||||
# own, and it no-ops without credentials regardless. Say what is true.
|
||||
if [[ -z "${TAILSCALE_API_KEY:-}" || -z "${TAILSCALE_TAILNET:-}" ]]; then
|
||||
warn "Automatic removal is not possible — TAILSCALE_API_KEY/TAILSCALE_TAILNET are unset; remove it in the Tailscale admin console"
|
||||
else
|
||||
warn "Removal after that is not yet automated — remove it in the Tailscale admin console"
|
||||
fi
|
||||
TAILSCALE_REMOVED=deferred
|
||||
unset _grace_h _due
|
||||
else
|
||||
# No grace configured, or the mirror is already unreachable — remove now.
|
||||
#
|
||||
# Outcome recorded, not assumed. remove_tailscale_device returns 1 when TAILSCALE_API_KEY
|
||||
# or TAILSCALE_TAILNET is unset — it warns "skipping Tailscale removal" and the summary
|
||||
# went on to report "removed ✅" anyway, so an offboard that left the device on the
|
||||
# tailnet said it had taken it off. Neither key is configured here, so that was every run.
|
||||
if remove_tailscale_device "$MIRROR"; then
|
||||
TAILSCALE_REMOVED=true
|
||||
fi
|
||||
fi
|
||||
# Outcome recorded, not assumed. remove_tailscale_device returns 1 when TAILSCALE_API_KEY or
|
||||
# TAILSCALE_TAILNET is unset — it warns "skipping Tailscale removal" and the summary went on
|
||||
# to report "removed ✅" anyway, so an offboard that left the device on the tailnet said it
|
||||
# had taken it off. Neither key is configured here, so that was the case on every run.
|
||||
if remove_tailscale_device "$MIRROR"; then
|
||||
TAILSCALE_REMOVED=true
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -667,11 +695,11 @@ echo " Step 10 — State: $( [[ "$STEP_STATE_WRITE_OK" == true ]] && e
|
||||
echo ""
|
||||
echo " Blocklist: $MIRROR blocked — re-onboard to permit access again ✅"
|
||||
if [[ "${PARTNERSHIP_REMOVE_TAILSCALE:-true}" == true ]]; then
|
||||
if [[ "$TAILSCALE_REMOVED" == true ]]; then
|
||||
echo " Tailscale: $MIRROR removed ✅"
|
||||
else
|
||||
echo " Tailscale: $MIRROR NOT removed ⚠ — still on the tailnet (needs TAILSCALE_API_KEY + TAILSCALE_TAILNET)"
|
||||
fi
|
||||
case "$TAILSCALE_REMOVED" in
|
||||
true) echo " Tailscale: $MIRROR removed ✅" ;;
|
||||
deferred) echo " Tailscale: $MIRROR kept until the grace period expires — see ${STATE_DIR}/tailscale_removal_due.db" ;;
|
||||
*) echo " Tailscale: $MIRROR NOT removed ⚠ — still on the tailnet (needs TAILSCALE_API_KEY + TAILSCALE_TAILNET)" ;;
|
||||
esac
|
||||
fi
|
||||
# Named because it is the one partnership switch neither onboard nor offboard moves, so it
|
||||
# survives an offboard still true and there is nothing else that would ever mention it.
|
||||
|
||||
Reference in New Issue
Block a user