feat(caddy): optional root redirect per route

Add a redirect_path column to the caddy table and an optional 'root redirect'
field in the route form. When set, buildCaddyfile emits 'redir / <path>' so the
bare host (e.g. checkmk.domain.local/) redirects to a sub-path (e.g.
/monitoring/check_mk/) while every other path still passes through to the
backend — the safe pattern for apps like CheckMK that bake their site path into
absolute URLs. Defensive ALTER TABLE keeps existing databases working.
This commit is contained in:
Brückner
2026-06-10 10:22:39 +02:00
parent a2d515992c
commit 49cd0ae4f6
4 changed files with 54 additions and 28 deletions

View File

@ -86,15 +86,19 @@ db.exec(`
);
CREATE TABLE IF NOT EXISTS caddy (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT NOT NULL,
upstream TEXT NOT NULL,
tls INTEGER NOT NULL DEFAULT 1,
compress INTEGER NOT NULL DEFAULT 1,
created_at TEXT DEFAULT (datetime('now'))
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT NOT NULL,
upstream TEXT NOT NULL,
tls INTEGER NOT NULL DEFAULT 1,
compress INTEGER NOT NULL DEFAULT 1,
redirect_path TEXT NOT NULL DEFAULT '',
created_at TEXT DEFAULT (datetime('now'))
);
`);
// redirect_path was added later; ensure it exists on databases created before it.
try { db.exec("ALTER TABLE caddy ADD COLUMN redirect_path TEXT NOT NULL DEFAULT ''"); } catch { /* column already exists */ }
// Seed default settings — INSERT OR IGNORE writes a key only if it is absent.
const DEFAULT_SETTINGS: Record<string, string> = {
azure_enabled: 'false',
@ -139,6 +143,7 @@ export interface CaddyRoute {
upstream: string;
tls: number;
compress: number;
redirect_path: string;
created_at: string;
}
@ -146,16 +151,16 @@ export function getCaddyRoutes(): CaddyRoute[] {
return db.prepare('SELECT * FROM caddy ORDER BY id ASC').all() as CaddyRoute[];
}
export function addCaddyRoute(hostname: string, upstream: string, tls: boolean, compress: boolean): CaddyRoute {
export function addCaddyRoute(hostname: string, upstream: string, tls: boolean, compress: boolean, redirectPath = ''): CaddyRoute {
const { lastInsertRowid } = db.prepare(
'INSERT INTO caddy (hostname, upstream, tls, compress) VALUES (?, ?, ?, ?)'
).run(hostname, upstream, tls ? 1 : 0, compress ? 1 : 0);
'INSERT INTO caddy (hostname, upstream, tls, compress, redirect_path) VALUES (?, ?, ?, ?, ?)'
).run(hostname, upstream, tls ? 1 : 0, compress ? 1 : 0, redirectPath);
return db.prepare('SELECT * FROM caddy WHERE id = ?').get(lastInsertRowid) as CaddyRoute;
}
export function updateCaddyRoute(id: number, hostname: string, upstream: string, tls: boolean, compress: boolean): CaddyRoute {
db.prepare('UPDATE caddy SET hostname = ?, upstream = ?, tls = ?, compress = ? WHERE id = ?')
.run(hostname, upstream, tls ? 1 : 0, compress ? 1 : 0, id);
export function updateCaddyRoute(id: number, hostname: string, upstream: string, tls: boolean, compress: boolean, redirectPath = ''): CaddyRoute {
db.prepare('UPDATE caddy SET hostname = ?, upstream = ?, tls = ?, compress = ?, redirect_path = ? WHERE id = ?')
.run(hostname, upstream, tls ? 1 : 0, compress ? 1 : 0, redirectPath, id);
return db.prepare('SELECT * FROM caddy WHERE id = ?').get(id) as CaddyRoute;
}