mirror of
https://git.meshkee.com/Meshkee/dashboards.git
synced 2026-08-11 22:30:58 +04:30
Ensure per-row SSL for apex, business.*, and customer.* hosts.
Lock icon probes live TLS and issues only missing certs; toast z-index sits above modals; ssl-sync agent supports blocking wait. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
aeaad0f645
commit
0212148a73
@@ -1,13 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Tiny HTTP agent on the dashboards VPS.
|
||||
* Super Admin → Nest API → POST here → runs ssl-sync.sh in the background.
|
||||
* Super Admin → Nest API → POST here → runs ssl-sync.sh
|
||||
*
|
||||
* Env (/etc/meshkee/ssl-sync-agent.env):
|
||||
* SSL_SYNC_AGENT_TOKEN=...
|
||||
* SSL_SYNC_SCRIPT=/opt/meshkee/dashboards/deploy/ssl-sync.sh
|
||||
* PORT=9051
|
||||
* BIND=0.0.0.0
|
||||
*
|
||||
* POST /ssl-sync
|
||||
* Body (optional JSON): { "wait": true }
|
||||
* wait=false (default): accept and run in background → 202
|
||||
* wait=true: run script and wait for exit → 200 / 500
|
||||
*/
|
||||
import { createServer } from 'node:http'
|
||||
import { spawn } from 'node:child_process'
|
||||
@@ -42,7 +47,24 @@ function json(res, status, body) {
|
||||
res.end(payload)
|
||||
}
|
||||
|
||||
function startSync() {
|
||||
function readJson(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks = []
|
||||
req.on('data', (c) => chunks.push(c))
|
||||
req.on('end', () => {
|
||||
const raw = Buffer.concat(chunks).toString('utf8').trim()
|
||||
if (!raw) return resolve({})
|
||||
try {
|
||||
resolve(JSON.parse(raw))
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
req.on('error', reject)
|
||||
})
|
||||
}
|
||||
|
||||
function startSyncDetached() {
|
||||
running = true
|
||||
const child = spawn(SCRIPT, [], {
|
||||
detached: true,
|
||||
@@ -62,7 +84,45 @@ function startSync() {
|
||||
child.unref()
|
||||
}
|
||||
|
||||
const server = createServer((req, res) => {
|
||||
function runSyncAndWait() {
|
||||
return new Promise((resolve) => {
|
||||
running = true
|
||||
const child = spawn(SCRIPT, [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
env: process.env,
|
||||
})
|
||||
let stdout = ''
|
||||
let stderr = ''
|
||||
child.stdout.on('data', (d) => {
|
||||
stdout += d.toString()
|
||||
})
|
||||
child.stderr.on('data', (d) => {
|
||||
stderr += d.toString()
|
||||
})
|
||||
child.on('error', (err) => {
|
||||
running = false
|
||||
resolve({
|
||||
ok: false,
|
||||
code: 1,
|
||||
log: err.message,
|
||||
})
|
||||
})
|
||||
child.on('exit', (code, signal) => {
|
||||
running = false
|
||||
const log = `${stdout}${stderr}`.trim().slice(-4000)
|
||||
console.log(
|
||||
`${new Date().toISOString()} ssl-sync waited code=${code} signal=${signal ?? ''}`,
|
||||
)
|
||||
resolve({
|
||||
ok: code === 0,
|
||||
code: code ?? 1,
|
||||
log,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const server = createServer(async (req, res) => {
|
||||
if (req.method === 'GET' && req.url === '/health') {
|
||||
return json(res, 200, { ok: true, running })
|
||||
}
|
||||
@@ -80,7 +140,34 @@ const server = createServer((req, res) => {
|
||||
return json(res, 409, { error: 'ssl sync already running' })
|
||||
}
|
||||
|
||||
startSync()
|
||||
let body = {}
|
||||
try {
|
||||
body = await readJson(req)
|
||||
} catch {
|
||||
return json(res, 400, { error: 'invalid json' })
|
||||
}
|
||||
|
||||
const wait = body && body.wait === true
|
||||
|
||||
if (wait) {
|
||||
console.log(`${new Date().toISOString()} ssl-sync wait start`)
|
||||
const result = await runSyncAndWait()
|
||||
if (!result.ok) {
|
||||
return json(res, 500, {
|
||||
status: 'failed',
|
||||
message: 'SSL sync script failed',
|
||||
code: result.code,
|
||||
log: result.log,
|
||||
})
|
||||
}
|
||||
return json(res, 200, {
|
||||
status: 'ok',
|
||||
message: 'SSL sync completed',
|
||||
log: result.log,
|
||||
})
|
||||
}
|
||||
|
||||
startSyncDetached()
|
||||
console.log(`${new Date().toISOString()} ssl-sync accepted`)
|
||||
return json(res, 202, {
|
||||
status: 'accepted',
|
||||
|
||||
Reference in New Issue
Block a user