#!/bin/bash # Navidrome health check — managed by Ansible (roles/navidrome) # # The exit code is the answer and systemd keeps it: # systemctl is-failed {{ navidrome_healthcheck_service_name }}.service # Reporting anywhere else is optional and generic. # # /app/ rather than /ping, established by testing against 0.64.0 on the box: # # /ping 200, Content-Type text/plain, body is a single "." - it # proves something is listening and nothing more. # /rest/ping.view identifies itself ("type":"navidrome") but logs TWO # warning lines per call. At one call per 5 minutes that is # ~576 spurious warnings a day, which is how you train # yourself to ignore the warning level. # /app/ 200, 2.8 KB, Navidrome, and SILENT. # # So /app/ is the only one that proves it is really Navidrome serving its real # UI without polluting the journal. Same reasoning as the xmrblocks check, # which fetches a real page because a missing templates dir serves 200s of # nothing. URL="${NAVIDROME_URL:-http://127.0.0.1:{{ navidrome_port }}}" 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 } # 30s: Navidrome answers /ping in milliseconds normally, but this box has one # core and a library scan will happily eat it. A tight timeout here would # manufacture false DOWNs every time a scan runs. body=$(curl -s --max-time 30 -w '\n%{http_code}' "${URL}/app/" 2>/dev/null) code=$(printf '%s' "$body" | tail -1) if [ -z "$code" ] || [ "$code" = "000" ]; then report "down" "navidrome not responding" exit 1 fi if [ "$code" != "200" ]; then report "down" "navidrome HTTP ${code}" exit 1 fi if ! printf '%s' "$body" | grep -qi "navidrome"; then report "down" "navidrome served 200 but not its own UI (something else on the port?)" exit 1 fi report "up" "OK" exit 0