# Deploying the ATT Healthcheck Server
Single-tenant PHP/SQLite app. Tiny — runs comfortably on the smallest VPS tier.
## Requirements
- PHP **8.1+** with `pdo`, `pdo_sqlite`, `json`, `mbstring` (all standard).
- Apache + `mod_rewrite`, or nginx with a `try_files` fallback.
- HTTPS terminating in front of PHP. Plain HTTP is technically accepted, but the plugin client will refuse to talk to non-`https://` endpoints.
## Layout on the server
Anywhere works — every path inside the app is resolved relative to its own files.
Example using `/home/www/healthcheck`:
```
/home/www/healthcheck/
├── public/ ← docroot
│ ├── .htaccess
│ └── index.php
├── src/
├── migrations/
├── data/ ← SQLite file lives here (writable by web user)
├── config.php ← deployment-specific, NOT in git
└── config.php.example
```
> **Perm gotcha for `/home/...` locations:** home directories often default to
> `750` or `700`, which blocks the web user from traversing into the app.
> `sudo chmod 755 /home/www` once is usually enough. `/var/www` doesn't have
> this problem (always world-readable by default).
## First-time install
```sh
# As you, on the server:
sudo mkdir -p /home/www/healthcheck
sudo chown $USER:www-data /home/www/healthcheck
sudo chmod 755 /home/www # see perm gotcha above
# From your dev box:
rsync -avz --exclude='data/' --exclude='config.php' \
~/dev/att-site-healthcheck/server/ \
user@vps:/home/www/healthcheck/
# Back on the server:
cd /home/www/healthcheck
cp config.php.example config.php
php -r 'echo bin2hex(random_bytes(32)), PHP_EOL;' # generate api_key
$EDITOR config.php # paste it in
mkdir -p data
sudo chown -R www-data:www-data data/ config.php
sudo chmod 640 config.php
sudo chmod 770 data/
```
## Apache vhost (example)
```apache
ServerName healthcheck-history.example.com
DocumentRoot /home/www/healthcheck/public
AllowOverride All
Require all granted
# Pass Authorization header through to PHP — Apache strips it by default with FPM.
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/healthcheck-history.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/healthcheck-history.example.com/privkey.pem
```
## nginx (example)
```nginx
server {
listen 443 ssl http2;
server_name healthcheck-history.example.com;
root /home/www/healthcheck/public;
index index.php;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
}
ssl_certificate /etc/letsencrypt/live/healthcheck-history.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/healthcheck-history.example.com/privkey.pem;
}
```
## TLS
Use Let's Encrypt + certbot. Example:
```sh
sudo certbot --apache -d healthcheck-history.example.com
# or for nginx:
sudo certbot --nginx -d healthcheck-history.example.com
```
## Configure the plugin to talk to it
In `wp-config.php` on each WordPress install:
```php
define('ATT_HC_API_URL', 'https://healthcheck-history.example.com');
define('ATT_HC_API_KEY', '');
```
## Backups
The SQLite DB is a single file. Snapshot it on a cron:
```cron
# Daily at 03:15, rotate 14 days. SQLite-safe online backup.
15 3 * * * /usr/bin/sqlite3 /home/www/healthcheck/data/att_hc.sqlite ".backup '/var/backups/att-hc/att_hc-$(date +\%F).sqlite'" && find /var/backups/att-hc -name 'att_hc-*.sqlite' -mtime +14 -delete
```
Pull those backups offsite with `rsync` / `rclone` to whatever you already use.
## Updating
Just rsync the source again — migrations run on first request after deploy.
```sh
rsync -avz --delete --exclude='data/' --exclude='config.php' \
~/dev/att-site-healthcheck/server/ \
user@vps:/home/www/healthcheck/
```
## Quick health check
```sh
curl https://healthcheck-history.example.com/
# → {"ok":true,"service":"att-site-healthcheck-server","version":"..."}
```