From da5955412d9b3402c8d4e0178ae33cfd478e610d Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 25 Feb 2026 08:13:38 +1000 Subject: [PATCH] Command to regenerate nginx configs --- backend/package.json | 3 +- backend/scripts/regenerate-config | 104 ++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100755 backend/scripts/regenerate-config diff --git a/backend/package.json b/backend/package.json index d06fc297..827eacb6 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,7 +9,8 @@ "scripts": { "lint": "biome lint", "prettier": "biome format --write .", - "validate-schema": "node validate-schema.js" + "validate-schema": "node validate-schema.js", + "regenerate-config": "node scripts/regenerate-config" }, "dependencies": { "@apidevtools/json-schema-ref-parser": "^15.2.2", diff --git a/backend/scripts/regenerate-config b/backend/scripts/regenerate-config new file mode 100755 index 00000000..1254ded8 --- /dev/null +++ b/backend/scripts/regenerate-config @@ -0,0 +1,104 @@ +#!/usr/bin/env node + +import * as process from "node:process"; // Use the node: protocol for built-ins +import internalNginx from "../internal/nginx.js"; +import { castJsonIfNeed } from "../lib/helpers.js"; +import { global as logger } from "../logger.js"; +import deadHostModel from "../models/dead_host.js"; +import proxyHostModel from "../models/proxy_host.js"; +import redirectionHostModel from "../models/redirection_host.js"; +import streamModel from "../models/stream.js"; + +const args = process.argv.slice(2); +const UNATTENDED = args.includes("-y") || args.includes("--yes"); +if (args.includes("--help")) { + console.log("Usage: ./regenerate-config [--help] [-y|--yes]"); +} + +// ask for the user to confirm the action if not in unattended mode +if (!UNATTENDED) { + const readline = await import("node:readline"); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const question = (query) => + new Promise((resolve) => rl.question(query, resolve)); + + const answer = await question( + "This will iterate over all Hosts and regnerate their Nginx configs.\n\nAre you sure you want to proceed? (y/N) ", + ); + rl.close(); + + if (answer.toLowerCase() !== "y") { + console.log("Aborting."); + process.exit(0); + } +} + +// Let's do it. + +// Proxy hosts +const proxyRows = await proxyHostModel + .query() + .where("is_deleted", 0) + .andWhere("enabled", 1) + .groupBy("id") + .allowGraph("[owner,access_list,certificate]") + .orderBy(castJsonIfNeed("domain_names"), "ASC"); + +for (const row of proxyRows) { + logger.info( + `Regenerating config for Proxy Host #${row.id}: ${row.domain_names.join(", ")}`, + ); + await internalNginx.configure(proxyHostModel, "proxy_host", row); +} + +// Redirection hosts +const redirectionRows = await redirectionHostModel + .query() + .where("is_deleted", 0) + .andWhere("enabled", 1) + .groupBy("id") + .allowGraph("[owner,access_list,certificate]") + .orderBy(castJsonIfNeed("domain_names"), "ASC"); + +for (const row of redirectionRows) { + logger.info( + `Regenerating config for Redirection Host #${row.id}: ${row.domain_names.join(", ")}`, + ); + await internalNginx.configure(redirectionHostModel, "redirection_host", row); +} + +// 404 hosts +const deadRows = await deadHostModel + .query() + .where("is_deleted", 0) + .andWhere("enabled", 1) + .groupBy("id") + .allowGraph("[owner,access_list,certificate]") + .orderBy(castJsonIfNeed("domain_names"), "ASC"); + +for (const row of deadRows) { + logger.info( + `Regenerating config for 404 Host #${row.id}: ${row.domain_names.join(", ")}`, + ); + await internalNginx.configure(deadHostModel, "dead_host", row); +} + +// Streams +const streamRows = await streamModel + .query() + .where("is_deleted", 0) + .andWhere("enabled", 1) + .groupBy("id") + .allowGraph("[owner,access_list,certificate]"); + +for (const row of streamRows) { + logger.info(`Regenerating config for Stream #${row.id}: ${row.incoming_port} -> ${row.forwarding_host}:${row.forwarding_port}`); + await internalNginx.configure(deadHostModel, "stream", row); +} + +logger.success("Completed"); +process.exit(0);