From cfa838e86a2cfd573c3350cf014d318168627124 Mon Sep 17 00:00:00 2001 From: "Claude (Chronicler #47)" Date: Sun, 29 Mar 2026 14:10:47 +0000 Subject: [PATCH] feat: modpack version checker dashboard + PHP proxy (v1.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WHAT WAS DONE: - Built browser dashboard (dashboard.html) showing installed vs latest version for all Pterodactyl game servers - Built PHP proxy (proxy.php + config.php) for Billing VPS deployment - Created isolated Nginx server block (version-proxy.conf) - Created full deployment guide (DEPLOYMENT-GUIDE.md) ARCHITECTURE: - PHP proxy at /var/www/version-proxy on Billing VPS (38.68.14.188) - Isolated from Paymenter/Laravel routing — separate directory + port - API keys (Pterodactyl ptlc_, CurseForge) live server-side only - FTB packs: fully automatic via .manifest.json + FTB public API - CurseForge packs: reads manifest.json, needs CF Project ID + API key - config.php blocked from direct web access via Nginx PENDING AT DEPLOYMENT: - Verify port 8080 is free (ss -tlnp) before enabling Nginx block - Fill real API keys into config.php on server - Enter CurseForge Project IDs for CF packs (saved in localStorage) COLLABORATION: - PHP proxy architecture designed by Gemini (consultation session 2026-03-29) - Dashboard HTML and detection logic by Chronicler #47 - Gemini identified Laravel routing conflict and content-type gotcha WHY: - Interim solution before full Blueprint extension (post-launch) - Hands-off modpack update monitoring for staff - Zero manual checking required after initial CF Project ID setup Signed-off-by: claude@firefrostgaming.com --- .../DEPLOYMENT-GUIDE.md | 126 ++++ .../modpack-version-checker/dashboard.html | 546 ++++++++++++++++++ .../modpack-version-checker/proxy/config.php | 10 + .../modpack-version-checker/proxy/proxy.php | 71 +++ .../proxy/version-proxy.conf | 38 ++ 5 files changed, 791 insertions(+) create mode 100644 docs/tasks/modpack-version-checker/DEPLOYMENT-GUIDE.md create mode 100644 docs/tasks/modpack-version-checker/dashboard.html create mode 100644 docs/tasks/modpack-version-checker/proxy/config.php create mode 100644 docs/tasks/modpack-version-checker/proxy/proxy.php create mode 100644 docs/tasks/modpack-version-checker/proxy/version-proxy.conf diff --git a/docs/tasks/modpack-version-checker/DEPLOYMENT-GUIDE.md b/docs/tasks/modpack-version-checker/DEPLOYMENT-GUIDE.md new file mode 100644 index 0000000..e36e916 --- /dev/null +++ b/docs/tasks/modpack-version-checker/DEPLOYMENT-GUIDE.md @@ -0,0 +1,126 @@ +# Modpack Version Checker — Deployment Guide + +**Status:** READY TO DEPLOY +**Created:** 2026-03-29 +**Created By:** Chronicler #47 + Gemini (architecture consultation) +**Prerequisite:** PHP proxy must be deployed before the dashboard will work + +--- + +## Overview + +A browser-based dashboard that automatically checks all Pterodactyl game servers for modpack version status (up to date vs update available). Uses a PHP proxy on the Billing VPS to handle API calls securely — no API keys in the browser. + +**Platforms supported:** +- FTB — fully automatic (reads `.manifest.json`, compares against FTB public API) +- CurseForge — reads installed version from `manifest.json`; needs CF Project ID entered once per pack + CurseForge API key in `config.php` +- Modrinth — detects installed version; latest version lookup TBD + +--- + +## Files + +| File | Purpose | +|------|---------| +| `dashboard.html` | The browser dashboard — can be hosted anywhere | +| `proxy/proxy.php` | PHP proxy — deploy to Billing VPS | +| `proxy/config.php` | API keys config — deploy to Billing VPS, fill in real keys | +| `proxy/version-proxy.conf` | Nginx server block — deploy to Billing VPS | + +--- + +## Deployment Steps + +### Step 1: Verify Port 8080 is Free + +SSH to Billing VPS and run: + +```bash +ss -tlnp | grep 8080 +``` + +If 8080 is taken, pick 8081 or 8090. Update the port in: +- `version-proxy.conf` (`listen 8080;`) +- `dashboard.html` (`const PROXY_URL = ...`) + +### Step 2: Create Proxy Directory + +```bash +sudo mkdir -p /var/www/version-proxy +sudo chown -R www-data:www-data /var/www/version-proxy +``` + +### Step 3: Upload Proxy Files + +Copy `proxy.php` and `config.php` to `/var/www/version-proxy/` on the Billing VPS. + +### Step 4: Fill In Real Keys + +Edit `/var/www/version-proxy/config.php` with real values: +- `panel_key` — Pterodactyl client API key (`ptlc_NDkYX6yPPBHZacPmViFWtl4AvopzgxNcnHoQTOOtQEl`) +- `cf_key` — CurseForge API key (get from https://console.curseforge.com) + +### Step 5: Enable Nginx Config + +```bash +sudo cp version-proxy.conf /etc/nginx/sites-available/version-proxy.conf +sudo ln -s /etc/nginx/sites-available/version-proxy.conf /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +### Step 6: Open Firewall Port + +```bash +sudo ufw allow 8080/tcp +``` + +(Change 8080 to whichever port you confirmed is free.) + +### Step 7: Test the Proxy + +Open in browser: +``` +http://38.68.14.188:8080/proxy.php?action=servers +``` + +Should return JSON list of your Pterodactyl servers. + +### Step 8: Open the Dashboard + +Open `dashboard.html` in any browser and click **Check All**. + +--- + +## CurseForge Pack IDs + +For packs without automatic version detection, enter the CurseForge Project ID in the card's input field. The dashboard saves these in browser localStorage so you only enter them once. + +Known packs on your servers: + +| Server | Pack | CF Project ID | +|--------|------|---------------| +| Mythcraft 5 - NC | MYTHCRAFT 5 | (find on CurseForge) | +| Ars Eclectica - TX | Ars Eclectica | (find on CurseForge) | +| Create Plus - TX | Create V0.9.0 | (find on CurseForge) | +| Society: Sunlit Valley - TX | Society: Sunlit Valley | (find on CurseForge) | + +ATM10, ATM Sky, All The Mons — no version manifest detected on disk. Version will show "Not detected" until a manifest file exists. + +--- + +## Architecture Notes + +- PHP proxy lives at `/var/www/version-proxy/` — **isolated from Paymenter's Laravel routing** +- `config.php` is blocked from direct web access via Nginx (`location = /config.php { deny all; }`) +- FTB API calls are made directly from the browser (public API, no CORS issues) +- All Pterodactyl and CurseForge calls go through the proxy (API keys never reach the browser) +- CurseForge Project IDs stored in browser localStorage (persist between sessions) + +--- + +## Revision History + +| Version | Date | Author | Notes | +|---------|------|--------|-------| +| 1.0 | 2026-03-29 | Chronicler #47 + Gemini | Initial build. PHP proxy architecture by Gemini. Dashboard HTML by Chronicler #47. | diff --git a/docs/tasks/modpack-version-checker/dashboard.html b/docs/tasks/modpack-version-checker/dashboard.html new file mode 100644 index 0000000..e3577cc --- /dev/null +++ b/docs/tasks/modpack-version-checker/dashboard.html @@ -0,0 +1,546 @@ + + + + + +Firefrost — Modpack Version Checker + + + + +
+ +
+
Never checked
+ +
+
+ +
+
+
+
Up to Date
+
+
+
+
Outdated
+
+
+
+
Unknown
+
+
+
+
Total Servers
+
+
+ +
+
+ Click "Check All" to load servers and check versions. +
+
+ + + + + + diff --git a/docs/tasks/modpack-version-checker/proxy/config.php b/docs/tasks/modpack-version-checker/proxy/config.php new file mode 100644 index 0000000..9c353ef --- /dev/null +++ b/docs/tasks/modpack-version-checker/proxy/config.php @@ -0,0 +1,10 @@ + 'https://panel.firefrostgaming.com', + 'panel_key' => 'ptlc_YOUR_CLIENT_KEY', // Pterodactyl client API key (ptlc_...) + 'cf_key' => 'YOUR_CURSEFORGE_KEY' // CurseForge API key (optional, for CF version lookups) +]; diff --git a/docs/tasks/modpack-version-checker/proxy/proxy.php b/docs/tasks/modpack-version-checker/proxy/proxy.php new file mode 100644 index 0000000..b82a8ac --- /dev/null +++ b/docs/tasks/modpack-version-checker/proxy/proxy.php @@ -0,0 +1,71 @@ += 400) { + http_response_code($httpCode); + echo json_encode(['error' => "HTTP $httpCode"]); + exit; + } + return $result; +} + +$panelHeaders = [ + "Authorization: Bearer {$config['panel_key']}", + "Accept: application/json" +]; + +if ($action === 'servers') { + // List all servers + header('Content-Type: application/json'); + echo makeRequest("{$config['panel_url']}/api/client/servers", $panelHeaders); + +} elseif ($action === 'files') { + // List files in server root + header('Content-Type: application/json'); + $id = urlencode($_GET['server'] ?? ''); + echo makeRequest("{$config['panel_url']}/api/client/servers/{$id}/files/list", $panelHeaders); + +} elseif ($action === 'read') { + // Read a specific file from server filesystem + // Note: Pterodactyl returns raw text here, not JSON + header('Content-Type: text/plain'); + $id = urlencode($_GET['server'] ?? ''); + $file = urlencode($_GET['file'] ?? ''); + echo makeRequest("{$config['panel_url']}/api/client/servers/{$id}/files/contents?file={$file}", $panelHeaders); + +} elseif ($action === 'curseforge') { + // Get latest CurseForge mod files (API key stays server-side) + header('Content-Type: application/json'); + $projectId = urlencode($_GET['project'] ?? ''); + $cfHeaders = [ + "x-api-key: {$config['cf_key']}", + "Accept: application/json" + ]; + echo makeRequest("https://api.curseforge.com/v1/mods/{$projectId}/files?pageSize=1&sortField=5&sortOrder=desc", $cfHeaders); + +} else { + header('Content-Type: application/json'); + http_response_code(400); + echo json_encode(['error' => 'Invalid action']); +} diff --git a/docs/tasks/modpack-version-checker/proxy/version-proxy.conf b/docs/tasks/modpack-version-checker/proxy/version-proxy.conf new file mode 100644 index 0000000..11bda23 --- /dev/null +++ b/docs/tasks/modpack-version-checker/proxy/version-proxy.conf @@ -0,0 +1,38 @@ +# /etc/nginx/sites-available/version-proxy.conf +# Isolated Nginx block for the modpack version checker PHP proxy +# Hosted on Billing VPS (38.68.14.188) in its own directory +# to avoid conflicts with Paymenter (Laravel) and Mailcow routing. +# +# BEFORE ENABLING: verify port 8080 is free with `ss -tlnp` +# If 8080 is taken, change to 8081 or 8090 here AND in the HTML dashboard's PROXY_URL. + +server { + # Custom port — avoids Paymenter/Mailcow conflicts + # Verify with: ss -tlnp | grep 8080 + listen 8080; + + server_name _; + + root /var/www/version-proxy; + index proxy.php; + + location / { + try_files $uri $uri/ /proxy.php?$query_string; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + # PHP 8.3 socket (matches existing Billing VPS environment) + fastcgi_pass unix:/var/run/php/php8.3-fpm.sock; + } + + # Block access to config.php directly + location = /config.php { + deny all; + return 404; + } + + location ~ /\.ht { + deny all; + } +}