Add /health-status endpoint for live HTTP health checks

Parallel-fetches /health on each app LXC, returns up/down + response
time. Used by the portal Uptime tab instead of embedding Uptime Kuma.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-01 17:34:56 +00:00
parent 78f29ff0d0
commit 5b3b45a45c

View file

@ -17,6 +17,17 @@ const deployLog = []
const statusCache = {}
const CACHE_TTL = 5 * 60 * 1000
const healthMap = {
'portal': { host: '10.10.10.102', port: 3000 },
'auth': { host: '10.10.10.101', port: 3001 },
'noticeboard': { host: '10.10.10.112', port: 3080 },
'kitchen': { host: '10.10.10.110', port: 3080 },
'cashup': { host: '10.10.10.111', port: 3080 },
'housekeeping': { host: '10.10.10.114', port: 3080 },
'forecasting': { host: '10.10.10.113', port: 3080 },
'rates': { host: '10.10.10.115', port: 3080 },
}
function verifySignature(body, signature) {
if (!WEBHOOK_SECRET) return true
const expected = `sha256=${crypto.createHmac('sha256', WEBHOOK_SECRET).update(body).digest('hex')}`
@ -95,6 +106,23 @@ async function deploy(target, repoName) {
app.get('/health', async () => ({ status: 'healthy' }))
app.get('/health-status', async () => {
const results = await Promise.all(
Object.entries(healthMap).map(async ([name, { host, port }]) => {
const t0 = Date.now()
try {
const res = await fetch(`http://${host}:${port}/health`, {
signal: AbortSignal.timeout(3000),
})
return { name, up: res.ok, ms: Date.now() - t0 }
} catch {
return { name, up: false, ms: null }
}
})
)
return results
})
app.get('/deploys', async () => deployLog)
app.get('/status', async (request) => {