| … | … | @@ -30,6 +30,14 @@ REPO_DIR="${HIVERELAY_REPO_DIR:-$HOME/hiverelay}" |
| 30 | 30 | CONF="${HIVERELAY_UPDATER_CONF:-/etc/hiverelay-updater.conf}" |
| 31 | 31 | CHANNELS_URL="${HIVERELAY_CHANNELS_URL:-https://raw.githubusercontent.com/bigdestiny2/P2P-Hiverelay/main/fleet/channels.json}" |
| 32 | 32 | SERVICE="${HIVERELAY_SERVICE:-hiverelay}" |
| 33 | # Where this agent is installed, for the post-update self-refresh. Resolved from |
| 34 | # $0 so a non-standard install path still refreshes itself; falls back to the |
| 35 | # canonical location when $0 is not a readable file (e.g. piped from stdin). |
| 36 | SELF_PATH="${HIVERELAY_UPDATER_PATH:-}" |
| 37 | if [ -z "$SELF_PATH" ]; then |
| 38 | if [ -f "$0" ]; then SELF_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")" |
| 39 | else SELF_PATH="/usr/local/bin/hiverelay-updater"; fi |
| 40 | fi |
| 33 | 41 | API="${HIVERELAY_API:-http://127.0.0.1:9100}" |
| 34 | 42 | ENV_FILE="${HIVERELAY_ENV_FILE:-/etc/hiverelay/hiverelay.env}" |
| 35 | 43 | HEALTH_TIMEOUT="${HIVERELAY_HEALTH_TIMEOUT:-120}" |
| … | … | @@ -242,6 +250,24 @@ deps_if_changed() { # $1=from-ref $2=to-ref |
| 242 | 250 | fi |
| 243 | 251 | } |
| 244 | 252 | |
| 253 | # Prove the runtime can actually boot BEFORE restarting the live service. |
| 254 | # |
| 255 | # `npm ci` succeeding does not mean the relay can start. On 2026-07-28 |
| 256 | # utah-0.5gb installed cleanly and then crash-looped, because require-addon |
| 257 | # resolved the package root to "/" and looked for |
| 258 | # /prebuilds/linux-x64/sodium-native.node — the binary was present and correct |
| 259 | # inside node_modules. Same tag, same install; the difference was Node |
| 260 | # v22.22.2 vs v22.22.0 on the box that worked. `engines: >=20.0.0` admits both. |
| 261 | # |
| 262 | # Loading hyperswarm walks the exact chain that failed |
| 263 | # (hyperswarm -> hyperdht -> dht-rpc -> udx-native -> require-addon -> |
| 264 | # sodium-native), so this catches native-addon breakage of any origin — bad |
| 265 | # prebuild, wrong libc, Node ABI drift — without pinning a version we would |
| 266 | # then have to chase. Cheap: a require, no network, no listeners. |
| 267 | preflight_runtime() { |
| 268 | node -e 'require("hyperswarm")' >/dev/null 2>&1 |
| 269 | } |
| 270 | |
| 245 | 271 | rollback_to_previous() { |
| 246 | 272 | local reason="$1" |
| 247 | 273 | log "FAIL $reason — ROLLING BACK to $CUR_VER ($CUR_SHA)" |
| … | … | @@ -278,6 +304,34 @@ verify_tag "$TARGET" || die "refusing to update: tag $TARGET is not signed by a |
| 278 | 304 | |
| 279 | 305 | git checkout --quiet "$TARGET" || die "checkout $TARGET failed" |
| 280 | 306 | deps_if_changed "$CUR_SHA" "$TARGET_SHA" || rollback_to_previous "dependency install failed on $TARGET" |
| 307 | preflight_runtime || rollback_to_previous "runtime preflight failed on $TARGET (native addon or Node ABI)" |
| 308 | |
| 309 | # SELF-UPDATE. The agent is the one component an update could never fix: it |
| 310 | # runs from /usr/local/bin and nothing here reinstalled it, so a bug in the |
| 311 | # update path could only be repaired by hand-visiting every box. That is |
| 312 | # exactly what happened with the missing --force on the rollback checkout — |
| 313 | # the fix shipped in the tag and reached no relay. |
| 314 | # |
| 315 | # Ordering matters. This runs AFTER verify_tag and AFTER the deps install, so |
| 316 | # the script being installed comes from a signature-verified tree that has |
| 317 | # already proven it can install. It runs BEFORE the service restart so a |
| 318 | # failed restart rolls back with the NEW agent's logic. |
| 319 | # |
| 320 | # The running shell is unaffected: bash has already read this file, and the |
| 321 | # replacement takes effect on the next tick. Install atomically (write a temp |
| 322 | # beside the target, then rename) so a crash mid-copy cannot leave a partial |
| 323 | # interpreter script at a path systemd will execute. |
| 324 | if [ -f "$REPO_DIR/fleet/updater.sh" ] && ! cmp -s "$REPO_DIR/fleet/updater.sh" "$SELF_PATH"; then |
| 325 | if install -m 0755 "$REPO_DIR/fleet/updater.sh" "$SELF_PATH.next" 2>/dev/null && |
| 326 | bash -n "$SELF_PATH.next" 2>/dev/null && |
| 327 | mv -f "$SELF_PATH.next" "$SELF_PATH" 2>/dev/null; then |
| 328 | log "agent self-updated from $TARGET — active next tick" |
| 329 | else |
| 330 | rm -f "$SELF_PATH.next" 2>/dev/null || true |
| 331 | log "WARN agent self-update failed (non-fatal); continuing with the running agent" |
| 332 | fi |
| 333 | fi |
| 334 | |
| 281 | 335 | systemctl restart "$SERVICE" |
| 282 | 336 | |
| 283 | 337 | if healthy "${TARGET#v}"; then |