# Deployment Guide This application can run on basic shared webhosting because it uses: - plain PHP - no database - no Composer dependencies - JSON files for persistence The deployment target assumed by this guide is a classic shared hosting account with a document root such as `public_html/`. ## Requirements Required: - PHP 8.1 or newer recommended - PHP sessions enabled - permission for PHP to read `src/` and read/write `data/` - domain or subdomain pointing to the app Optional but useful: - working `mail()` configuration for email alerts - `allow_url_fopen` enabled for webhook alerts - outbound HTTPS requests for webhook alerts - browser access to `cdn.jsdelivr.net` if the Swagger UI should load at `/docs/` or `/docs/` Not required: - database - Composer - Node.js - cron job ## Base Path And Subfolder Deployments The application now supports an optional configured base path for deployments below the domain root. Examples: - root deployment: `https://monitor.example.com/` - root deployment: `https://example.com/` - subfolder deployment: `https://example.com/monitor/` The relevant config value is `app.base_path` in `data/config.json`: - leave it empty for deployment directly under `/` - set it to the URL prefix for subfolder deployments, for example `"/monitor"` - the value is normalized on save, so `monitor`, `/monitor`, and `/monitor/` all become `"/monitor"` This setting is used for generated links, asset URLs, admin redirects, and dashboard API polling. Important: - `app.base_path` changes URLs, not the required PHP file layout - `src/` and `data/` must still stay outside the public web root - the public PHP files must still be deployed in a layout where their relative `../src/...` and `../data/...` paths resolve correctly ## Where Everything Should Be ### Preferred layout if the host allows a custom document root Keep the repository structure as-is and point the domain document root to `public/`. ```text /home/account/getraenke-monitor/ ├── data/ │ ├── alert_log.json │ ├── config.json │ └── state.json ├── public/ <- document root │ ├── admin/ │ ├── api/ │ ├── docs/ │ ├── app.js │ ├── index.php │ ├── openapi.yaml │ └── styles.css └── src/ ``` ### Recommended layout for basic shared hosting with `public_html/` If the host does not let you choose `public/` as document root, upload the files like this: ```text /home/account/ ├── data/ │ ├── alert_log.json │ ├── config.json │ └── state.json ├── public_html/ <- public contents go here │ ├── admin/ │ ├── api/ │ ├── docs/ │ ├── app.js │ ├── index.php │ ├── openapi.yaml │ └── styles.css └── src/ ``` Important: - upload the **contents of `public/`** into `public_html/` - upload `src/` next to `public_html/`, not inside it - upload `data/` next to `public_html/`, not inside it This exact layout matches how the PHP files resolve `../src/bootstrap.php` and `../data/...`. ## What Must Be Public And What Must Stay Private Public in the web root: - `index.php` - `styles.css` - `app.js` - `openapi.yaml` - `admin/` - `api/` - `docs/` Private, outside the public web root: - `src/` - `data/config.json` - `data/state.json` - `data/alert_log.json` Do not place `data/` inside the public web root if you can avoid it. Those files contain credentials, live state, and alert history. ## Deployment Steps ### 1. Prepare the files From this repository, you need these folders: - `public/` - `src/` - `data/` You do not need `docs/` on the server for runtime operation. The `docs/` folder in the repository is only Markdown documentation for developers. ### 2. Upload the application Using FTP, SFTP, or your hosting file manager: - upload `src/` outside the public web root - upload `data/` outside the public web root - upload the contents of `public/` into the public web root For a typical shared host that means: - repo `src/` -> server `~/src/` - repo `data/` -> server `~/data/` - repo `public/*` -> server `~/public_html/` ### 3. Set permissions PHP must be able to write to `data/` and the JSON files in it. Typical safe defaults: - directories: `755` or `775` - files: `644` or `664` If the host runs PHP under your own account, `755/644` is often enough. If writes fail, adjust group write permissions first before considering anything more permissive. The app needs write access for: - `data/config.json` - `data/state.json` - `data/alert_log.json` ### 4. Set the PHP version In the hosting control panel, select PHP `8.1` or newer for the domain/subdomain. ### 5. Open the app After upload, these URLs should work. If `app.base_path` is empty: - `/` - `/admin/` - `/api/v1/status.php` - `/docs/` - `/openapi.yaml` Examples: - `https://monitor.example.com/` - `https://monitor.example.com/admin/` - `https://monitor.example.com/api/v1/status.php` If `app.base_path` is set to `/monitor`: - `/monitor/` - `/monitor/admin/` - `/monitor/api/v1/status.php` - `/monitor/docs/` - `/monitor/openapi.yaml` Examples: - `https://example.com/monitor/` - `https://example.com/monitor/admin/` - `https://example.com/monitor/api/v1/status.php` ### 6. Replace the default credentials The example files ship with placeholder credentials. After the first login, immediately change: - admin username - admin password - API bearer token You can do that in `/admin/` or `/admin/`, depending on the deployment. ### 7. Configure the application In the admin panel, configure: - app name - timezone - dashboard refresh interval - email sender - base path - webhook targets - email recipients - machines - slots - sensor calibration values - alert thresholds For the base path: - leave it empty when the app is served directly from the domain root - set it to the exact URL prefix when the app is served from a subfolder, for example `/monitor` The JSON structure is documented in [CONFIG.md](./CONFIG.md). ### 8. Connect the sensor clients Each ESP32 or other sensor client should send readings to: ```text POST https://your-domain.example/api/v1/readings.php Authorization: Bearer Content-Type: application/json ``` Examples: - root deployment: `https://your-domain.example/api/v1/readings.php` - subfolder deployment with `app.base_path = "/monitor"`: `https://your-domain.example/monitor/api/v1/readings.php` The request and response format is documented in [API.md](./API.md). ### 9. Run a deployment check Verify all of the following: - dashboard loads without PHP errors - admin login works - saving config works - `data/state.json` updates after a test reading - webhook delivery works if configured - email delivery works if configured - `/api/v1/status.php` returns JSON - `/docs/` loads Swagger UI - all links, redirects, CSS, and JavaScript requests use the expected base path if deployed in a subfolder ## First Live Test Use one manual API call after deployment: ```bash curl -X POST https://your-domain.example/api/v1/readings.php \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "machine_id": "automat-lobby", "sensor_id": "fach-a1", "distance_mm": 184 }' ``` If that works, the dashboard should shortly show the new state. ## Troubleshooting ### Dashboard loads, but saving config fails Cause: - `data/` is not writable by PHP Check: - directory permissions - file ownership - hosting PHP user ### PHP errors about missing `src/bootstrap.php` Cause: - `src/` was uploaded into the wrong place Fix: - place `src/` next to `public_html/`, not inside it ### API works locally but not on shared hosting Check: - PHP version - whether `Authorization` headers are forwarded by the host - whether HTTPS is used The app already checks both `HTTP_AUTHORIZATION` and `REDIRECT_HTTP_AUTHORIZATION`, which helps on many Apache-based hosts. ### Dashboard loads without CSS/JS, or admin links point to the wrong URL Cause: - `app.base_path` does not match the actual public URL prefix Fix: - leave `app.base_path` empty for deployment at `/` - set it to the exact subfolder path for deployments such as `/monitor` - save the config again from `/admin/` or update `data/config.json` directly if the admin URL is currently wrong ### `/docs/` does not render Cause: - the Swagger UI page loads its assets from `cdn.jsdelivr.net` Fix: - allow outbound access to the CDN - or replace the hosted Swagger assets with local files later ## Recommended Go-Live Checklist - set `app.base_path` correctly for the final public URL - keep `src/` and `data/` outside the public web root - ensure `data/` is writable - replace all demo credentials - test one real API reading - verify alerts before production use