Files
2026-08-01 12:03:22 +02:00

84 lines
3.9 KiB
Nix

{ pkgs, ... }:
let
healthScript = pkgs.writeShellScriptBin "nixserve-health" ''
R='\033[0;31m' G='\033[0;32m' Y='\033[1;33m' B='\033[0;34m' W='\033[1m' N='\033[0m'
ok() { echo -e " ''${G}✓''${N} $*"; }
warn() { echo -e " ''${Y}⚠''${N} $*"; }
bad() { echo -e " ''${R}✗''${N} $*"; }
section(){ echo -e "\n''${W}''${B}$*''${N}"; }
echo -e "''${W}nixserve''${N} — $(date '+%Y-%m-%d %H:%M') uptime: $(uptime | sed 's/.*up //; s/,.*//') load: $(cut -d' ' -f1-3 /proc/loadavg)"
# ── ZFS ────────────────────────────────────────────────────────────────────
section "ZFS"
while IFS= read -r pool; do
health=$(zpool list -H -o health "$pool" 2>/dev/null)
errors=$(zpool status "$pool" 2>/dev/null | awk '/errors:/{$1=""; print substr($0,2)}')
scrub=$(zpool status "$pool" 2>/dev/null | awk '/scan:/{$1=""; print substr($0,2)}' | head -1)
if [[ "$health" == "ONLINE" ]]; then
ok "$pool $health — $errors"
else
bad "$pool $health — $errors"
fi
[[ -n "$scrub" ]] && echo -e " scrub: $scrub"
done < <(zpool list -H -o name 2>/dev/null)
# ── Systemd ─────────────────────────────────────────────────────────────────
section "Systemd"
failed=$(systemctl --failed --no-legend --no-pager 2>/dev/null | awk '{print $1}')
if [[ -z "$failed" ]]; then
ok "No failed units"
else
while IFS= read -r u; do bad "$u"; done <<< "$failed"
fi
# ── Docker ──────────────────────────────────────────────────────────────────
section "Docker"
if docker info &>/dev/null 2>&1; then
while IFS=$'\t' read -r name status; do
[[ -z "$name" ]] && continue
if [[ "$status" == Up* ]]; then ok "$name ($status)"
else bad "$name ($status)"; fi
done < <(docker ps -a --format $'{{.Names}}\t{{.Status}}' 2>/dev/null)
else
warn "docker not reachable"
fi
# ── Disk ────────────────────────────────────────────────────────────────────
section "Disk"
df -h --output=target,pcent,used,size -x tmpfs -x devtmpfs -x efivarfs 2>/dev/null \
| tail -n +2 \
| while read -r mnt pct used size; do
n=''${pct/\%/}
if (( n >= 90 )); then bad "$mnt $pct ($used / $size)"
elif (( n >= 75 )); then warn "$mnt $pct ($used / $size)"
else ok "$mnt $pct ($used / $size)"
fi
done
# ── Memory ──────────────────────────────────────────────────────────────────
section "Memory"
free -h | awk '/^Mem:/{printf " used: %s / %s free: %s\n", $3, $2, $4}'
# ── Recent errors ───────────────────────────────────────────────────────────
section "Journal errors (last hour)"
errs=$(journalctl -p err --since "1 hour ago" --no-pager -q 2>/dev/null \
| grep -v "^$" | tail -8)
if [[ -z "$errs" ]]; then
ok "None"
else
while IFS= read -r line; do warn "$line"; done <<< "$errs"
fi
echo
'';
in
{
environment.systemPackages = [ healthScript ];
programs.zsh.loginShellInit = ''
[[ -n "$SSH_CONNECTION" ]] && nixserve-health
'';
}