66 lines
2.4 KiB
Text
66 lines
2.4 KiB
Text
|
|
#!/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, <title>Navidrome</title>, 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
|