| 1 | #!/usr/bin/env sh |
| 2 | # π€ ops mesh β mesh-membership maintenance for the activator mesh |
| 3 | # (docs/planet-scale.md; meshreplicate.go). |
| 4 | # |
| 5 | # ./deploy/ops mesh seed <peer-base-url> [box] # replicate every in-scope |
| 6 | # # hibernating route (+ its |
| 7 | # # instance env) to a peer |
| 8 | # |
| 9 | # Why this verb exists: a box joins the mesh with an EMPTY registry, but HRW |
| 10 | # placement starts assigning it hosts the moment it heartbeats β any host it |
| 11 | # doesn't know answers "unknown host", so an unseeded member silently blackholes |
| 12 | # ~1/N of the placement-scoped fleet, new creates included. `lchat mesh-seed` is |
| 13 | # the catch-up; this verb runs it on the source box with the router's own env |
| 14 | # borrowed via --env-file (the mesh token/domains live in /data/router.env, |
| 15 | # which operators deliberately cannot read β the sudo'd binary can). |
| 16 | # |
| 17 | # Run it FROM the box that has the routes (the established member), pointing at |
| 18 | # the box that needs them. Idempotent: re-seeding overwrites with the same |
| 19 | # content, so run it again whenever in doubt β e.g. after a peer rebuild, or |
| 20 | # after this repo gains new replicated fields (the env began riding along |
| 21 | # 2026-07-24; a pre-env seed left peers waking instances token-less). |
| 22 | set -eu |
| 23 | |
| 24 | sub="${1:-}" |
| 25 | [ $# -gt 0 ] && shift |
| 26 | |
| 27 | case "$sub" in |
| 28 | seed) |
| 29 | # `seed --prune` also tombstones peer rows the source no longer has β |
| 30 | # the reconciliation for deletions a best-effort fan-out missed (#1346). |
| 31 | PRUNE="" |
| 32 | if [ "${1:-}" = "--prune" ]; then PRUNE="--prune"; shift; fi |
| 33 | peer="${1:-}" |
| 34 | box="${2:-${LCHAT_MESH_SOURCE_BOX:-elevenbox}}" |
| 35 | if [ -z "$peer" ]; then |
| 36 | echo "usage: ops mesh seed [--prune] <peer-base-url> [box] (e.g. ops mesh seed https://77.68.125.53)" >&2 |
| 37 | exit 2 |
| 38 | fi |
| 39 | echo "== seeding mesh routes (+env) from $box to $peer${PRUNE:+, pruning stale peer rows}" |
| 40 | ssh "$box" "sudo -n /opt/lchat/lchat mesh-seed --env-file /data/router.env $PRUNE '$peer'" |
| 41 | ;; |
| 42 | ""|-h|--help|help|*) |
| 43 | cat <<'EOF' >&2 |
| 44 | ops mesh β mesh-membership maintenance |
| 45 | |
| 46 | ./deploy/ops mesh seed [--prune] <peer-base-url> [box] |
| 47 | replicate all in-scope hibernating |
| 48 | routes (+ instance env) to a peer; |
| 49 | --prune also tombstones peer rows |
| 50 | the source no longer has |
| 51 | (box defaults to elevenbox) |
| 52 | EOF |
| 53 | [ "$sub" = "" ] || [ "$sub" = "-h" ] || [ "$sub" = "--help" ] || [ "$sub" = "help" ] || exit 2 |
| 54 | ;; |
| 55 | esac |
| 56 | |