fix(headroom): support Docker sidecar proxy

Treat configured Headroom proxy as running when its /health endpoint
responds, even if local headroom CLI is not installed. Dashboard
Start/Stop stays limited to local loopback proxies while external
Docker sidecars can be enabled via HEADROOM_URL.

Closes #1948

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Carmelo Campos
2026-06-21 17:45:27 +07:00
committed by decolua
co-authored by Cursor
parent 096491d8d7
commit 50ed79fe9e
8 changed files with 140 additions and 40 deletions
+5 -1
View File
@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { getSettings } from "@/lib/localDb";
import { startHeadroomProxy } from "@/lib/headroom/process";
import { DEFAULT_HEADROOM_URL, isLoopbackHeadroomUrl } from "@/lib/headroom/detect";
export const dynamic = "force-dynamic";
@@ -16,7 +17,10 @@ function parsePortFromUrl(url) {
export async function POST() {
try {
const settings = await getSettings();
const url = settings.headroomUrl || "http://localhost:8787";
const url = settings.headroomUrl || DEFAULT_HEADROOM_URL;
if (!isLoopbackHeadroomUrl(url)) {
return NextResponse.json({ error: "External Headroom proxies must be started outside 9Router", code: "EXTERNAL_PROXY" }, { status: 400 });
}
const port = parsePortFromUrl(url) || 8787;
const result = await startHeadroomProxy({ port });
return NextResponse.json({ success: true, ...result });
+2 -2
View File
@@ -1,6 +1,6 @@
import { NextResponse } from "next/server";
import { getSettings } from "@/lib/localDb";
import { getHeadroomStatus } from "@/lib/headroom/detect";
import { DEFAULT_HEADROOM_URL, getHeadroomStatus } from "@/lib/headroom/detect";
import { getManagedPid } from "@/lib/headroom/process";
export const dynamic = "force-dynamic";
@@ -8,7 +8,7 @@ export const dynamic = "force-dynamic";
export async function GET() {
try {
const settings = await getSettings();
const url = settings.headroomUrl || "http://localhost:8787";
const url = settings.headroomUrl || DEFAULT_HEADROOM_URL;
const status = await getHeadroomStatus(url);
const managedPid = getManagedPid();
return NextResponse.json({ ...status, url, managedPid });