← back to Security Dashboard
prod-ready: env PORT + PROBE_LOCAL on-box probe mode, /api/health, relative api/status fetch (subpath-safe), ecosystem.config.cjs (:9769), .deploy.conf
3b1fd390596e144d52f9488b6848356e935df5e2 · 2026-05-31 19:59:52 -0700 · SteveStudio2
Files touched
A .deploy.confA ecosystem.config.cjsM public/index.htmlM server.js
Diff
commit 3b1fd390596e144d52f9488b6848356e935df5e2
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Sun May 31 19:59:52 2026 -0700
prod-ready: env PORT + PROBE_LOCAL on-box probe mode, /api/health, relative api/status fetch (subpath-safe), ecosystem.config.cjs (:9769), .deploy.conf
---
.deploy.conf | 5 +++++
ecosystem.config.cjs | 12 ++++++++++++
public/index.html | 2 +-
server.js | 20 +++++++++++++++++---
4 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/.deploy.conf b/.deploy.conf
new file mode 100644
index 0000000..05b905f
--- /dev/null
+++ b/.deploy.conf
@@ -0,0 +1,5 @@
+PROJECT_NAME="security-dashboard"
+DEPLOY_PATH="/root/public-projects/security-dashboard"
+HEALTH_URL="http://127.0.0.1:9769/api/health"
+# zero-dependency (no package.json) — skip npm install on remote
+INSTALL_CMD="true"
diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs
new file mode 100644
index 0000000..ffd803b
--- /dev/null
+++ b/ecosystem.config.cjs
@@ -0,0 +1,12 @@
+// prod (Kamatera) launch — PROBE_LOCAL makes the probe run on-box instead of
+// ssh-ing to itself; served behind admin.agentabrams.com/security/ (IP-locked).
+module.exports = {
+ apps: [{
+ name: 'security-dashboard',
+ script: 'server.js',
+ cwd: '/root/public-projects/security-dashboard',
+ env: { PORT: '9769', PROBE_LOCAL: '1' },
+ autorestart: true,
+ max_memory_restart: '150M',
+ }],
+};
diff --git a/public/index.html b/public/index.html
index 555035b..e06deff 100644
--- a/public/index.html
+++ b/public/index.html
@@ -225,7 +225,7 @@ function render(d){
async function load(force){
try{
- const r=await fetch('/api/status'+(force?'?t='+Date.now():''));
+ const r=await fetch('api/status'+(force?'?t='+Date.now():''));
render(await r.json());
}catch(e){ document.getElementById('checked').innerHTML='<span style="color:var(--red)">probe failed</span>'; }
}
diff --git a/server.js b/server.js
index 85c36c7..5f5893d 100644
--- a/server.js
+++ b/server.js
@@ -7,7 +7,7 @@ const fs = require('fs');
const path = require('path');
const { execFile } = require('child_process');
-const PORT = 9768;
+const PORT = parseInt(process.env.PORT || '9768', 10);
const PUBLIC = path.join(__dirname, 'public');
const REGISTRY = `${process.env.HOME}/Projects/secrets-manager/registry.json`;
@@ -37,9 +37,18 @@ echo "UFW_DEFAULT=$UFW_DEFAULT"
echo "UID0_BACKDOOR=\${PAKCHOI:-none}"
`;
+// On Mac (dev) we reach prod via the `ssh my-server` alias. When this app is
+// itself hosted ON prod (PROBE_LOCAL=1), localhost IS prod — run the probe
+// script directly with `bash -s` instead of ssh-ing to ourselves.
+const PROBE_LOCAL = process.env.PROBE_LOCAL === '1';
+
function probeProd() {
return new Promise((resolve) => {
- execFile('ssh', ['my-server', 'bash -s'], { timeout: 25_000 }, (err, stdout) => {
+ const child = PROBE_LOCAL
+ ? execFile('bash', ['-s'], { timeout: 25_000 }, onDone)
+ : execFile('ssh', ['my-server', 'bash -s'], { timeout: 25_000 }, onDone);
+ child.stdin.end(PROBE);
+ function onDone(err, stdout) {
const kv = {};
(stdout || '').split('\n').forEach((l) => {
const i = l.indexOf('=');
@@ -47,7 +56,7 @@ function probeProd() {
});
kv._error = err ? String(err.message || err).slice(0, 120) : null;
resolve(kv);
- }).stdin.end(PROBE);
+ }
});
}
@@ -90,6 +99,11 @@ async function status() {
}
const server = http.createServer(async (req, res) => {
+ if (req.url === '/api/health') {
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
+ res.end(JSON.stringify({ status: 'ok', probe: PROBE_LOCAL ? 'local' : 'ssh' }));
+ return;
+ }
if (req.url === '/api/status') {
try {
const data = await status();
← cf95d58 dashboard: mark 3 leaks env-ified (code closed; still rotate
·
back to Security Dashboard
·
gitignore: add missing standard excludes (dist/ build/ .next 30cc8fb →