#!/bin/bash # xmrblocks health check — managed by Ansible (roles/xmrblocks) # # The exit code is the answer and systemd keeps it: # systemctl is-failed xmrblocks-healthcheck.service # Reporting anywhere else is optional and generic. # # This fetches a real page rather than just opening the port. The binary # resolves its HTML as "./templates" relative to the working directory, so a # deploy that got WorkingDirectory wrong listens happily on 8081 and fails # every request. A TCP check would call that healthy. URL="${XMRBLOCKS_URL:-http://127.0.0.1:8081}" PUSH_URL="${HEALTHCHECK_PUSH_URL:-}" PUSH_TOKEN="${HEALTHCHECK_PUSH_TOKEN:-}" report() { local status=$1 local msg=$2 # No push URL is normal, not an error: the exit code below is still a # complete answer for anything reading unit state. [ -n "$PUSH_URL" ] || return 0 local encoded_msg="${msg// /%20}" local _ok=false [ "${status}" = "up" ] && _ok=true curl -s --max-time 15 --retry 2 -o /dev/null -X POST \ -H "Authorization: Bearer ${PUSH_TOKEN}" \ "${PUSH_URL}?success=${_ok}&error=${encoded_msg}" || true } # 90s, not the obvious 10 or 25. The index page renders ~46 KB from the LMDB, # and this pool is a spinning-disk mirror shared with a syncing monerod: a COLD # request measured 68 SECONDS, while the two immediately after it took 0.87s and # 0.012s. A short timeout here does not detect a slow explorer, it manufactures # a false DOWN every time the page cache has gone cold between runs. body=$(curl -s --max-time 90 -w '\n%{http_code}' "${URL}/" 2>/dev/null) code=$(printf '%s' "$body" | tail -1) if [ -z "$code" ] || [ "$code" = "000" ]; then report "down" "xmrblocks not responding" exit 1 fi if [ "$code" != "200" ]; then report "down" "xmrblocks HTTP ${code}" exit 1 fi # A 200 that is not the explorer is still a failure. The index page always # carries the project name in its title. if ! printf '%s' "$body" | grep -qi "monero"; then report "down" "xmrblocks served 200 but not an explorer page (templates missing?)" exit 1 fi report "up" "OK" exit 0