added new scripts

This commit is contained in:
DeSqBlocki
2026-09-13 10:08:10 +02:00
parent b07b7e901f
commit 46b78816b9
17 changed files with 3391 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
# /etc/check_mk/adguard.conf
ADGUARD_URL="http://127.0.0.1:80"
ADGUARD_USER="checkmk"
ADGUARD_PASSWORD="CHANGE_ME"
CHECK_UPDATES="yes"
# If protection gets disabled intentionally, set this to "no".
ALERT_PROTECTION_DISABLED="yes"
+347
View File
@@ -0,0 +1,347 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_adguard
set -u
CONFIG="/etc/check_mk/adguard.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Home\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
ADGUARD_URL="${ADGUARD_URL:-http://127.0.0.1:3000}"
ADGUARD_USER="${ADGUARD_USER:-}"
ADGUARD_PASSWORD="${ADGUARD_PASSWORD:-}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
ALERT_PROTECTION_DISABLED="${ALERT_PROTECTION_DISABLED:-yes}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Home\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Home\" - jq is not installed"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--fail
--connect-timeout 3
--max-time 10
)
AUTH_OPTS=()
if [[ -n "$ADGUARD_USER" ]]; then
AUTH_OPTS=(
--user "${ADGUARD_USER}:${ADGUARD_PASSWORD}"
)
fi
#
# ---------------------------------------------------------------------------
# AdGuard status / version
# ---------------------------------------------------------------------------
#
STATUS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_OPTS[@]}" \
"${ADGUARD_URL%/}/control/status" \
2>/dev/null
)"
STATUS_RC=$?
if [[ $STATUS_RC -ne 0 || -z "$STATUS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"AdGuard Home\" - API unavailable or authentication failed at ${ADGUARD_URL}"
exit 0
fi
if ! printf '%s' "$STATUS_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Home\" - Status API returned unexpected data"
exit 0
fi
VERSION="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.version // empty'
)"
RUNNING="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.running // false'
)"
PROTECTION_ENABLED="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.protection_enabled // false'
)"
DNS_PORT="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.dns_port // 53'
)"
DNS_ADDRESSES="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '
(.dns_addresses // [])
| join(", ")
'
)"
if [[ "$RUNNING" != "true" ]]; then
printf '%s\n' \
"${CRIT} \"AdGuard Home\" - API reachable but DNS service reports not running"
else
if [[ -n "$VERSION" ]]; then
printf '%s\n' \
"${OK} \"AdGuard Home\" - API reachable, DNS running, version ${VERSION}, port ${DNS_PORT}"
else
printf '%s\n' \
"${OK} \"AdGuard Home\" - API reachable, DNS running, port ${DNS_PORT}"
fi
fi
#
# ---------------------------------------------------------------------------
# Protection state
# ---------------------------------------------------------------------------
#
if [[ "$PROTECTION_ENABLED" == "true" ]]; then
printf '%s\n' \
"${OK} \"AdGuard Protection\" - Protection enabled"
else
if [[ "$ALERT_PROTECTION_DISABLED" == "yes" ]]; then
printf '%s\n' \
"${WARN} \"AdGuard Protection\" - Protection disabled"
else
printf '%s\n' \
"${OK} \"AdGuard Protection\" - Protection disabled"
fi
fi
#
# ---------------------------------------------------------------------------
# Statistics
# ---------------------------------------------------------------------------
#
STATS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_OPTS[@]}" \
"${ADGUARD_URL%/}/control/stats" \
2>/dev/null
)"
STATS_RC=$?
if [[ $STATS_RC -ne 0 || -z "$STATS_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Statistics\" - Unable to retrieve DNS statistics"
elif ! printf '%s' "$STATS_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Statistics\" - Statistics API returned unexpected data"
else
DNS_QUERIES="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.num_dns_queries // 0'
)"
BLOCKED="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.num_blocked_filtering // 0'
)"
SAFE_BROWSING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.num_replaced_safebrowsing // 0'
)"
SAFE_SEARCH="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.num_replaced_safesearch // 0'
)"
PARENTAL="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.num_replaced_parental // 0'
)"
AVG_TIME="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.avg_processing_time // 0'
)"
[[ "$DNS_QUERIES" =~ ^[0-9]+$ ]] || DNS_QUERIES=0
[[ "$BLOCKED" =~ ^[0-9]+$ ]] || BLOCKED=0
[[ "$SAFE_BROWSING" =~ ^[0-9]+$ ]] || SAFE_BROWSING=0
[[ "$SAFE_SEARCH" =~ ^[0-9]+$ ]] || SAFE_SEARCH=0
[[ "$PARENTAL" =~ ^[0-9]+$ ]] || PARENTAL=0
[[ "$AVG_TIME" =~ ^[0-9]+([.][0-9]+)?$ ]] || AVG_TIME=0
BLOCK_PERCENT="$(
awk \
-v blocked="$BLOCKED" \
-v total="$DNS_QUERIES" \
'BEGIN {
if (total > 0) {
printf "%.2f", (blocked / total) * 100
} else {
printf "0.00"
}
}'
)"
#
# avg_processing_time is reported in seconds.
#
AVG_TIME_MS="$(
awk \
-v seconds="$AVG_TIME" \
'BEGIN {
printf "%.3f", seconds * 1000
}'
)"
printf '%s\n' \
"${OK} \"AdGuard Statistics\" queries=${DNS_QUERIES};;;0|blocked=${BLOCKED};;;0|blocked_percent=${BLOCK_PERCENT}%;;;0;100|avg_processing_time=${AVG_TIME_MS}ms;;;0 ${DNS_QUERIES} queries, ${BLOCKED} blocked (${BLOCK_PERCENT}%), average processing ${AVG_TIME_MS} ms"
fi
#
# ---------------------------------------------------------------------------
# AdGuard update check
# ---------------------------------------------------------------------------
#
# AdGuard Home provides its own update-information endpoint.
# This is preferable to independently scraping GitHub because it follows
# AdGuard's own release/update logic.
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
VERSION_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_OPTS[@]}" \
-X POST \
-H "Content-Type: application/json" \
-d '{"recheck_now":true}' \
"${ADGUARD_URL%/}/control/version.json" \
2>/dev/null
)"
VERSION_RC=$?
if [[ $VERSION_RC -ne 0 || -z "$VERSION_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Update\" - Installed ${VERSION:-unknown}, unable to retrieve update information"
elif ! printf '%s' "$VERSION_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"AdGuard Update\" - Update API returned unexpected data"
else
UPDATE_DISABLED="$(
printf '%s' "$VERSION_RESPONSE" |
jq -r '.disabled // false'
)"
NEW_VERSION="$(
printf '%s' "$VERSION_RESPONSE" |
jq -r '.new_version // empty'
)"
NEW_VERSION="${NEW_VERSION#v}"
INSTALLED_VERSION="${VERSION#v}"
if [[ "$UPDATE_DISABLED" == "true" ]]; then
printf '%s\n' \
"${OK} \"AdGuard Update\" - Update checking disabled by AdGuard Home, installed ${INSTALLED_VERSION:-unknown}"
elif [[ -z "$NEW_VERSION" ]]; then
printf '%s\n' \
"${OK} \"AdGuard Update\" - Current: installed ${INSTALLED_VERSION:-unknown}"
elif [[ -z "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${WARN} \"AdGuard Update\" - New version ${NEW_VERSION} available, installed version unknown"
elif [[ "$NEW_VERSION" == "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${OK} \"AdGuard Update\" - Current: installed ${INSTALLED_VERSION}"
else
printf '%s\n' \
"${WARN} \"AdGuard Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${NEW_VERSION}"
fi
fi
fi
exit 0
+709
View File
@@ -0,0 +1,709 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_crafty
set -u
CONFIG="/etc/check_mk/crafty.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
CRAFTY_URL="${CRAFTY_URL:-https://127.0.0.1:8443}"
CRAFTY_USER="${CRAFTY_USER:-}"
CRAFTY_PASSWORD="${CRAFTY_PASSWORD:-}"
CRAFTY_INSECURE="${CRAFTY_INSECURE:-yes}"
IGNORE_HIDDEN_SERVERS="${IGNORE_HIDDEN_SERVERS:-yes}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
CRAFTY_RELEASE_API="${CRAFTY_RELEASE_API:-https://gitlab.com/api/v4/projects/34675721/releases/permalink/latest}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - jq is not installed"
exit 0
fi
if [[ -z "$CRAFTY_USER" || -z "$CRAFTY_PASSWORD" ]]; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - CRAFTY_USER or CRAFTY_PASSWORD is not configured"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--connect-timeout 3
--max-time 10
)
if [[ "$CRAFTY_INSECURE" == "yes" ]]; then
CURL_OPTS+=(--insecure)
fi
#
# ---------------------------------------------------------------------------
# Login
# ---------------------------------------------------------------------------
#
LOGIN_PAYLOAD="$(
jq -n \
--arg username "$CRAFTY_USER" \
--arg password "$CRAFTY_PASSWORD" \
'{
username: $username,
password: $password
}'
)"
LOGIN_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-X POST \
-H "Content-Type: application/json" \
-d "$LOGIN_PAYLOAD" \
"${CRAFTY_URL%/}/api/v2/auth/login" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$LOGIN_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Unable to reach Crafty login API at ${CRAFTY_URL}"
exit 0
fi
if ! printf '%s' "$LOGIN_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Login API returned invalid JSON"
exit 0
fi
LOGIN_STATUS="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.status // empty'
)"
TOKEN="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.data.token // empty'
)"
if [[ "$LOGIN_STATUS" != "ok" || -z "$TOKEN" ]]; then
LOGIN_ERROR="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.error_data // .error // "authentication failed"'
)"
printf '%s\n' \
"${CRIT} \"Crafty\" - Authentication failed: ${LOGIN_ERROR}"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Server inventory
# ---------------------------------------------------------------------------
#
SERVERS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/api/v2/servers" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory request failed, curl exit code ${CURL_RC}"
exit 0
fi
if [[ -z "$SERVERS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory API returned an empty response"
exit 0
fi
if ! printf '%s' "$SERVERS_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Server inventory returned invalid JSON"
exit 0
fi
SERVERS_STATUS="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.status // empty'
)"
if [[ "$SERVERS_STATUS" != "ok" ]]; then
SERVER_ERROR="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.error_data // .error // "unknown API error"'
)"
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory API error: ${SERVER_ERROR}"
exit 0
fi
DATA_TYPE="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.data | type'
)"
if [[ "$DATA_TYPE" != "array" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Server inventory returned unexpected data type: ${DATA_TYPE}"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Server counts
# ---------------------------------------------------------------------------
#
TOTAL_CONFIGURED="$(
printf '%s' "$SERVERS_RESPONSE" |
jq '.data | length'
)"
if [[ "$IGNORE_HIDDEN_SERVERS" == "yes" ]]; then
SERVER_COUNT="$(
printf '%s' "$SERVERS_RESPONSE" |
jq '[.data[] | select(.show_status != false)] | length'
)"
else
SERVER_COUNT="$TOTAL_CONFIGURED"
fi
#
# ---------------------------------------------------------------------------
# Crafty installed version via /metrics
# ---------------------------------------------------------------------------
#
METRICS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/metrics" \
2>/dev/null
)"
METRICS_RC=$?
INSTALLED_VERSION=""
if [[ $METRICS_RC -eq 0 && -n "$METRICS_RESPONSE" ]]; then
INSTALLED_VERSION="$(
printf '%s\n' "$METRICS_RESPONSE" |
grep -m1 '^Crafty_Controller_info{' |
sed -n 's/.*version="\([^"]*\)".*/\1/p' |
tr -d '[:space:]'
)"
fi
#
# ---------------------------------------------------------------------------
# Overall Crafty service
# ---------------------------------------------------------------------------
#
if [[ -n "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Crafty\" servers=${SERVER_COUNT};;;0 API reachable and authenticated - version ${INSTALLED_VERSION}, ${SERVER_COUNT}/${TOTAL_CONFIGURED} servers monitored"
else
printf '%s\n' \
"${OK} \"Crafty\" servers=${SERVER_COUNT};;;0 API reachable and authenticated - ${SERVER_COUNT}/${TOTAL_CONFIGURED} servers monitored"
fi
#
# ---------------------------------------------------------------------------
# Crafty update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
if [[ -z "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to determine installed Crafty version from /metrics"
else
RELEASE_RESPONSE="$(
curl \
--silent \
--show-error \
--location \
--fail \
--connect-timeout 3 \
--max-time 10 \
-H "User-Agent: checkmk-crafty-local-check" \
"$CRAFTY_RELEASE_API" \
2>/dev/null
)"
RELEASE_RC=$?
if [[ $RELEASE_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Installed ${INSTALLED_VERSION}, unable to query GitLab release API"
elif ! printf '%s' "$RELEASE_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - GitLab release API returned invalid JSON"
else
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty'
)"
LATEST_VERSION="${LATEST_VERSION#v}"
if [[ -z "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to determine latest Crafty release"
elif [[ ! "$INSTALLED_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to parse installed version ${INSTALLED_VERSION}"
elif [[ ! "$LATEST_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to parse latest version ${LATEST_VERSION}"
else
NEWEST="$(
printf '%s\n%s\n' \
"$INSTALLED_VERSION" \
"$LATEST_VERSION" |
sort -V |
tail -n 1
)"
if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Crafty Update\" - Current: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
elif [[ "$NEWEST" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${WARN} \"Crafty Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
else
printf '%s\n' \
"${OK} \"Crafty Update\" - Installed ${INSTALLED_VERSION} is newer than latest stable ${LATEST_VERSION}"
fi
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Individual Minecraft servers
# ---------------------------------------------------------------------------
#
while IFS= read -r SERVER; do
SERVER_ID="$(
printf '%s' "$SERVER" |
jq -r '.server_id // empty'
)"
SERVER_NAME="$(
printf '%s' "$SERVER" |
jq -r '.server_name // "Unknown"'
)"
SERVER_PORT="$(
printf '%s' "$SERVER" |
jq -r '.server_port // 0'
)"
AUTO_START="$(
printf '%s' "$SERVER" |
jq -r '.auto_start // false'
)"
CRASH_DETECTION="$(
printf '%s' "$SERVER" |
jq -r '.crash_detection // false'
)"
COUNT_PLAYERS="$(
printf '%s' "$SERVER" |
jq -r '.count_players // false'
)"
SHOW_STATUS="$(
printf '%s' "$SERVER" |
jq -r '.show_status // true'
)"
if [[ "$IGNORE_HIDDEN_SERVERS" == "yes" && "$SHOW_STATUS" == "false" ]]; then
continue
fi
SERVER_NAME="${SERVER_NAME//\"/\'}"
if [[ -z "$SERVER_ID" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Server entry does not contain a server ID"
continue
fi
#
# -----------------------------------------------------------------------
# Runtime statistics
# -----------------------------------------------------------------------
#
STATS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/api/v2/servers/${SERVER_ID}/stats" \
2>/dev/null
)"
STATS_RC=$?
if [[ $STATS_RC -ne 0 || -z "$STATS_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Unable to retrieve Crafty server statistics"
continue
fi
if ! printf '%s' "$STATS_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Statistics API returned invalid JSON"
continue
fi
STATS_STATUS="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.status // empty'
)"
if [[ "$STATS_STATUS" != "ok" ]]; then
STATS_ERROR="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.error_data // .error // "unknown API error"'
)"
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Crafty statistics API error: ${STATS_ERROR}"
continue
fi
#
# -----------------------------------------------------------------------
# Runtime values
# -----------------------------------------------------------------------
#
RUNNING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.running // false'
)"
CRASHED="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.crashed // false'
)"
UPDATING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.updating // false'
)"
WAITING_START="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.waiting_start // false'
)"
IMPORTING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.importing // false'
)"
FIRST_RUN="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.first_run // false'
)"
CPU="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.cpu // 0'
)"
MEMORY="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.mem // 0'
)"
MEMORY_PERCENT="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.mem_percent // 0'
)"
PLAYERS_ONLINE="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.online | type) == "number"
then .data.online
else 0
end
'
)"
PLAYERS_MAX="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.max | type) == "number"
then .data.max
else 0
end
'
)"
WORLD_NAME="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.world_name // "") == ""
then "unknown"
else .data.world_name
end
'
)"
WORLD_SIZE="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.world_size // "") == ""
then "unknown"
else .data.world_size
end
'
)"
MC_VERSION="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (
.data.version == false or
.data.version == null or
.data.version == ""
)
then ""
else (.data.version | tostring)
end
'
)"
#
# -----------------------------------------------------------------------
# Sanitize performance values
# -----------------------------------------------------------------------
#
if ! [[ "$CPU" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
CPU=0
fi
if ! [[ "$MEMORY" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
MEMORY=0
fi
if ! [[ "$MEMORY_PERCENT" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
MEMORY_PERCENT=0
fi
if ! [[ "$PLAYERS_ONLINE" =~ ^[0-9]+$ ]]; then
PLAYERS_ONLINE=0
fi
if ! [[ "$PLAYERS_MAX" =~ ^[0-9]+$ ]]; then
PLAYERS_MAX=0
fi
#
# -----------------------------------------------------------------------
# Determine CheckMK state
# -----------------------------------------------------------------------
#
STATE=$OK
STATUS_TEXT="Stopped"
if [[ "$CRASHED" == "true" ]]; then
STATE=$CRIT
STATUS_TEXT="Crashed"
elif [[ "$UPDATING" == "true" ]]; then
STATUS_TEXT="Updating"
elif [[ "$IMPORTING" == "true" ]]; then
STATUS_TEXT="Importing"
elif [[ "$WAITING_START" == "true" ]]; then
STATUS_TEXT="Waiting to start"
elif [[ "$RUNNING" == "true" ]]; then
STATUS_TEXT="Running"
fi
#
# -----------------------------------------------------------------------
# Performance data
# -----------------------------------------------------------------------
#
PERFDATA="cpu=${CPU}%;;;0;100|memory=${MEMORY};;;0|memory_percent=${MEMORY_PERCENT}%;;;0;100"
if [[ "$COUNT_PLAYERS" == "true" ]]; then
if [[ "$PLAYERS_MAX" -gt 0 ]]; then
PERFDATA="${PERFDATA}|players=${PLAYERS_ONLINE};;;0;${PLAYERS_MAX}"
else
PERFDATA="${PERFDATA}|players=${PLAYERS_ONLINE};;;0"
fi
fi
#
# -----------------------------------------------------------------------
# Human-readable output
# -----------------------------------------------------------------------
#
DETAILS="$STATUS_TEXT"
if [[ "$RUNNING" == "true" ]]; then
if [[ "$COUNT_PLAYERS" == "true" ]]; then
if [[ "$PLAYERS_MAX" -gt 0 ]]; then
DETAILS="${DETAILS} - players ${PLAYERS_ONLINE}/${PLAYERS_MAX}"
else
DETAILS="${DETAILS} - players ${PLAYERS_ONLINE}"
fi
fi
if [[ -n "$MC_VERSION" ]]; then
DETAILS="${DETAILS}, version ${MC_VERSION}"
fi
DETAILS="${DETAILS}, CPU ${CPU}%, memory ${MEMORY_PERCENT}%"
fi
if [[ "$WORLD_NAME" != "unknown" ]]; then
DETAILS="${DETAILS}, world ${WORLD_NAME}"
fi
if [[ "$WORLD_SIZE" != "unknown" ]]; then
DETAILS="${DETAILS} (${WORLD_SIZE})"
fi
DETAILS="${DETAILS}, port ${SERVER_PORT}"
if [[ "$AUTO_START" == "true" ]]; then
DETAILS="${DETAILS}, auto-start enabled"
fi
if [[ "$CRASH_DETECTION" == "true" ]]; then
DETAILS="${DETAILS}, crash detection enabled"
fi
if [[ "$FIRST_RUN" == "true" ]]; then
DETAILS="${DETAILS}, first-run flag set"
fi
printf '%s\n' \
"${STATE} \"Minecraft ${SERVER_NAME}\" ${PERFDATA} ${DETAILS}"
done < <(
printf '%s' "$SERVERS_RESPONSE" |
jq -c '.data[]'
)
exit 0
+190
View File
@@ -0,0 +1,190 @@
#!/bin/bash
set -u
CONFIG="/etc/check_mk/gitea.conf"
#
# CheckMK states
#
OK=0
WARN=1
CRIT=2
UNKNOWN=3
if [[ ! -r "$CONFIG" ]]; then
echo "${UNKNOWN} \"Gitea\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
#
# Defaults
#
GITEA_URL="${GITEA_URL:-http://127.0.0.1:3000}"
GITEA_TOKEN="${GITEA_TOKEN:-}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
GITEA_RELEASE_API="${GITEA_RELEASE_API:-https://api.github.com/repos/go-gitea/gitea/releases/latest}"
#
# Requirements
#
if ! command -v curl >/dev/null 2>&1; then
echo "${UNKNOWN} \"Gitea\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
echo "${UNKNOWN} \"Gitea\" - jq is not installed"
exit 0
fi
#
# curl options
#
CURL_OPTS=(
--silent
--show-error
--fail
--connect-timeout 3
--max-time 8
)
#
# Gitea authentication
#
AUTH_ARGS=()
if [[ -n "$GITEA_TOKEN" ]]; then
AUTH_ARGS=(
--header "Authorization: token ${GITEA_TOKEN}"
)
fi
#
# ---------------------------------------------------------------------------
# Gitea health / version
# ---------------------------------------------------------------------------
#
VERSION_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_ARGS[@]}" \
"${GITEA_URL%/}/api/v1/version" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$VERSION_RESPONSE" ]]; then
echo "${CRIT} \"Gitea\" - API unavailable at ${GITEA_URL}"
exit 0
fi
INSTALLED_VERSION="$(
printf '%s' "$VERSION_RESPONSE" |
jq -r '.version // empty' 2>/dev/null
)"
if [[ -z "$INSTALLED_VERSION" ]]; then
echo "${CRIT} \"Gitea\" - API responded but no version was returned"
exit 0
fi
echo "${OK} \"Gitea\" - API reachable, version ${INSTALLED_VERSION}"
#
# ---------------------------------------------------------------------------
# Update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" != "yes" ]]; then
echo "${OK} \"Gitea Update\" - Update check disabled, installed ${INSTALLED_VERSION}"
exit 0
fi
RELEASE_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
--header "Accept: application/vnd.github+json" \
--header "User-Agent: checkmk-gitea-local-check" \
"$GITEA_RELEASE_API" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
echo "${UNKNOWN} \"Gitea Update\" - Installed ${INSTALLED_VERSION}, unable to query upstream release"
exit 0
fi
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty' 2>/dev/null |
sed 's/^v//'
)"
if [[ -z "$LATEST_VERSION" ]]; then
echo "${UNKNOWN} \"Gitea Update\" - Installed ${INSTALLED_VERSION}, upstream returned no release version"
exit 0
fi
#
# Remove common suffixes that may appear in Gitea's version response.
#
# Examples:
# 1.27.2
# 1.27.2+gitea
# 1.27.2 built with GNU Make
#
INSTALLED_CLEAN="$(
printf '%s' "$INSTALLED_VERSION" |
grep -oE '^[0-9]+\.[0-9]+\.[0-9]+' |
head -n1
)"
LATEST_CLEAN="$(
printf '%s' "$LATEST_VERSION" |
grep -oE '^[0-9]+\.[0-9]+\.[0-9]+' |
head -n1
)"
if [[ -z "$INSTALLED_CLEAN" || -z "$LATEST_CLEAN" ]]; then
echo "${UNKNOWN} \"Gitea Update\" - Unable to compare installed=${INSTALLED_VERSION} latest=${LATEST_VERSION}"
exit 0
fi
#
# sort -V performs semantic-ish version ordering suitable for Gitea's
# major.minor.patch release numbers.
#
NEWEST="$(
printf '%s\n%s\n' "$INSTALLED_CLEAN" "$LATEST_CLEAN" |
sort -V |
tail -n1
)"
if [[ "$INSTALLED_CLEAN" == "$LATEST_CLEAN" ]]; then
echo "${OK} \"Gitea Update\" - Current version ${INSTALLED_CLEAN}"
elif [[ "$NEWEST" == "$LATEST_CLEAN" ]]; then
echo "${WARN} \"Gitea Update\" - Update available: installed ${INSTALLED_CLEAN}, latest ${LATEST_CLEAN}"
else
#
# Installed version newer than upstream latest.
# This can happen with prerelease/dev builds.
#
echo "${OK} \"Gitea Update\" - Installed ${INSTALLED_CLEAN} is newer than upstream stable ${LATEST_CLEAN}"
fi
exit 0
+466
View File
@@ -0,0 +1,466 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_mail_archiver
set -u
CONFIG="/etc/check_mk/mail_archiver.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
MAIL_ARCHIVER_URL="${MAIL_ARCHIVER_URL:-http://127.0.0.1:5000}"
MAIL_ARCHIVER_TOKEN="${MAIL_ARCHIVER_TOKEN:-}"
WARN_SYNC_AGE="${WARN_SYNC_AGE:-3600}"
CRIT_SYNC_AGE="${CRIT_SYNC_AGE:-7200}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
MAIL_ARCHIVER_RELEASE_API="${MAIL_ARCHIVER_RELEASE_API:-https://api.github.com/repos/s1t5/mail-archiver/releases/latest}"
VERSION_FILE="${VERSION_FILE:-/root/.mail-archiver}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - jq is not installed"
exit 0
fi
if ! command -v date >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - date is not available"
exit 0
fi
if [[ -z "$MAIL_ARCHIVER_TOKEN" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - MAIL_ARCHIVER_TOKEN is not configured"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Validate thresholds
# ---------------------------------------------------------------------------
#
if ! [[ "$WARN_SYNC_AGE" =~ ^[0-9]+$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - WARN_SYNC_AGE must be an integer"
exit 0
fi
if ! [[ "$CRIT_SYNC_AGE" =~ ^[0-9]+$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - CRIT_SYNC_AGE must be an integer"
exit 0
fi
if [[ "$CRIT_SYNC_AGE" -le "$WARN_SYNC_AGE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - CRIT_SYNC_AGE must be greater than WARN_SYNC_AGE"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--fail
--connect-timeout 3
--max-time 10
)
AUTH_HEADER="Authorization: Bearer ${MAIL_ARCHIVER_TOKEN}"
#
# ---------------------------------------------------------------------------
# Accounts API / application health
# ---------------------------------------------------------------------------
#
ACCOUNTS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "$AUTH_HEADER" \
"${MAIL_ARCHIVER_URL%/}/api/v1/accounts" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$ACCOUNTS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Mail Archiver\" - API unavailable or authentication failed at ${MAIL_ARCHIVER_URL}"
exit 0
fi
if ! printf '%s' "$ACCOUNTS_RESPONSE" |
jq -e 'type == "array"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver\" - Accounts API returned unexpected data"
exit 0
fi
ACCOUNT_COUNT="$(
printf '%s' "$ACCOUNTS_RESPONSE" |
jq 'length'
)"
ENABLED_COUNT="$(
printf '%s' "$ACCOUNTS_RESPONSE" |
jq '[.[] | select(.isEnabled == true)] | length'
)"
DISABLED_COUNT=$((ACCOUNT_COUNT - ENABLED_COUNT))
printf '%s\n' \
"${OK} \"Mail Archiver\" accounts=${ACCOUNT_COUNT};;;0|enabled=${ENABLED_COUNT};;;0|disabled=${DISABLED_COUNT};;;0 API reachable and authenticated - ${ENABLED_COUNT}/${ACCOUNT_COUNT} accounts enabled"
#
# ---------------------------------------------------------------------------
# Archive statistics
# ---------------------------------------------------------------------------
#
STATS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "$AUTH_HEADER" \
"${MAIL_ARCHIVER_URL%/}/api/v1/stats" \
2>/dev/null
)"
STATS_RC=$?
if [[ $STATS_RC -ne 0 || -z "$STATS_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archive Statistics\" - Unable to retrieve archive statistics"
elif ! printf '%s' "$STATS_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"Mail Archive Statistics\" - Statistics API returned unexpected data"
else
EMAILS="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.emails // 0'
)"
STATS_ACCOUNTS="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.accounts // 0'
)"
ATTACHMENTS="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.attachments // 0'
)"
DATABASE_MB="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.databaseSizeInMB // "0"'
)"
[[ "$EMAILS" =~ ^[0-9]+$ ]] || EMAILS=0
[[ "$STATS_ACCOUNTS" =~ ^[0-9]+$ ]] || STATS_ACCOUNTS=0
[[ "$ATTACHMENTS" =~ ^[0-9]+$ ]] || ATTACHMENTS=0
[[ "$DATABASE_MB" =~ ^[0-9]+([.][0-9]+)?$ ]] || DATABASE_MB=0
printf '%s\n' \
"${OK} \"Mail Archive Statistics\" emails=${EMAILS};;;0|accounts=${STATS_ACCOUNTS};;;0|attachments=${ATTACHMENTS};;;0|database_size=${DATABASE_MB}MB;;;0 ${EMAILS} emails, ${STATS_ACCOUNTS} accounts, ${ATTACHMENTS} attachments, database ${DATABASE_MB} MB"
fi
#
# ---------------------------------------------------------------------------
# Individual account sync state
# ---------------------------------------------------------------------------
#
# Mail-Archiver returns lastSync values such as:
#
# 2026-09-13T07:33:35.199543
#
# These represent UTC, but do not contain a timezone suffix.
#
# Therefore we explicitly parse them with TZ=UTC. Once converted to Unix
# epoch seconds, comparisons are timezone-independent and automatically safe
# across CET/CEST daylight-saving changes.
#
NOW_EPOCH="$(date +%s)"
while IFS= read -r ACCOUNT; do
ACCOUNT_NAME="$(
printf '%s' "$ACCOUNT" |
jq -r '.name // empty'
)"
EMAIL_ADDRESS="$(
printf '%s' "$ACCOUNT" |
jq -r '.emailAddress // empty'
)"
PROVIDER="$(
printf '%s' "$ACCOUNT" |
jq -r '.provider // "Unknown"'
)"
ENABLED="$(
printf '%s' "$ACCOUNT" |
jq -r '.isEnabled // false'
)"
LAST_SYNC="$(
printf '%s' "$ACCOUNT" |
jq -r '.lastSync // empty'
)"
#
# Prefer friendly account name, then email address.
#
if [[ -n "$ACCOUNT_NAME" ]]; then
SERVICE_NAME="$ACCOUNT_NAME"
elif [[ -n "$EMAIL_ADDRESS" ]]; then
SERVICE_NAME="$EMAIL_ADDRESS"
else
SERVICE_NAME="Unknown"
fi
SERVICE_NAME="${SERVICE_NAME//\"/\'}"
#
# Disabled accounts are treated as intentional.
#
if [[ "$ENABLED" != "true" ]]; then
printf '%s\n' \
"${OK} \"Mail Archive ${SERVICE_NAME}\" - Disabled, provider ${PROVIDER}"
continue
fi
#
# Enabled account without a sync timestamp.
#
if [[ -z "$LAST_SYNC" || "$LAST_SYNC" == "null" ]]; then
printf '%s\n' \
"${WARN} \"Mail Archive ${SERVICE_NAME}\" - Enabled but no successful sync timestamp is available, provider ${PROVIDER}"
continue
fi
#
# Mail-Archiver supplies UTC without an explicit Z/+00:00 suffix.
# Force UTC interpretation rather than allowing GNU date to interpret
# the timestamp using the host's local timezone.
#
LAST_SYNC_EPOCH="$(
TZ=UTC date -d "$LAST_SYNC" +%s 2>/dev/null || true
)"
if [[ -z "$LAST_SYNC_EPOCH" || ! "$LAST_SYNC_EPOCH" =~ ^[0-9]+$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archive ${SERVICE_NAME}\" - Unable to parse lastSync '${LAST_SYNC}'"
continue
fi
SYNC_AGE=$((NOW_EPOCH - LAST_SYNC_EPOCH))
#
# Protect against small clock differences between systems.
#
if [[ "$SYNC_AGE" -lt 0 ]]; then
SYNC_AGE=0
fi
DAYS=$((SYNC_AGE / 86400))
HOURS=$(((SYNC_AGE % 86400) / 3600))
MINUTES=$(((SYNC_AGE % 3600) / 60))
if [[ "$DAYS" -gt 0 ]]; then
AGE_TEXT="${DAYS}d ${HOURS}h ${MINUTES}m"
elif [[ "$HOURS" -gt 0 ]]; then
AGE_TEXT="${HOURS}h ${MINUTES}m"
else
AGE_TEXT="${MINUTES}m"
fi
STATE=$OK
if [[ "$SYNC_AGE" -ge "$CRIT_SYNC_AGE" ]]; then
STATE=$CRIT
elif [[ "$SYNC_AGE" -ge "$WARN_SYNC_AGE" ]]; then
STATE=$WARN
fi
printf '%s\n' \
"${STATE} \"Mail Archive ${SERVICE_NAME}\" sync_age=${SYNC_AGE};${WARN_SYNC_AGE};${CRIT_SYNC_AGE};0 Last sync ${AGE_TEXT} ago, provider ${PROVIDER}"
done < <(
printf '%s' "$ACCOUNTS_RESPONSE" |
jq -c '.[]'
)
#
# ---------------------------------------------------------------------------
# Installed version
# ---------------------------------------------------------------------------
#
# Community Scripts stores the deployed Mail-Archiver release version in:
#
# /root/.mail-archiver
#
# This is maintained by the Community Scripts installer/updater and is used
# as the authoritative installed-version source here.
#
INSTALLED_VERSION=""
if [[ -r "$VERSION_FILE" ]]; then
INSTALLED_VERSION="$(
head -n 1 "$VERSION_FILE" |
tr -d '[:space:]'
)"
fi
INSTALLED_VERSION="${INSTALLED_VERSION#v}"
#
# ---------------------------------------------------------------------------
# Mail-Archiver update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
RELEASE_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Accept: application/vnd.github+json" \
-H "User-Agent: checkmk-mail-archiver-local-check" \
"$MAIL_ARCHIVER_RELEASE_API" \
2>/dev/null
)"
RELEASE_RC=$?
if [[ $RELEASE_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
if [[ -n "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Installed ${INSTALLED_VERSION}, unable to query GitHub releases"
else
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Unable to determine installed version or query GitHub releases"
fi
elif ! printf '%s' "$RELEASE_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - GitHub release API returned unexpected data"
else
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty'
)"
LATEST_VERSION="${LATEST_VERSION#v}"
if [[ -z "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Unable to determine latest release"
elif [[ -z "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Latest ${LATEST_VERSION}, but installed version marker ${VERSION_FILE} is missing or unreadable"
elif [[ ! "$INSTALLED_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Unable to parse installed version ${INSTALLED_VERSION}"
elif [[ ! "$LATEST_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Mail Archiver Update\" - Unable to parse latest version ${LATEST_VERSION}"
else
NEWEST="$(
printf '%s\n%s\n' \
"$INSTALLED_VERSION" \
"$LATEST_VERSION" |
sort -V |
tail -n 1
)"
if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Mail Archiver Update\" - Current: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
elif [[ "$NEWEST" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${WARN} \"Mail Archiver Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
else
printf '%s\n' \
"${OK} \"Mail Archiver Update\" - Installed ${INSTALLED_VERSION} is newer than latest ${LATEST_VERSION}"
fi
fi
fi
fi
exit 0
+440
View File
@@ -0,0 +1,440 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_npm
set -u
CONFIG="/etc/check_mk/npm.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Nginx Proxy Manager\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
NPM_URL="${NPM_URL:-http://127.0.0.1:81}"
NPM_IDENTITY="${NPM_IDENTITY:-}"
NPM_SECRET="${NPM_SECRET:-}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
NPM_RELEASE_API="${NPM_RELEASE_API:-https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Nginx Proxy Manager\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Nginx Proxy Manager\" - jq is not installed"
exit 0
fi
if [[ -z "$NPM_IDENTITY" || -z "$NPM_SECRET" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Nginx Proxy Manager\" - NPM_IDENTITY or NPM_SECRET is not configured"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--fail
--connect-timeout 3
--max-time 10
)
#
# ---------------------------------------------------------------------------
# Public API health / installed version
# ---------------------------------------------------------------------------
#
STATUS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${NPM_URL%/}/api/" \
2>/dev/null
)"
STATUS_RC=$?
if [[ $STATUS_RC -ne 0 || -z "$STATUS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Nginx Proxy Manager\" - API unavailable at ${NPM_URL}"
exit 0
fi
if ! printf '%s' "$STATUS_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"Nginx Proxy Manager\" - Public API returned unexpected data"
exit 0
fi
API_STATUS="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.status // empty'
)"
SETUP_COMPLETE="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.setup // false'
)"
VERSION_MAJOR="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.version.major // empty'
)"
VERSION_MINOR="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.version.minor // empty'
)"
VERSION_REVISION="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.version.revision // empty'
)"
INSTALLED_VERSION=""
if [[ -n "$VERSION_MAJOR" && -n "$VERSION_MINOR" && -n "$VERSION_REVISION" ]]; then
INSTALLED_VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}"
fi
if [[ "$API_STATUS" != "OK" ]]; then
printf '%s\n' \
"${CRIT} \"Nginx Proxy Manager\" - API responded with status ${API_STATUS:-unknown}"
exit 0
fi
if [[ "$SETUP_COMPLETE" != "true" ]]; then
printf '%s\n' \
"${WARN} \"Nginx Proxy Manager\" - API reachable but initial setup is incomplete"
else
if [[ -n "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Nginx Proxy Manager\" - API reachable, version ${INSTALLED_VERSION}"
else
printf '%s\n' \
"${OK} \"Nginx Proxy Manager\" - API reachable"
fi
fi
#
# ---------------------------------------------------------------------------
# Update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
RELEASE_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Accept: application/vnd.github+json" \
-H "User-Agent: checkmk-npm-local-check" \
"$NPM_RELEASE_API" \
2>/dev/null
)"
RELEASE_RC=$?
if [[ $RELEASE_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"NPM Update\" - Installed ${INSTALLED_VERSION:-unknown}, unable to query GitHub releases"
elif ! printf '%s' "$RELEASE_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"NPM Update\" - GitHub release API returned unexpected data"
else
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty'
)"
LATEST_VERSION="${LATEST_VERSION#v}"
if [[ -z "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"NPM Update\" - Unable to determine latest release"
elif [[ -z "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"NPM Update\" - Latest ${LATEST_VERSION}, installed version unknown"
else
NEWEST="$(
printf '%s\n%s\n' \
"$INSTALLED_VERSION" \
"$LATEST_VERSION" |
sort -V |
tail -n 1
)"
if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${OK} \"NPM Update\" - Current: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
elif [[ "$NEWEST" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${WARN} \"NPM Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
else
printf '%s\n' \
"${OK} \"NPM Update\" - Installed ${INSTALLED_VERSION} is newer than latest ${LATEST_VERSION}"
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Authentication
# ---------------------------------------------------------------------------
#
LOGIN_PAYLOAD="$(
jq -n \
--arg identity "$NPM_IDENTITY" \
--arg secret "$NPM_SECRET" \
'{
identity: $identity,
secret: $secret
}'
)"
TOKEN_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-X POST \
-H "Content-Type: application/json" \
-d "$LOGIN_PAYLOAD" \
"${NPM_URL%/}/api/tokens" \
2>/dev/null
)"
TOKEN_RC=$?
if [[ $TOKEN_RC -ne 0 || -z "$TOKEN_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"NPM Proxy Hosts\" - API reachable but authentication failed"
exit 0
fi
if ! printf '%s' "$TOKEN_RESPONSE" |
jq -e 'type == "object"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"NPM Proxy Hosts\" - Authentication API returned unexpected data"
exit 0
fi
TOKEN="$(
printf '%s' "$TOKEN_RESPONSE" |
jq -r '.token // empty'
)"
TOKEN_EXPIRES="$(
printf '%s' "$TOKEN_RESPONSE" |
jq -r '.expires // empty'
)"
if [[ -z "$TOKEN" ]]; then
printf '%s\n' \
"${CRIT} \"NPM Proxy Hosts\" - Authentication response did not contain a token"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Proxy host inventory
# ---------------------------------------------------------------------------
#
HOSTS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${NPM_URL%/}/api/nginx/proxy-hosts" \
2>/dev/null
)"
HOSTS_RC=$?
if [[ $HOSTS_RC -ne 0 || -z "$HOSTS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"NPM Proxy Hosts\" - Unable to retrieve proxy hosts"
exit 0
fi
if ! printf '%s' "$HOSTS_RESPONSE" |
jq -e 'type == "array"' >/dev/null 2>&1
then
printf '%s\n' \
"${UNKNOWN} \"NPM Proxy Hosts\" - Proxy host API returned unexpected data"
exit 0
fi
TOTAL_HOSTS="$(
printf '%s' "$HOSTS_RESPONSE" |
jq 'length'
)"
ENABLED_HOSTS="$(
printf '%s' "$HOSTS_RESPONSE" |
jq '[.[] | select(.enabled == true)] | length'
)"
DISABLED_HOSTS="$(
printf '%s' "$HOSTS_RESPONSE" |
jq '[.[] | select(.enabled != true)] | length'
)"
ONLINE_HOSTS="$(
printf '%s' "$HOSTS_RESPONSE" |
jq '
[
.[]
| select(
.enabled == true
and
(.meta.nginx_online == true)
)
]
| length
'
)"
ERROR_HOSTS="$(
printf '%s' "$HOSTS_RESPONSE" |
jq '
[
.[]
| select(
.enabled == true
and
(
.meta.nginx_online != true
or
.meta.nginx_err != null
)
)
]
| length
'
)"
#
# ---------------------------------------------------------------------------
# Broken host details
# ---------------------------------------------------------------------------
#
ERROR_LIST="$(
printf '%s' "$HOSTS_RESPONSE" |
jq -r '
.[]
| select(
.enabled == true
and
(
.meta.nginx_online != true
or
.meta.nginx_err != null
)
)
|
(
(.domain_names | join(","))
+
" -> "
+
(.forward_scheme // "http")
+
"://"
+
(.forward_host // "unknown")
+
":"
+
((.forward_port // 0) | tostring)
+
(
if .meta.nginx_err != null
then " (" + (.meta.nginx_err | tostring) + ")"
else ""
end
)
)
' |
paste -sd ';' -
)"
STATE=$OK
if [[ "$ERROR_HOSTS" -gt 0 ]]; then
STATE=$CRIT
fi
PERFDATA="total=${TOTAL_HOSTS};;;0|enabled=${ENABLED_HOSTS};;;0|disabled=${DISABLED_HOSTS};;;0|online=${ONLINE_HOSTS};;;0|errors=${ERROR_HOSTS};;;0"
DETAILS="${ENABLED_HOSTS}/${TOTAL_HOSTS} enabled, ${ONLINE_HOSTS} online"
if [[ "$DISABLED_HOSTS" -gt 0 ]]; then
DETAILS="${DETAILS}, ${DISABLED_HOSTS} disabled"
fi
if [[ "$ERROR_HOSTS" -gt 0 ]]; then
DETAILS="${DETAILS}, ${ERROR_HOSTS} with nginx errors"
fi
if [[ -n "$ERROR_LIST" ]]; then
DETAILS="${DETAILS}: ${ERROR_LIST}"
fi
printf '%s\n' \
"${STATE} \"NPM Proxy Hosts\" ${PERFDATA} ${DETAILS}"
exit 0
+542
View File
@@ -0,0 +1,542 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_pm2
set -u
CONFIG="/etc/check_mk/pm2.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' "${UNKNOWN} \"PM2\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
PM2_USER="${PM2_USER:-root}"
PM2_HOME="${PM2_HOME:-}"
CHECK_PM2_UPDATES="${CHECK_PM2_UPDATES:-yes}"
CHECK_NODE_UPDATES="${CHECK_NODE_UPDATES:-yes}"
PM2_PACKAGE_URL="${PM2_PACKAGE_URL:-https://registry.npmjs.org/pm2/latest}"
NODE_RELEASES_URL="${NODE_RELEASES_URL:-https://nodejs.org/dist/index.json}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"PM2\" - jq is not installed"
exit 0
fi
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"PM2\" - curl is not installed"
exit 0
fi
if ! id "$PM2_USER" >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"PM2\" - Configured PM2 user ${PM2_USER} does not exist"
exit 0
fi
#
# ---------------------------------------------------------------------------
# User / PM2 environment
# ---------------------------------------------------------------------------
#
USER_HOME="$(
getent passwd "$PM2_USER" |
cut -d: -f6
)"
if [[ -z "$USER_HOME" ]]; then
printf '%s\n' "${UNKNOWN} \"PM2\" - Unable to determine home directory for ${PM2_USER}"
exit 0
fi
if [[ -z "$PM2_HOME" ]]; then
PM2_HOME="${USER_HOME}/.pm2"
fi
#
# ---------------------------------------------------------------------------
# Locate PM2
# ---------------------------------------------------------------------------
#
PM2_BIN=""
for candidate in \
/usr/bin/pm2 \
/usr/local/bin/pm2 \
"${USER_HOME}/.local/bin/pm2"
do
if [[ -x "$candidate" ]]; then
PM2_BIN="$candidate"
break
fi
done
if [[ -z "$PM2_BIN" ]]; then
PM2_BIN="$(command -v pm2 2>/dev/null || true)"
fi
#
# NVM fallback
#
if [[ -z "$PM2_BIN" && -d "${USER_HOME}/.nvm/versions/node" ]]; then
PM2_BIN="$(
find "${USER_HOME}/.nvm/versions/node" \
-mindepth 3 \
-maxdepth 3 \
-type f \
-path '*/bin/pm2' \
-perm -u+x \
2>/dev/null |
sort -V |
tail -n 1
)"
fi
if [[ -z "$PM2_BIN" || ! -x "$PM2_BIN" ]]; then
printf '%s\n' "${UNKNOWN} \"PM2\" - Unable to locate PM2 executable"
exit 0
fi
PM2_BIN_DIR="$(dirname "$PM2_BIN")"
#
# Node used by this PM2 installation.
#
NODE_BIN="${PM2_BIN_DIR}/node"
if [[ ! -x "$NODE_BIN" ]]; then
NODE_BIN="$(command -v node 2>/dev/null || true)"
fi
#
# ---------------------------------------------------------------------------
# Retrieve PM2 process list
# ---------------------------------------------------------------------------
#
if [[ "$PM2_USER" == "root" ]]; then
PM2_JSON="$(
PM2_HOME="$PM2_HOME" \
PATH="${PM2_BIN_DIR}:${PATH}" \
"$PM2_BIN" jlist 2>/dev/null
)"
PM2_RC=$?
else
PM2_JSON="$(
runuser -u "$PM2_USER" -- \
env \
PM2_HOME="$PM2_HOME" \
PATH="${PM2_BIN_DIR}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
"$PM2_BIN" jlist 2>/dev/null
)"
PM2_RC=$?
fi
if [[ $PM2_RC -ne 0 || -z "$PM2_JSON" ]]; then
printf '%s\n' "${CRIT} \"PM2\" - Unable to retrieve PM2 process list for user ${PM2_USER}"
exit 0
fi
if ! printf '%s' "$PM2_JSON" | jq -e 'type == "array"' >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"PM2\" - PM2 returned invalid JSON"
exit 0
fi
PROCESS_COUNT="$(
printf '%s' "$PM2_JSON" |
jq 'length'
)"
if [[ "$PROCESS_COUNT" -eq 0 ]]; then
printf '%s\n' "${WARN} \"PM2\" processes=0 No processes managed by PM2 for user ${PM2_USER}"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Overall PM2 state
# ---------------------------------------------------------------------------
#
ONLINE_COUNT="$(
printf '%s' "$PM2_JSON" |
jq '[.[] | select(.pm2_env.status == "online")] | length'
)"
OFFLINE_COUNT=$((PROCESS_COUNT - ONLINE_COUNT))
if [[ "$OFFLINE_COUNT" -eq 0 ]]; then
printf '%s\n' \
"${OK} \"PM2\" processes=${PROCESS_COUNT};;;0|online=${ONLINE_COUNT};;;0|offline=0;;;0 ${PROCESS_COUNT}/${PROCESS_COUNT} processes online"
else
printf '%s\n' \
"${CRIT} \"PM2\" processes=${PROCESS_COUNT};;;0|online=${ONLINE_COUNT};;;0|offline=${OFFLINE_COUNT};;;0 ${ONLINE_COUNT}/${PROCESS_COUNT} processes online, ${OFFLINE_COUNT} not online"
fi
#
# ---------------------------------------------------------------------------
# PM2 version / update
# ---------------------------------------------------------------------------
#
PM2_VERSION="$(
PATH="${PM2_BIN_DIR}:${PATH}" \
"$PM2_BIN" --version 2>/dev/null |
tail -n 1 |
tr -d '[:space:]'
)"
if [[ "$CHECK_PM2_UPDATES" == "yes" ]]; then
if [[ -z "$PM2_VERSION" ]]; then
printf '%s\n' "${UNKNOWN} \"PM2 Update\" - Unable to determine installed PM2 version"
else
PM2_RELEASE_RESPONSE="$(
curl \
--silent \
--show-error \
--fail \
--connect-timeout 3 \
--max-time 8 \
"$PM2_PACKAGE_URL" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$PM2_RELEASE_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"PM2 Update\" - Installed ${PM2_VERSION}, unable to query npm registry"
elif ! printf '%s' "$PM2_RELEASE_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"PM2 Update\" - npm registry returned invalid JSON"
else
PM2_LATEST="$(
printf '%s' "$PM2_RELEASE_RESPONSE" |
jq -r '.version // empty'
)"
if [[ -z "$PM2_LATEST" ]]; then
printf '%s\n' \
"${UNKNOWN} \"PM2 Update\" - Unable to determine latest PM2 version"
else
NEWEST="$(
printf '%s\n%s\n' \
"$PM2_VERSION" \
"$PM2_LATEST" |
sort -V |
tail -n 1
)"
if [[ "$PM2_VERSION" == "$PM2_LATEST" ]]; then
printf '%s\n' \
"${OK} \"PM2 Update\" - Current: installed ${PM2_VERSION}, latest ${PM2_LATEST}"
elif [[ "$NEWEST" == "$PM2_LATEST" ]]; then
printf '%s\n' \
"${WARN} \"PM2 Update\" - Update available: installed ${PM2_VERSION}, latest ${PM2_LATEST}"
else
printf '%s\n' \
"${OK} \"PM2 Update\" - Installed ${PM2_VERSION} is newer than latest ${PM2_LATEST}"
fi
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Node.js / NVM version
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_NODE_UPDATES" == "yes" ]]; then
if [[ -z "$NODE_BIN" || ! -x "$NODE_BIN" ]]; then
printf '%s\n' "${UNKNOWN} \"Node.js Update\" - Unable to locate Node.js executable"
else
NODE_VERSION="$(
"$NODE_BIN" --version 2>/dev/null |
sed 's/^v//'
)"
if [[ -z "$NODE_VERSION" ]]; then
printf '%s\n' "${UNKNOWN} \"Node.js Update\" - Unable to determine installed Node.js version"
else
NODE_RELEASES="$(
curl \
--silent \
--show-error \
--fail \
--connect-timeout 3 \
--max-time 8 \
"$NODE_RELEASES_URL" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$NODE_RELEASES" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Node.js Update\" - Installed ${NODE_VERSION}, unable to query Node.js releases"
elif ! printf '%s' "$NODE_RELEASES" | jq -e 'type == "array"' >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Node.js Update\" - Node.js release API returned invalid data"
else
INSTALLED_MAJOR="${NODE_VERSION%%.*}"
LATEST_CURRENT="$(
printf '%s' "$NODE_RELEASES" |
jq -r '
[
.[]
| select(.lts == false)
| .version
][0] // empty
' |
sed 's/^v//'
)"
LATEST_LTS="$(
printf '%s' "$NODE_RELEASES" |
jq -r '
[
.[]
| select(.lts != false)
| .version
][0] // empty
' |
sed 's/^v//'
)"
LATEST_SAME_MAJOR="$(
printf '%s' "$NODE_RELEASES" |
jq -r \
--arg prefix "v${INSTALLED_MAJOR}." '
[
.[]
| select(.version | startswith($prefix))
| .version
][0] // empty
' |
sed 's/^v//'
)"
SAME_MAJOR_LTS="$(
printf '%s' "$NODE_RELEASES" |
jq -r \
--arg prefix "v${INSTALLED_MAJOR}." '
[
.[]
| select(.version | startswith($prefix))
| .lts
][0] // false
'
)"
#
# If no releases for the installed major exist in the current
# Node.js release index, consider it unsupported/EOL.
#
if [[ -z "$LATEST_SAME_MAJOR" ]]; then
printf '%s\n' \
"${WARN} \"Node.js Update\" - Installed ${NODE_VERSION} appears unsupported/EOL; latest LTS ${LATEST_LTS}, current ${LATEST_CURRENT}"
elif [[ "$SAME_MAJOR_LTS" == "false" && "$INSTALLED_MAJOR" -lt "${LATEST_CURRENT%%.*}" ]]; then
printf '%s\n' \
"${WARN} \"Node.js Update\" - Installed ${NODE_VERSION} is on a non-LTS release line; latest LTS ${LATEST_LTS}, current ${LATEST_CURRENT}"
elif [[ "$NODE_VERSION" != "$LATEST_SAME_MAJOR" ]]; then
NEWEST="$(
printf '%s\n%s\n' \
"$NODE_VERSION" \
"$LATEST_SAME_MAJOR" |
sort -V |
tail -n 1
)"
if [[ "$NEWEST" == "$LATEST_SAME_MAJOR" ]]; then
printf '%s\n' \
"${WARN} \"Node.js Update\" - Update available in Node ${INSTALLED_MAJOR}.x: installed ${NODE_VERSION}, latest ${LATEST_SAME_MAJOR}; latest LTS ${LATEST_LTS}"
else
printf '%s\n' \
"${OK} \"Node.js Update\" - Installed ${NODE_VERSION}; latest LTS ${LATEST_LTS}, current ${LATEST_CURRENT}"
fi
else
printf '%s\n' \
"${OK} \"Node.js Update\" - Current on Node ${INSTALLED_MAJOR}.x: ${NODE_VERSION}; latest LTS ${LATEST_LTS}, current ${LATEST_CURRENT}"
fi
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Individual PM2 processes
# ---------------------------------------------------------------------------
#
while IFS= read -r PROCESS; do
NAME="$(
printf '%s' "$PROCESS" |
jq -r '.name // "unknown"'
)"
STATUS="$(
printf '%s' "$PROCESS" |
jq -r '.pm2_env.status // "unknown"'
)"
PID="$(
printf '%s' "$PROCESS" |
jq -r '.pid // 0'
)"
RESTARTS="$(
printf '%s' "$PROCESS" |
jq -r '.pm2_env.restart_time // 0'
)"
CRON_RESTART="$(
printf '%s' "$PROCESS" |
jq -r '.pm2_env.cron_restart // empty'
)"
AUTORESTART="$(
printf '%s' "$PROCESS" |
jq -r '.pm2_env.autorestart // true'
)"
CPU="$(
printf '%s' "$PROCESS" |
jq -r '.monit.cpu // 0'
)"
MEMORY_BYTES="$(
printf '%s' "$PROCESS" |
jq -r '.monit.memory // 0'
)"
START_TIME="$(
printf '%s' "$PROCESS" |
jq -r '.pm2_env.pm_uptime // 0'
)"
NAME="${NAME//\"/\'}"
MEMORY_MB="$(
awk -v bytes="$MEMORY_BYTES" \
'BEGIN { printf "%.1f", bytes / 1024 / 1024 }'
)"
NOW_MS=$(( $(date +%s) * 1000 ))
if [[ "$START_TIME" =~ ^[0-9]+$ && "$START_TIME" -gt 0 ]]; then
UPTIME_SECONDS="$(
awk -v now="$NOW_MS" -v start="$START_TIME" \
'BEGIN {
diff = (now - start) / 1000
if (diff < 0) diff = 0
printf "%.0f", diff
}'
)"
else
UPTIME_SECONDS=0
fi
DAYS=$((UPTIME_SECONDS / 86400))
HOURS=$(((UPTIME_SECONDS % 86400) / 3600))
MINUTES=$(((UPTIME_SECONDS % 3600) / 60))
if [[ "$DAYS" -gt 0 ]]; then
UPTIME_TEXT="${DAYS}d ${HOURS}h ${MINUTES}m"
elif [[ "$HOURS" -gt 0 ]]; then
UPTIME_TEXT="${HOURS}h ${MINUTES}m"
else
UPTIME_TEXT="${MINUTES}m"
fi
STATE=$OK
STATE_TEXT="Online"
if [[ "$STATUS" != "online" ]]; then
STATE=$CRIT
STATE_TEXT="Status ${STATUS}"
fi
if [[ -n "$CRON_RESTART" ]]; then
RESTART_INFO="restarts ${RESTARTS}, scheduled restart ${CRON_RESTART}"
else
RESTART_INFO="restarts ${RESTARTS}"
fi
if [[ "$AUTORESTART" == "false" ]]; then
RESTART_INFO="${RESTART_INFO}, autorestart disabled"
fi
PERFDATA="cpu=${CPU}%;;;0;100|memory=${MEMORY_BYTES}B;;;0|restarts=${RESTARTS};;;0|uptime=${UPTIME_SECONDS}s;;;0"
printf '%s\n' \
"${STATE} \"PM2 ${NAME}\" ${PERFDATA} ${STATE_TEXT} - PID ${PID}, uptime ${UPTIME_TEXT}, CPU ${CPU}%, memory ${MEMORY_MB} MiB, ${RESTART_INFO}"
done < <(
printf '%s' "$PM2_JSON" |
jq -c '.[]'
)
exit 0
+423
View File
@@ -0,0 +1,423 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_portainer
set -u
CONFIG="/etc/check_mk/portainer.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
PORTAINER_URL="${PORTAINER_URL:-https://127.0.0.1:9443}"
PORTAINER_TOKEN="${PORTAINER_TOKEN:-}"
PORTAINER_INSECURE="${PORTAINER_INSECURE:-yes}"
ALERT_STOPPED_CONTAINERS="${ALERT_STOPPED_CONTAINERS:-no}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
PORTAINER_RELEASE_API="${PORTAINER_RELEASE_API:-https://api.github.com/repos/portainer/portainer/releases/latest}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - jq is not installed"
exit 0
fi
if ! command -v sort >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - sort is not installed"
exit 0
fi
if [[ -z "$PORTAINER_TOKEN" ]]; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - PORTAINER_TOKEN is not configured"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--connect-timeout 3
--max-time 10
)
if [[ "$PORTAINER_INSECURE" == "yes" ]]; then
CURL_OPTS+=(--insecure)
fi
AUTH_HEADER="X-API-Key: ${PORTAINER_TOKEN}"
#
# ---------------------------------------------------------------------------
# Portainer health / version
# ---------------------------------------------------------------------------
#
STATUS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${PORTAINER_URL%/}/api/status" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$STATUS_RESPONSE" ]]; then
printf '%s\n' "${CRIT} \"Portainer\" - API unavailable at ${PORTAINER_URL}"
exit 0
fi
if ! printf '%s' "$STATUS_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Portainer\" - Status API returned invalid JSON"
exit 0
fi
VERSION="$(
printf '%s' "$STATUS_RESPONSE" |
jq -r '.Version // .version // empty'
)"
if [[ -n "$VERSION" ]]; then
printf '%s\n' "${OK} \"Portainer\" - API reachable, version ${VERSION}"
else
printf '%s\n' "${OK} \"Portainer\" - API reachable"
fi
#
# ---------------------------------------------------------------------------
# Portainer update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
if [[ -z "$VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Installed Portainer version could not be determined"
else
RELEASE_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Accept: application/vnd.github+json" \
-H "User-Agent: checkmk-portainer-local-check" \
"$PORTAINER_RELEASE_API" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Unable to retrieve latest release information"
elif ! printf '%s' "$RELEASE_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Release API returned invalid JSON"
else
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty'
)"
INSTALLED_VERSION="${VERSION#v}"
LATEST_VERSION="${LATEST_VERSION#v}"
if [[ -z "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Latest release version could not be determined"
else
#
# Strip known suffixes before numeric comparison.
#
# Examples:
# 2.36.0
# 2.36.0-sts
# 2.36.0-lts
#
INSTALLED_COMPARE="${INSTALLED_VERSION%%-*}"
LATEST_COMPARE="${LATEST_VERSION%%-*}"
if [[ ! "$INSTALLED_COMPARE" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Unable to parse installed version ${INSTALLED_VERSION}"
elif [[ ! "$LATEST_COMPARE" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Portainer Update\" - Unable to parse latest version ${LATEST_VERSION}"
else
NEWEST="$(
printf '%s\n%s\n' \
"$INSTALLED_COMPARE" \
"$LATEST_COMPARE" |
sort -V |
tail -n 1
)"
if [[ "$INSTALLED_COMPARE" == "$LATEST_COMPARE" ]]; then
printf '%s\n' \
"${OK} \"Portainer Update\" - Current: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
elif [[ "$NEWEST" == "$LATEST_COMPARE" ]]; then
printf '%s\n' \
"${WARN} \"Portainer Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
else
printf '%s\n' \
"${OK} \"Portainer Update\" - Installed ${INSTALLED_VERSION} is newer than latest stable ${LATEST_VERSION}"
fi
fi
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Endpoints
# ---------------------------------------------------------------------------
#
ENDPOINTS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "$AUTH_HEADER" \
"${PORTAINER_URL%/}/api/endpoints" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$ENDPOINTS_RESPONSE" ]]; then
printf '%s\n' "${CRIT} \"Portainer Endpoints\" - Unable to retrieve endpoints"
exit 0
fi
if ! printf '%s' "$ENDPOINTS_RESPONSE" | jq -e 'type == "array"' >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Portainer Endpoints\" - Endpoint API returned unexpected data"
exit 0
fi
ENDPOINT_COUNT="$(
printf '%s' "$ENDPOINTS_RESPONSE" |
jq 'length'
)"
UP_ENDPOINTS=0
DOWN_ENDPOINTS=0
while IFS= read -r ENDPOINT; do
ENDPOINT_ID="$(
printf '%s' "$ENDPOINT" |
jq -r '.Id // .ID // empty'
)"
ENDPOINT_NAME="$(
printf '%s' "$ENDPOINT" |
jq -r '.Name // "Unknown"'
)"
ENDPOINT_STATUS="$(
printf '%s' "$ENDPOINT" |
jq -r '.Status // 0'
)"
ENDPOINT_NAME="${ENDPOINT_NAME//\"/\'}"
#
# Portainer endpoint states:
# 1 = UP
# 2 = DOWN
#
if [[ "$ENDPOINT_STATUS" == "1" ]]; then
UP_ENDPOINTS=$((UP_ENDPOINTS + 1))
printf '%s\n' \
"${OK} \"Portainer Endpoint ${ENDPOINT_NAME}\" - Endpoint is UP"
else
DOWN_ENDPOINTS=$((DOWN_ENDPOINTS + 1))
printf '%s\n' \
"${CRIT} \"Portainer Endpoint ${ENDPOINT_NAME}\" - Endpoint is DOWN, status ${ENDPOINT_STATUS}"
fi
#
# -----------------------------------------------------------------------
# Containers for this endpoint
# -----------------------------------------------------------------------
#
if [[ -z "$ENDPOINT_ID" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Docker Containers ${ENDPOINT_NAME}\" - Endpoint ID missing"
continue
fi
CONTAINERS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "$AUTH_HEADER" \
"${PORTAINER_URL%/}/api/endpoints/${ENDPOINT_ID}/docker/containers/json?all=1" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$CONTAINERS_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Docker Containers ${ENDPOINT_NAME}\" - Unable to retrieve containers"
continue
fi
if ! printf '%s' "$CONTAINERS_RESPONSE" | jq -e 'type == "array"' >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Docker Containers ${ENDPOINT_NAME}\" - Container API returned unexpected data"
continue
fi
TOTAL_CONTAINERS="$(
printf '%s' "$CONTAINERS_RESPONSE" |
jq 'length'
)"
RUNNING_CONTAINERS="$(
printf '%s' "$CONTAINERS_RESPONSE" |
jq '[.[] | select(.State == "running")] | length'
)"
STOPPED_CONTAINERS="$(
printf '%s' "$CONTAINERS_RESPONSE" |
jq '[.[] | select(.State != "running")] | length'
)"
UNHEALTHY_CONTAINERS="$(
printf '%s' "$CONTAINERS_RESPONSE" |
jq '
[
.[]
| select(
((.Status // "") | test("\\(unhealthy\\)"))
)
]
| length
'
)"
PROBLEM_LIST="$(
printf '%s' "$CONTAINERS_RESPONSE" |
jq -r '
.[]
| select(
(.State != "running")
or
((.Status // "") | test("\\(unhealthy\\)"))
)
| (
(
(.Names[0] // .Id // "unknown")
| sub("^/"; "")
)
+ "="
+ (.Status // .State // "unknown")
)
' |
paste -sd ';' -
)"
STATE=$OK
if [[ "$UNHEALTHY_CONTAINERS" -gt 0 ]]; then
STATE=$CRIT
elif [[ "$ALERT_STOPPED_CONTAINERS" == "yes" && "$STOPPED_CONTAINERS" -gt 0 ]]; then
STATE=$WARN
fi
PERFDATA="total=${TOTAL_CONTAINERS};;;0|running=${RUNNING_CONTAINERS};;;0|stopped=${STOPPED_CONTAINERS};;;0|unhealthy=${UNHEALTHY_CONTAINERS};;;0"
DETAILS="${RUNNING_CONTAINERS}/${TOTAL_CONTAINERS} running"
if [[ "$UNHEALTHY_CONTAINERS" -gt 0 ]]; then
DETAILS="${DETAILS}, ${UNHEALTHY_CONTAINERS} unhealthy"
fi
if [[ "$STOPPED_CONTAINERS" -gt 0 ]]; then
DETAILS="${DETAILS}, ${STOPPED_CONTAINERS} stopped"
fi
if [[ -n "$PROBLEM_LIST" ]]; then
DETAILS="${DETAILS}: ${PROBLEM_LIST}"
fi
printf '%s\n' \
"${STATE} \"Docker Containers ${ENDPOINT_NAME}\" ${PERFDATA} ${DETAILS}"
done < <(
printf '%s' "$ENDPOINTS_RESPONSE" |
jq -c '.[]'
)
#
# ---------------------------------------------------------------------------
# Endpoint summary
# ---------------------------------------------------------------------------
#
ENDPOINT_STATE=$OK
if [[ "$DOWN_ENDPOINTS" -gt 0 ]]; then
ENDPOINT_STATE=$CRIT
fi
printf '%s\n' \
"${ENDPOINT_STATE} \"Portainer Endpoints\" total=${ENDPOINT_COUNT};;;0|up=${UP_ENDPOINTS};;;0|down=${DOWN_ENDPOINTS};;;0 ${UP_ENDPOINTS}/${ENDPOINT_COUNT} endpoints UP"
exit 0
+177
View File
@@ -0,0 +1,177 @@
#!/bin/bash
set -u
CONFIG="/etc/check_mk/prometheus.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
if [[ ! -r "$CONFIG" ]]; then
echo "${UNKNOWN} \"Prometheus\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
PROMETHEUS_URL="${PROMETHEUS_URL:-http://127.0.0.1:9090}"
PROMETHEUS_TOKEN="${PROMETHEUS_TOKEN:-}"
TARGET_DOWN_STATE="${TARGET_DOWN_STATE:-2}"
if ! command -v curl >/dev/null 2>&1; then
echo "${UNKNOWN} \"Prometheus\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
echo "${UNKNOWN} \"Prometheus\" - jq is not installed"
exit 0
fi
CURL_OPTS=(
--silent
--show-error
--fail
--connect-timeout 3
--max-time 8
)
AUTH_ARGS=()
if [[ -n "$PROMETHEUS_TOKEN" ]]; then
AUTH_ARGS=(
--header "Authorization: Bearer ${PROMETHEUS_TOKEN}"
)
fi
#
# ---------------------------------------------------------------------------
# Prometheus health / version
# ---------------------------------------------------------------------------
#
BUILD_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_ARGS[@]}" \
"${PROMETHEUS_URL%/}/api/v1/status/buildinfo" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$BUILD_RESPONSE" ]]; then
echo "${CRIT} \"Prometheus\" - API unavailable at ${PROMETHEUS_URL}"
exit 0
fi
API_STATUS="$(
printf '%s' "$BUILD_RESPONSE" |
jq -r '.status // empty' 2>/dev/null
)"
VERSION="$(
printf '%s' "$BUILD_RESPONSE" |
jq -r '.data.version // empty' 2>/dev/null
)"
if [[ "$API_STATUS" != "success" || -z "$VERSION" ]]; then
echo "${CRIT} \"Prometheus\" - API responded but build information is invalid"
exit 0
fi
echo "${OK} \"Prometheus\" - API reachable, version ${VERSION}"
#
# ---------------------------------------------------------------------------
# Prometheus scrape targets
# ---------------------------------------------------------------------------
#
TARGET_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
"${AUTH_ARGS[@]}" \
"${PROMETHEUS_URL%/}/api/v1/targets?state=active" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$TARGET_RESPONSE" ]]; then
echo "${UNKNOWN} \"Prometheus Targets\" - Unable to retrieve target status"
exit 0
fi
TARGET_API_STATUS="$(
printf '%s' "$TARGET_RESPONSE" |
jq -r '.status // empty' 2>/dev/null
)"
if [[ "$TARGET_API_STATUS" != "success" ]]; then
echo "${UNKNOWN} \"Prometheus Targets\" - Prometheus returned an unsuccessful API response"
exit 0
fi
TOTAL="$(
printf '%s' "$TARGET_RESPONSE" |
jq '.data.activeTargets | length' 2>/dev/null
)"
UP="$(
printf '%s' "$TARGET_RESPONSE" |
jq '[.data.activeTargets[] | select(.health == "up")] | length' 2>/dev/null
)"
DOWN="$(
printf '%s' "$TARGET_RESPONSE" |
jq '[.data.activeTargets[] | select(.health != "up")] | length' 2>/dev/null
)"
if [[ -z "$TOTAL" || -z "$UP" || -z "$DOWN" ]]; then
echo "${UNKNOWN} \"Prometheus Targets\" - Unable to parse target information"
exit 0
fi
PERFDATA="total=${TOTAL} up=${UP} down=${DOWN}"
if [[ "$DOWN" -eq 0 ]]; then
echo "${OK} \"Prometheus Targets\" ${PERFDATA} All ${TOTAL} active targets are UP"
exit 0
fi
#
# Build readable DOWN target list.
#
# Prefer job + instance labels. Fall back to scrape URL where needed.
#
DOWN_LIST="$(
printf '%s' "$TARGET_RESPONSE" |
jq -r '
.data.activeTargets[]
| select(.health != "up")
| (
(.labels.job // "unknown-job")
+ "/"
+ (.labels.instance // .scrapeUrl // "unknown-target")
+ (
if (.lastError // "") != ""
then " (" + .lastError + ")"
else ""
end
)
)
' 2>/dev/null |
paste -sd '; ' -
)"
if [[ -z "$DOWN_LIST" ]]; then
DOWN_LIST="unable to identify failed targets"
fi
echo "${TARGET_DOWN_STATE} \"Prometheus Targets\" ${PERFDATA} ${UP}/${TOTAL} targets UP, ${DOWN} DOWN: ${DOWN_LIST}"
exit 0
+19
View File
@@ -0,0 +1,19 @@
# /etc/check_mk/crafty.conf
CRAFTY_URL="https://127.0.0.1:8443"
CRAFTY_USER="checkmk"
CRAFTY_PASSWORD="CHANGE_ME"
CRAFTY_INSECURE="yes"
IGNORE_HIDDEN_SERVERS="yes"
CHECK_UPDATES="yes"
# Community Script installation path.
CRAFTY_INSTALL_DIR="/opt/crafty-controller/crafty/crafty-4"
# Normally leave empty. Useful only if automatic version detection fails.
CRAFTY_INSTALLED_VERSION=""
CRAFTY_RELEASE_API="https://gitlab.com/api/v4/projects/34675721/releases/permalink/latest"
+14
View File
@@ -0,0 +1,14 @@
# Gitea API base URL.
# Localhost is preferable because CheckMK runs directly on the Gitea host.
GITEA_URL="http://127.0.0.1:3000"
# Optional API token.
# /api/v1/version may be accessible without authentication depending on config,
# but using a dedicated read-only token keeps things predictable.
GITEA_TOKEN=""
# Enable/disable upstream update check.
CHECK_UPDATES="yes"
# Upstream Gitea repository API.
GITEA_RELEASE_API="https://api.github.com/repos/go-gitea/gitea/releases/latest"
+12
View File
@@ -0,0 +1,12 @@
# /etc/check_mk/mail_archiver.conf
MAIL_ARCHIVER_URL="http://127.0.0.1:5000"
MAIL_ARCHIVER_TOKEN="ma_CHANGE_ME"
WARN_SYNC_AGE=3600
CRIT_SYNC_AGE=7200
CHECK_UPDATES="yes"
MAIL_ARCHIVER_RELEASE_API="https://api.github.com/repos/s1t5/mail-archiver/releases/latest"
VERSION_FILE="/root/.mail-archiver"
+9
View File
@@ -0,0 +1,9 @@
# /etc/check_mk/npm.conf
NPM_URL="http://127.0.0.1:81"
NPM_IDENTITY="checkmk@example.com"
NPM_SECRET="CHANGE_ME"
CHECK_UPDATES="yes"
NPM_RELEASE_API="https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest"
+10
View File
@@ -0,0 +1,10 @@
# /etc/check_mk/pm2.conf
PM2_USER="root"
PM2_HOME=""
CHECK_PM2_UPDATES="yes"
CHECK_NODE_UPDATES="yes"
PM2_PACKAGE_URL="https://registry.npmjs.org/pm2/latest"
NODE_RELEASES_URL="https://nodejs.org/dist/index.json"
+15
View File
@@ -0,0 +1,15 @@
# /etc/check_mk/portainer.conf
CHECK_UPDATES="yes"
PORTAINER_RELEASE_API="https://api.github.com/repos/portainer/portainer/releases/latest"
PORTAINER_URL="https://127.0.0.1:9443"
PORTAINER_TOKEN="ptr_XXXXXXXXXXXXXXXXXXXX"
# Portainer's local certificate may be self-signed.
PORTAINER_INSECURE="yes"
# Ignore containers that were intentionally stopped.
# Only unhealthy/running-state problems will alert.
ALERT_STOPPED_CONTAINERS="no"
+7
View File
@@ -0,0 +1,7 @@
PROMETHEUS_URL="http://127.0.0.1:9090"
# Optional bearer token if you ever place auth in front of Prometheus.
PROMETHEUS_TOKEN=""
# State when one or more scrape targets are DOWN.
TARGET_DOWN_STATE=2