# Server Stats Monitor

## Architecture
- **stats.php** — standalone lightweight endpoint on Debian 10 Linode. Reads only `/proc` filesystem (no `exec`/`shell` for security). Returns JSON.
- **dashboard.php** — single-file dashboard (no Laravel, no Composer, no Vite). Reads `/proc` directly, serves HTML with inline JS + Tailwind CDN. Password-protected via HTTP Basic Auth.

## URLs
- Endpoint: `https://stats.beatlenut.com/stats.php`
- Dashboard: `https://stats.beatlenut.com/dashboard.php` (or `php -S localhost:8000 dashboard.php` locally)

## Server Paths
- stats.php: `/home/rob/public/stats.beatlenut.com/public/public/stats.php`
- dashboard.php: `/home/rob/public/stats.beatlenut.com/public/public/dashboard.php`
- config/sites.php: `/home/rob/public/stats.beatlenut.com/public/public/config/sites.php`
- Apache vhost: `/etc/apache2/sites-enabled/stats.beatlenut.com.conf` — Apache 2.4.62, PHP 8.3 FPM via SetHandler, user www-data

## Key Files
- `stats.php` — standalone /proc endpoint
- `dashboard.php` — single-file dashboard (PHP + HTML + CSS + JS all in one)
- `config/sites.php` — list of monitored sites (name + URL pairs)

## Password
- Set via `$PASSWORD` variable at top of `dashboard.php`
- HTTP Basic Auth — browser shows native login prompt
- JS fetch requests automatically include credentials (same-origin)
- Test: `curl -u "admin:password" https://stats.beatlenut.com/dashboard.php`

## Server Stats
- Reads `/proc/stat`, `/proc/cpuinfo`, `/proc/meminfo`, `/proc/uptime`, `/proc/diskstats`, `/proc/net/dev`, `/proc/net/tcp`, `/proc/net/tcp6`, `/proc/mounts`
- Falls back to mock data when `/proc` unavailable (e.g., macOS dev)

## Disk I/O
- `/proc/diskstats` on Debian 10 with newer kernel has extra discard columns (14+ columns, not just 11)
- Uses `preg_split`-by-whitespace approach
- Root device (`sda`) may not be `disk_io[0]` (alphabetical ordering). Returns `root_device` from `/proc/mounts`; dashboard filters `disk_io` array by it.

## Networking
- Regex matches `eth0|ens\d+|enp\d+s\d+|eno\d+` interfaces (skips `lo`)
- Network rates calculated from delta between polls (bytes/s)

## Sites Monitoring
- 22 sites checked via cURL HEAD requests every 60s (file-based JSON cache at `sites_cache.json`)
- Results merged into JSON response under `sites` key
- Dashboard renders sites in responsive grid with green/red status dots
- Config in `config/sites.php` — edit to add/remove monitored URLs
- Timeout per site: 5s (connect 3s). Cache prevents hammering on 3s poll interval.
- Countdown timer shows seconds until next check batch

## Running Locally
```bash
cd ~/Sites/server-stats && php -S localhost:8000 dashboard.php
```
Open `http://localhost:8000` and enter the password from `$PASSWORD`. No build step needed — edit `dashboard.php` and refresh.
