Files
Varaverk/Monitors/README-Monitors.md
T

376 lines
13 KiB
Markdown

# Monitors
Watch and report only. Scripts in this folder never take action — they observe, measure, and notify. Intervention is handled by other parts of the ecosystem.
```
unRAID_Essentials/ — acts on the system (restarts, reboots, stops)
Docker_Essentials/ — acts on containers (watchdog, restarts)
Monitors/ — observes and reports (this folder)
```
All monitor scripts are safe to run at any time. None of them write to flash drives except `bandwidth_monitor.sh` which makes one bounded append per rsync run. All other monitors are read-only operations.
---
## Scripts
### `cert_monitor.sh`
Monitors SSL certificate expiry for all configured domains.
```bash
# Scheduled as: 0 9 * * 0 (Sunday 9am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/cert_monitor.sh
```
**How it works:**
Connects directly to each domain via `openssl s_client` and reads the certificate the server is actually presenting. This is different from checking your certificate files directly — it catches real-world issues that file-based checks miss:
- Certificate renewed but web server not reloaded — old cert still being served
- Wrong certificate being served for a domain
- Certificate chain issues invisible to the cert file itself
Each domain and subdomain is a separate entry. They have independent certificates — `gmer4lfe.com` and `auth.gmer4lfe.com` may expire on different dates.
**Notification behavior:**
- Silent when all certs are healthy
- One warning notification for all domains approaching `CERT_WARN_DAYS`
- One critical notification for all domains within `CERT_CRIT_DAYS`
- Notifications batched by severity — not one per domain
**Configuration:**
```bash
CERT_MONITOR_DOMAINS=(
"Gmer4Lfe.com"
"Gmer4Lfe.us"
# "auth.Gmer4Lfe.com" # add subdomains as separate entries
)
CERT_WARN_DAYS=30 # warn when this many days remaining
CERT_CRIT_DAYS=7 # critical when this many days remaining
CERT_TIMEOUT=10 # seconds before giving up per domain
```
---
### `smart_health.sh`
Checks SMART health attributes for all drives in the system.
```bash
# Scheduled as: 0 7 * * 0 (Sunday 7am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/smart_health.sh
```
**What it checks per drive:**
| Attribute | Threshold | Meaning |
|-----------|-----------|---------|
| Reallocated_Sector_Ct | > 0 = warning | Bad sectors remapped — drive showing wear |
| Current_Pending_Sector | > 0 = warning | Sectors awaiting reallocation |
| Offline_Uncorrectable | > 0 = critical | Sectors that could not be corrected |
| Temperature_Celsius | SMART_TEMP_WARN/CRIT | Drive running hot |
| Power_On_Hours | informational | Drive age estimate |
| Overall health status | PASSED/FAILED | Drive's own self-assessment |
Drive discovery is automatic — `/dev/sd*` and `/dev/nvme*` are scanned on every run. No drive list to maintain.
**Why ignore the boot USB:**
unRAID boots from a USB flash drive that typically appears as `sda`. Flash drives either don't support SMART or report meaningless values. Add it to `SMART_IGNORE_DRIVES` to keep it out of the report.
**Notification behavior:**
- Silent when all drives are healthy
- One warning notification listing all drives with concerning attributes
- One critical notification if any drive has uncorrectable sectors
**Configuration:**
```bash
SMART_TEMP_WARN=45 # degrees C
SMART_TEMP_CRIT=55 # degrees C
SMART_IGNORE_DRIVES=(
"sda" # boot USB — not meaningful to check
)
```
---
### `zfs_memory_snapshot.sh`
Weekly ZFS pool health and memory diagnostic report.
```bash
# Scheduled as: 0 6 * * 0 (Sunday 6am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/zfs_memory_snapshot.sh
```
**What it reports:**
- Pool status — ONLINE/DEGRADED/FAULTED per pool
- Pool overview — size, allocated, free, capacity, health
- ARC statistics — max, current, metadata usage, utilization %
- Memory status — total, free, available RAM vs thresholds
- Top N Docker containers by memory usage
- Kernel pressure snapshot via vmstat
**Informational only.** This script reports what it finds. `system_watchdog.sh` handles threshold-based intervention — ARC reclaim, reboot decisions, memory pressure response. The snapshot gives you the weekly picture; the watchdog handles emergencies.
**Output is written to both console and `ZFS_REPORT_LOG`** — the log file lets you compare pool health week over week without having to remember what last week's numbers were.
**Pool ignore list:**
Pools expected to run at high capacity can be excluded from health reporting. They remain fully monitored by unRAID — this only affects what appears in the weekly report.
```bash
ZFS_REPORT_IGNORE_POOLS=(
"disk10" # high usage expected
"disk9"
"disk8"
"disk6"
"disk5"
)
```
**Configuration:**
```bash
ZFS_REPORT_LOG="/var/log/zfs-weekly-health.log"
ZFS_REPORT_ARC_WARN_PCT=90 # warn if ARC utilization above this %
ZFS_REPORT_FREE_WARN_GB=10 # warn if free RAM below this GB
ZFS_REPORT_AVAIL_WARN_GB=20 # warn if available RAM below this GB
ZFS_REPORT_DOCKER_TOP=10 # top N Docker memory users to show
```
---
### `backup_verify.sh`
Verifies the rsync mirror is healthy by comparing random file checksums between local and remote servers.
```bash
# Scheduled as: 0 10 * * 0 (Sunday 10am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/backup_verify.sh
```
**Why this matters:**
`rsync.sh` copies files successfully. But does the copy match the original? `backup_verify.sh` answers that question by independently computing MD5 checksums on both sides and comparing them. It catches:
- Silent data corruption during transfer
- Files that transferred but were corrupted at rest
- Partial transfers that rsync reported as success
- Storage hardware issues on either server
**How it works:**
1. Randomly samples `BACKUP_VERIFY_SAMPLE` files per share (files larger than `BACKUP_VERIFY_MIN_SIZE`)
2. Computes MD5 checksum locally
3. SSHes to remote and computes MD5 checksum there
4. Compares results
**Result per file:**
| Result | Meaning |
|--------|---------|
| MATCH | Checksums identical — file correctly mirrored |
| MISMATCH | File exists on both but checksums differ — sync may have failed |
| MISSING | File exists locally but not on remote — not yet synced or deleted |
**Configuration:**
```bash
# Leave empty to use DAILY_SYNC_SHARES automatically
BACKUP_VERIFY_SHARES=(
# /mnt/user/Movies
# /mnt/user/Tv_Shows
)
BACKUP_VERIFY_SAMPLE=10 # files sampled per share per run
BACKUP_VERIFY_MIN_SIZE=1M # skip files smaller than this
```
If `BACKUP_VERIFY_SHARES` is empty the script automatically uses `DAILY_SYNC_SHARES` — no additional configuration needed for the standard setup.
Uses the existing SSH keys already configured for rsync — no additional setup required.
---
### `bandwidth_monitor.sh`
Logs rsync transfer history and generates weekly summary reports. Called automatically by `rsync.sh` — you do not need to schedule the logging mode manually.
```bash
# Log mode — called automatically by rsync.sh after each successful sync
# No manual scheduling needed
# Report mode — run manually or schedule weekly
# Scheduled as: 0 11 * * 0 (Sunday 11am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/bandwidth_monitor.sh --report
```
**Two modes:**
**`--log-transfer profile duration status`** — called by `rsync.sh` after each sync. Appends one line to the log file and trims entries older than `BANDWIDTH_LOG_RETENTION` days. You never call this manually.
**`--report`** — reads the log file and generates a weekly summary showing per-profile run counts, average durations, last 7 days activity, and failure counts.
**Log format:**
```
YYYY-MM-DD|HH:MM|profile|duration_seconds|status
2026-04-14|01:23|arrs_stack|287|success
2026-04-14|01:31|critical-data|143|success
2026-04-14|02:15|movies|1847|failed
```
**Why this format:**
The log never parses rsync output. Earlier designs tried to extract bytes transferred from rsync's human-readable output — that approach breaks silently when rsync updates and changes its output format. The current format captures what's reliably available: profile, duration, and success/failure. This is version-proof and survives any rsync update.
**Flash drive design:**
The log lives on `/boot/` so it survives reboots. Each rsync run makes exactly one append and one trim — the file never grows beyond `BANDWIDTH_LOG_RETENTION` lines. Minimal flash wear.
**Configuration:**
```bash
BANDWIDTH_LOG="/boot/config/bandwidth_history.db"
BANDWIDTH_LOG_RETENTION=90 # days — file stays bounded
BANDWIDTH_WARN_GB=50 # flag days exceeding this in reports
# (note: current log tracks duration not bytes)
```
---
### `weekly_health_digest.sh`
Aggregates system health data from across the entire ecosystem into a single digest report.
```bash
# Scheduled as: 0 8 * * * (8am daily — profile controls when it notifies)
/mnt/user/appdata/unraid_scripts/Monitors/weekly_health_digest.sh
```
**The key design:** schedule it daily regardless of profile. The `DIGEST_PROFILE` setting in `Master.conf` controls when a notification is actually sent — not the cron schedule.
**Three profiles:**
| Profile | Behavior | Use When |
|---------|----------|----------|
| `always` | Sends every run | You want a daily health summary |
| `smart` | Sends only if something worth reporting | Quiet operation, alerts on issues |
| `weekly` | Sends once per week on `DIGEST_DAY` | Weekly digest, silent other days |
Switch profiles by changing `DIGEST_PROFILE` in `Master.conf` — no cron changes needed.
**Data sources — reads only, no writes:**
| Source | What it reads |
|--------|---------------|
| `/tmp/transcode_state.db` | Ramdisk symlink and usage |
| `/tmp/container_watchdog_state.db` | Active container watchdog strikes |
| `/tmp/system_watchdog_state.db` | Active system watchdog strikes |
| `/boot/config/failover_state.db` | Current failover state |
| `/boot/config/system_watchdog_failed.db` | Container skip list |
| `/boot/config/bandwidth_history.db` | Recent transfer totals |
| Live `openssl` connection | SSL cert days remaining per domain |
**Smart profile triggers:**
```bash
# Set true to include this check in smart mode's "worth reporting" decision
DIGEST_SMART_ON_WATCHDOG=true # any active watchdog strikes
DIGEST_SMART_ON_FAILOVER=true # failover state is not NORMAL
DIGEST_SMART_ON_CERT_WARN=true # any cert under CERT_WARN_DAYS
DIGEST_SMART_ON_BANDWIDTH=true # any transfer exceeded BANDWIDTH_WARN_GB
```
**Configuration:**
```bash
DIGEST_PROFILE="weekly" # always | smart | weekly
DIGEST_DAY="Sunday" # for weekly profile — must match date +%A output
```
---
### `emby_session_report.sh`
Weekly Emby usage report via the Emby API.
```bash
# Scheduled as: 0 11 * * 0 (Sunday 11am weekly)
/mnt/user/appdata/unraid_scripts/Monitors/emby_session_report.sh
```
**What it reports:**
- Active streams at time of run
- Stream breakdown — total, Live TV, transcoding, direct play
- Library counts — movies, episodes, songs
- Current ramdisk transcode usage and symlink state
**No persistent writes** — queries the Emby API fresh on every run. No log files, no state. Run it any time for a current snapshot.
**Requires an Emby API key:**
1. Open Emby Settings → API Keys
2. Generate a new key
3. Paste it into `Master.conf` as `EMBY_API_KEY`
**Configuration:**
```bash
EMBY_URL="http://localhost:8096"
EMBY_API_KEY="" # get from Emby Settings → API Keys
EMBY_REPORT_DAYS=7 # report period in days
EMBY_REPORT_TOP_N=10 # top N content items to show
```
---
## Flash Drive Write Policy
unRAID boots from a USB flash drive. Flash drives have limited write cycles. The Monitors folder is designed with this in mind:
| Script | Writes to flash | Notes |
|--------|----------------|-------|
| `cert_monitor.sh` | Never | Read-only openssl checks |
| `smart_health.sh` | Never | Read-only smartctl checks |
| `zfs_memory_snapshot.sh` | Never | Writes to `/var/log/` (RAM disk) |
| `backup_verify.sh` | Never | SSH + MD5 comparison only |
| `bandwidth_monitor.sh` | One append + one trim per rsync run | Bounded — never exceeds retention days |
| `weekly_health_digest.sh` | Never | Reads existing state files only |
| `emby_session_report.sh` | Never | API queries only |
The only flash write in the entire Monitors folder is `bandwidth_monitor.sh` — and it's designed to be minimal and bounded.
---
## Recommended Schedule
```bash
# Daily
0 8 * * * weekly_health_digest.sh # profile controls when it notifies
# Weekly — Sunday morning block
0 6 * * 0 zfs_memory_snapshot.sh
0 7 * * 0 smart_health.sh
0 9 * * 0 cert_monitor.sh
0 10 * * 0 backup_verify.sh
0 11 * * 0 emby_session_report.sh
0 11 * * 0 bandwidth_monitor.sh --report
# Automatic — no scheduling needed
# bandwidth_monitor.sh --log-transfer is called by rsync.sh after each sync
```
The Sunday morning block runs after the nightly maintenance window — by the time the monitors run, the weekly restarts, log clears, and media management jobs have completed. The health snapshot reflects a freshly maintained system.
---
## --dry-run Support
All monitor scripts support `--dry-run`. In dry-run mode:
- Checks run and results are shown
- No notifications are sent
- No files are written
Useful for testing configuration changes before scheduling:
```bash
/mnt/user/appdata/unraid_scripts/Monitors/cert_monitor.sh --dry-run
/mnt/user/appdata/unraid_scripts/Monitors/backup_verify.sh --dry-run
/mnt/user/appdata/unraid_scripts/Monitors/smart_health.sh --dry-run
```