# Server Monitor (PHP)

Checks Apache and MySQL on any number of servers every minute, shows a dashboard, and emails
**every address you add** when a service goes DOWN and again when it recovers.

Works on PHP 7.4+ with MySQL 5.7+/8.x. No Composer or PHPMailer needed (it has its own SMTP client).

## Folders

| Folder | Purpose |
|---|---|
| `public/` | The web pages. The only folder Apache serves. |
| `inc/` | Config and code. Not web-accessible. |
| `cron/check.php` | The checker. Run every minute by Task Scheduler. |
| `cron/test-mail.php` | Command-line email tester that prints the full SMTP conversation. |
| `schema.sql` | Database tables. |

## Install on Windows Server

**1. Copy** the `server-monitor` folder to the server, e.g. `E:\btsapp\server-monitor`.

**2. Create the database.** In a MySQL client run `schema.sql`, then create the app user:

```sql
CREATE USER 'monitor_user'@'localhost' IDENTIFIED BY 'a-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON server_monitor.* TO 'monitor_user'@'localhost';
```

**3. On every server whose MySQL you want to watch**, create the probe user (no privileges needed):

```sql
CREATE USER 'monitor_ping'@'%' IDENTIFIED BY 'another-password';
```

Why: a bare TCP connect to MySQL counts as a failed handshake. After `max_connect_errors` (default 100)
of them MySQL blocks the monitoring host. A real login attempt does not.

**4. Edit `inc/config.php`:** database password, `monitor_ping` password (`mysql_probe`), the `smtp`
block, and the dashboard password hash:

```
php -r "echo password_hash('YourStrongPassword', PASSWORD_DEFAULT);"
```

**5. Publish the dashboard** by adding this to `C:\Apache2465\conf\httpd.conf` (or an included vhost file),
then restart Apache:

```apache
Alias /monitor "E:/btsapp/server-monitor/public"
<Directory "E:/btsapp/server-monitor/public">
    Require all granted
</Directory>
```

Open `http://SERVER/monitor/` and sign in. Better still, run the dashboard on a different machine from the
servers it watches, so it stays reachable when one of them is down. The checker itself runs from Task
Scheduler, not through Apache, so alerts still go out when Apache is down.

**6. Test email from the command line** (find your PHP with `where php`):

```
php E:\btsapp\server-monitor\cron\test-mail.php you@example.com
```

On failure it prints the exact server reply. Gmail / Google Workspace needs an **App Password**
(`534 5.7.9 Application-specific password required` means the normal password was used).

**7. Schedule the checker every minute** (elevated Command Prompt, adjust the two paths):

```
schtasks /Create /TN "ServerMonitor" /SC MINUTE /MO 1 /RU SYSTEM /RL HIGHEST /TR "C:\php\php.exe E:\btsapp\server-monitor\cron\check.php"
```

**8. Add servers** in the dashboard: *Services -> Quick add* creates an Apache (HTTP) and a MySQL check
for one server. Add alert addresses under *Alert emails* (paste several at once). Use *Test now* on a
service and *Send test email* to confirm everything works.

## How alerting works

* A check fails when the port is closed, the HTTP request times out or returns 5xx, or MySQL does not answer.
* A **DOWN** email is sent after `fail_threshold` consecutive failures (default 2, i.e. about 2 minutes), so one
  dropped packet does not page anyone. Set it to 1 for instant alerts.
* A **RECOVERED** email follows when the service answers again, with the downtime duration.
* While a service stays down you get one email, not one per minute.
* Every alert and its email result (sent / failed + reason) is listed under *Alert history*.
* The dashboard warns you if the checker has not run for over 3 minutes.

## Limits

* Checks run one after another, each with up to `check_timeout` seconds. Around 30 services is fine; for
  many more, run a second copy.
* If the machine running the checker itself dies, nothing is sent. For that, add an outside check
  (for example UptimeRobot) on the dashboard URL.
* Keep `inc/config.php` readable only by Administrators/SYSTEM: it holds the SMTP and database passwords.
