From 807911d026c9439a0684110429cec00510e5eb8b Mon Sep 17 00:00:00 2001 From: Hendrik Date: Fri, 1 May 2026 19:09:45 +0200 Subject: [PATCH] =?UTF-8?q?v0.1.10=20=E2=80=94=20caddy=20reload=20via=20'c?= =?UTF-8?q?addy=20reload'=20CLI=20(avoids=20admin=20API=20Origin=20403)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/caddy.ts | 36 ++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/caddy.ts b/lib/caddy.ts index e78d2b4..88b5546 100644 --- a/lib/caddy.ts +++ b/lib/caddy.ts @@ -1,7 +1,11 @@ import fs from "fs/promises"; import path from "path"; +import { exec } from "child_process"; +import { promisify } from "util"; import { getDb, getSetting, type DomainRow, type DomainGroupRow } from "./db"; +const execAsync = promisify(exec); + const CADDYFILE_PATH = process.env.NEXREDIRECT_CADDYFILE || "/etc/caddy/Caddyfile"; const CADDY_ADMIN = process.env.CADDY_ADMIN_URL || "http://localhost:2019"; const APP_PORT = process.env.PORT || "3000"; @@ -62,17 +66,29 @@ export async function writeCaddyfile(): Promise { export async function reloadCaddy(): Promise<{ ok: boolean; error?: string }> { try { await writeCaddyfile(); - const adapt = await fetch(`${CADDY_ADMIN}/load`, { - method: "POST", - headers: { "Content-Type": "text/caddyfile" }, - body: buildCaddyfile(), - }); - if (!adapt.ok) { - const text = await adapt.text().catch(() => ""); - return { ok: false, error: `Caddy load failed: ${adapt.status} ${text}` }; - } + } catch (e) { + return { ok: false, error: `write Caddyfile failed: ${e instanceof Error ? e.message : String(e)}` }; + } + + // Try shell `caddy reload` first — it talks to admin API as caddy itself, no Origin-header issues. + try { + await execAsync(`caddy reload --config ${CADDYFILE_PATH} --address localhost:2019`, { timeout: 30_000 }); return { ok: true }; } catch (e) { - return { ok: false, error: e instanceof Error ? e.message : String(e) }; + // Fall back to direct admin API POST (older Caddy / different admin URL). + try { + const adapt = await fetch(`${CADDY_ADMIN}/load`, { + method: "POST", + headers: { "Content-Type": "text/caddyfile", Origin: "" }, + body: buildCaddyfile(), + }); + if (!adapt.ok) { + const text = await adapt.text().catch(() => ""); + return { ok: false, error: `caddy reload failed: ${e instanceof Error ? e.message : String(e)} | api fallback: ${adapt.status} ${text}` }; + } + return { ok: true }; + } catch (e2) { + return { ok: false, error: `caddy reload + api fallback both failed: ${e instanceof Error ? e.message : String(e)} ; ${e2 instanceof Error ? e2.message : String(e2)}` }; + } } } diff --git a/package.json b/package.json index 343bec3..4ccce5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "corex-nexredirect", - "version": "0.1.9", + "version": "0.1.10", "license": "MIT", "overrides": { "postcss": "^8.5.13",