#!/usr/bin/env bash
# ap-health.sh: read-only health snapshot for a Debian host (bare metal, VPS, Proxmox node or guest).
# Prints key=value lines. Paste the output into the Overnight Console "Host triage" tab.
# Changes nothing. Safe to run as a normal user; run with sudo for journal, MySQL and Proxmox detail.
# Optional: CERTS="exchange.example.com:443 api.example.com:443" to check TLS expiry.
set -u
export LC_ALL=C
kv() { printf '%s=%s\n' "$1" "$2"; }
has() { command -v "$1" >/dev/null 2>&1; }

echo "# ap-health v1"
kv host "$(hostname -f 2>/dev/null || hostname)"
kv ts_utc "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
kv os "$(. /etc/os-release 2>/dev/null && echo "$PRETTY_NAME")"
kv kernel "$(uname -r)"
kv uptime_s "$(cut -d. -f1 /proc/uptime)"
kv cpus "$(nproc)"
kv load "$(cut -d' ' -f1-3 /proc/loadavg)"
awk '/^MemTotal:/{t=$2}/^MemAvailable:/{a=$2}/^SwapTotal:/{st=$2}/^SwapFree:/{sf=$2}
     END{printf "mem_total_kb=%d\nmem_avail_kb=%d\nswap_total_kb=%d\nswap_used_kb=%d\n",t,a,st,st-sf}' /proc/meminfo

# Filesystems: mount,use%  and inodes: mount,iuse%
df -P -x tmpfs -x devtmpfs -x overlay -x squashfs 2>/dev/null | awk 'NR>1{print "disk="$6","$5}' | sort -u
df -Pi -x tmpfs -x devtmpfs -x overlay -x squashfs 2>/dev/null | awk 'NR>1 && $5!="-"{print "inode="$6","$5}' | sort -u

# systemd, reboot, time sync
if has systemctl; then
  systemctl list-units --state=failed --no-legend --plain 2>/dev/null | awk '{print "failed_unit="$1}'
  kv ntp_synced "$(timedatectl show -p NTPSynchronized --value 2>/dev/null)"
fi
kv reboot_required "$([ -f /var/run/reboot-required ] && echo yes || echo no)"
if has apt; then
  up="$(apt list --upgradable 2>/dev/null | grep -v '^Listing')"
  kv apt_upgradable "$(printf '%s' "$up" | grep -c . )"
  kv apt_security "$(printf '%s' "$up" | grep -ci -- '-security')"
fi
if has journalctl; then
  kv journal_err_1h "$(journalctl -p err --since '-1h' -q --no-pager 2>/dev/null | wc -l)"
  kv oom_kills_24h "$(journalctl -k --since '-24h' -q --no-pager 2>/dev/null | grep -ci 'killed process')"
fi

# SSH exposure
if has sshd; then
  sshd -T 2>/dev/null | awk '/^permitrootlogin /{print "ssh_root_login="$2}/^passwordauthentication /{print "ssh_password_auth="$2}'
fi
has ss && kv listen_public "$(ss -Htln 2>/dev/null | awk '{print $4}' | grep -Ev '^(127\.|\[::1\]|::1)' | sed 's/.*://' | sort -un | tr '\n' ' ')"

# Docker: name|status|restarts
if has docker && docker info >/dev/null 2>&1; then
  for id in $(docker ps -aq 2>/dev/null); do
    docker inspect -f '{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}|{{.RestartCount}}' "$id" 2>/dev/null | sed 's#^/##; s/^/container=/'
  done
fi

# MySQL / MariaDB (uses ~/.my.cnf or socket auth)
if has mysql; then
  if mysqladmin ping >/dev/null 2>&1; then
    kv mysql_up yes
    mysql -NBe "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';" 2>/dev/null | awk '{print "mysql_"tolower($1)"="$2}'
    rep="$(mysql -e 'SHOW REPLICA STATUS\G' 2>/dev/null || mysql -e 'SHOW SLAVE STATUS\G' 2>/dev/null)"
    printf '%s\n' "$rep" | awk -F': ' '/Seconds_Behind_(Source|Master):/{print "mysql_lag_s="$2}
      /(Replica|Slave)_IO_Running:/{print "mysql_io="$2}/(Replica|Slave)_SQL_Running:/{print "mysql_sql="$2}
      /Last_(IO_)?Error:/{ if($2!="") print "mysql_last_error="$2}'
  else
    kv mysql_up no
  fi
fi

# Proxmox VE node
if has pvesh; then
  has pvecm && kv pve_quorate "$(pvecm status 2>/dev/null | awk -F': *' '/Quorate/{print $2}')"
  has qm  && qm list 2>/dev/null | awk 'NR>1{print "vm="$1","$2","$3}'
  has pct && pct list 2>/dev/null | awk 'NR>1{print "ct="$1","$NF","$2}'
  has pvesm && pvesm status 2>/dev/null | awk 'NR>1 && $4>0{printf "storage=%s,%s,%.0f%%\n",$1,$3,$5/$4*100}'
fi
has zpool && kv zpool_health "$(zpool status -x 2>/dev/null | head -1)"

# TLS expiry for listed endpoints
for ep in ${CERTS:-}; do
  end="$(echo | timeout 8 openssl s_client -servername "${ep%%:*}" -connect "$ep" 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)"
  if [ -n "$end" ]; then kv cert "$ep,$(( ($(date -d "$end" +%s) - $(date +%s)) / 86400 ))"; else kv cert "$ep,unreachable"; fi
done
echo "# end"
