diff --git a/app/(dashboard)/proxy-hosts/ProxyHostsClient.tsx b/app/(dashboard)/proxy-hosts/ProxyHostsClient.tsx
index 83a13b26..be9ef1a4 100644
--- a/app/(dashboard)/proxy-hosts/ProxyHostsClient.tsx
+++ b/app/(dashboard)/proxy-hosts/ProxyHostsClient.tsx
@@ -84,16 +84,10 @@ export default function ProxyHostsClient({ hosts, certificates, accessLists, aut
id: "upstreams",
label: "Target",
render: (host: ProxyHost) => (
- host.response_mode === "static" ? (
-
- Static Response ({host.static_status_code ?? 503})
-
- ) : (
-
- {host.upstreams[0]}
- {host.upstreams.length > 1 && ` +${host.upstreams.length - 1} more`}
-
- )
+
+ {host.upstreams[0]}
+ {host.upstreams.length > 1 && ` +${host.upstreams.length - 1} more`}
+
)
},
{
diff --git a/app/(dashboard)/proxy-hosts/actions.ts b/app/(dashboard)/proxy-hosts/actions.ts
index 921b6f4c..1ec3e10d 100644
--- a/app/(dashboard)/proxy-hosts/actions.ts
+++ b/app/(dashboard)/proxy-hosts/actions.ts
@@ -3,7 +3,7 @@
import { revalidatePath } from "next/cache";
import { requireAdmin } from "@/src/lib/auth";
import { actionError, actionSuccess, INITIAL_ACTION_STATE, type ActionState } from "@/src/lib/actions";
-import { createProxyHost, deleteProxyHost, updateProxyHost, type ProxyHostAuthentikInput, type LoadBalancerInput, type LoadBalancingPolicy, type DnsResolverInput, type ResponseMode } from "@/src/lib/models/proxy-hosts";
+import { createProxyHost, deleteProxyHost, updateProxyHost, type ProxyHostAuthentikInput, type LoadBalancerInput, type LoadBalancingPolicy, type DnsResolverInput } from "@/src/lib/models/proxy-hosts";
import { getCertificate } from "@/src/lib/models/certificates";
import { getCloudflareSettings } from "@/src/lib/settings";
@@ -270,28 +270,6 @@ function parseLoadBalancerConfig(formData: FormData): LoadBalancerInput | undefi
return Object.keys(result).length > 0 ? result : undefined;
}
-function parseResponseMode(value: FormDataEntryValue | null): ResponseMode {
- if (!value || typeof value !== "string") {
- return "proxy";
- }
- return value === "static" ? "static" : "proxy";
-}
-
-function parseStatusCode(value: FormDataEntryValue | null): number | null {
- if (!value || typeof value !== "string") {
- return null;
- }
- const trimmed = value.trim();
- if (trimmed === "") {
- return null;
- }
- const num = parseInt(trimmed, 10);
- if (!Number.isFinite(num) || num < 100 || num > 599) {
- return 200;
- }
- return num;
-}
-
function parseDnsResolverConfig(formData: FormData): DnsResolverInput | undefined {
if (!formData.has("dns_present")) {
return undefined;
@@ -370,8 +348,6 @@ export async function createProxyHostAction(
console.warn(`[createProxyHostAction] ${warning}`);
}
- const responseMode = parseResponseMode(formData.get("response_mode"));
-
await createProxyHost(
{
name: String(formData.get("name") ?? "Untitled"),
@@ -386,10 +362,7 @@ export async function createProxyHostAction(
custom_reverse_proxy_json: parseOptionalText(formData.get("custom_reverse_proxy_json")),
authentik: parseAuthentikConfig(formData),
load_balancer: parseLoadBalancerConfig(formData),
- dns_resolver: parseDnsResolverConfig(formData),
- response_mode: responseMode,
- static_status_code: parseStatusCode(formData.get("static_status_code")),
- static_response_body: parseOptionalText(formData.get("static_response_body"))
+ dns_resolver: parseDnsResolverConfig(formData)
},
userId
);
@@ -437,8 +410,6 @@ export async function updateProxyHostAction(
}
}
- const responseMode = formData.has("response_mode") ? parseResponseMode(formData.get("response_mode")) : undefined;
-
await updateProxyHost(
id,
{
@@ -460,10 +431,7 @@ export async function updateProxyHostAction(
: undefined,
authentik: parseAuthentikConfig(formData),
load_balancer: parseLoadBalancerConfig(formData),
- dns_resolver: parseDnsResolverConfig(formData),
- response_mode: responseMode,
- static_status_code: formData.has("static_status_code") ? parseStatusCode(formData.get("static_status_code")) : undefined,
- static_response_body: formData.has("static_response_body") ? parseOptionalText(formData.get("static_response_body")) : undefined
+ dns_resolver: parseDnsResolverConfig(formData)
},
userId
);
diff --git a/drizzle/0005_remove_static_response.sql b/drizzle/0005_remove_static_response.sql
new file mode 100644
index 00000000..1e1892f9
--- /dev/null
+++ b/drizzle/0005_remove_static_response.sql
@@ -0,0 +1,4 @@
+-- Remove static response feature columns from proxy_hosts
+ALTER TABLE `proxy_hosts` DROP COLUMN `response_mode`;
+ALTER TABLE `proxy_hosts` DROP COLUMN `static_status_code`;
+ALTER TABLE `proxy_hosts` DROP COLUMN `static_response_body`;
diff --git a/src/components/proxy-hosts/HostDialogs.tsx b/src/components/proxy-hosts/HostDialogs.tsx
index 9df93754..e86db51a 100644
--- a/src/components/proxy-hosts/HostDialogs.tsx
+++ b/src/components/proxy-hosts/HostDialogs.tsx
@@ -1,7 +1,7 @@
-import { Alert, Box, FormControl, FormControlLabel, FormLabel, MenuItem, Radio, RadioGroup, Stack, TextField, Typography } from "@mui/material";
+import { Alert, Box, MenuItem, Stack, TextField, Typography } from "@mui/material";
import { useFormState } from "react-dom";
-import { useEffect, useState } from "react";
+import { useEffect } from "react";
import {
createProxyHostAction,
deleteProxyHostAction,
@@ -10,7 +10,7 @@ import {
import { INITIAL_ACTION_STATE } from "@/src/lib/actions";
import { AccessList } from "@/src/lib/models/access-lists";
import { Certificate } from "@/src/lib/models/certificates";
-import { ProxyHost, ResponseMode } from "@/src/lib/models/proxy-hosts";
+import { ProxyHost } from "@/src/lib/models/proxy-hosts";
import { AuthentikSettings } from "@/src/lib/settings";
import { AppDialog } from "@/src/components/ui/AppDialog";
import { AuthentikFields } from "./AuthentikFields";
@@ -35,7 +35,6 @@ export function CreateHostDialog({
initialData?: ProxyHost | null;
}) {
const [state, formAction] = useFormState(createProxyHostAction, INITIAL_ACTION_STATE);
- const [responseMode, setResponseMode] = useState(initialData?.response_mode ?? "proxy");
useEffect(() => {
if (state.status === "success") {
@@ -43,13 +42,6 @@ export function CreateHostDialog({
}
}, [state.status, onClose]);
- // Reset response mode when dialog opens/closes
- useEffect(() => {
- if (open) {
- setResponseMode(initialData?.response_mode ?? "proxy");
- }
- }, [open, initialData]);
-
return (
-
- Response Mode
- setResponseMode(e.target.value as ResponseMode)}
- >
- } label="Proxy to Upstream" />
- } label="Static Response" />
-
-
- {responseMode === "proxy" && (
-
- )}
- {responseMode === "static" && (
- <>
-
-
- >
- )}
+
{certificates.map((cert) => (
@@ -187,7 +143,6 @@ export function EditHostDialog({
accessLists: AccessList[];
}) {
const [state, formAction] = useFormState(updateProxyHostAction.bind(null, host.id), INITIAL_ACTION_STATE);
- const [responseMode, setResponseMode] = useState(host.response_mode);
useEffect(() => {
if (state.status === "success") {
@@ -195,11 +150,6 @@ export function EditHostDialog({
}
}, [state.status, onClose]);
- // Reset response mode when host changes
- useEffect(() => {
- setResponseMode(host.response_mode);
- }, [host]);
-
return (
-
- Response Mode
- setResponseMode(e.target.value as ResponseMode)}
- >
- } label="Proxy to Upstream" />
- } label="Static Response" />
-
-
- {responseMode === "proxy" && (
-
- )}
- {responseMode === "static" && (
- <>
-
-
- >
- )}
+
{certificates.map((cert) => (
diff --git a/src/lib/caddy.ts b/src/lib/caddy.ts
index 5838fb4b..371e433e 100644
--- a/src/lib/caddy.ts
+++ b/src/lib/caddy.ts
@@ -47,9 +47,6 @@ type ProxyHostRow = {
skip_https_hostname_validation: number;
meta: string | null;
enabled: number;
- response_mode: string;
- static_status_code: number | null;
- static_response_body: string | null;
};
type DnsResolverMeta = {
@@ -326,58 +323,7 @@ function buildProxyRoutes(
continue;
}
- // Handle static response mode
- if (row.response_mode === "static") {
- const staticHandlers: Record[] = [];
-
- // Build static response handler
- const staticResponseHandler: Record = {
- handler: "static_response",
- status_code: row.static_status_code ?? 200,
- body: row.static_response_body ?? ""
- };
-
- // Add HSTS header if enabled
- if (row.hsts_enabled) {
- const hstsValue = row.hsts_subdomains ? "max-age=63072000; includeSubDomains" : "max-age=63072000";
- staticResponseHandler.headers = {
- "Strict-Transport-Security": [hstsValue]
- };
- }
-
- staticHandlers.push(staticResponseHandler);
-
- // SSL redirect for static responses
- if (row.ssl_forced) {
- routes.push({
- match: [
- {
- host: domains,
- expression: '{http.request.scheme} == "http"'
- }
- ],
- handle: [
- {
- handler: "static_response",
- status_code: 308,
- headers: {
- Location: ["https://{http.request.host}{http.request.uri}"]
- }
- }
- ],
- terminal: true
- });
- }
-
- routes.push({
- match: [{ host: domains }],
- handle: staticHandlers,
- terminal: true
- });
- continue;
- }
-
- // Proxy mode: require upstreams
+ // Require upstreams
const upstreams = parseJson(row.upstreams, []);
if (upstreams.length === 0) {
continue;
@@ -977,10 +923,7 @@ async function buildCaddyDocument() {
preserveHostHeader: proxyHosts.preserveHostHeader,
skipHttpsHostnameValidation: proxyHosts.skipHttpsHostnameValidation,
meta: proxyHosts.meta,
- enabled: proxyHosts.enabled,
- responseMode: proxyHosts.responseMode,
- staticStatusCode: proxyHosts.staticStatusCode,
- staticResponseBody: proxyHosts.staticResponseBody
+ enabled: proxyHosts.enabled
})
.from(proxyHosts),
db
@@ -1029,10 +972,7 @@ async function buildCaddyDocument() {
preserve_host_header: h.preserveHostHeader ? 1 : 0,
skip_https_hostname_validation: h.skipHttpsHostnameValidation ? 1 : 0,
meta: h.meta,
- enabled: h.enabled ? 1 : 0,
- response_mode: h.responseMode,
- static_status_code: h.staticStatusCode,
- static_response_body: h.staticResponseBody
+ enabled: h.enabled ? 1 : 0
}));
const redirectHostRows: RedirectHostRow[] = redirectHostRecords.map((h) => ({
diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts
index 8036951e..5b200050 100644
--- a/src/lib/db/schema.ts
+++ b/src/lib/db/schema.ts
@@ -147,12 +147,7 @@ export const proxyHosts = sqliteTable("proxy_hosts", {
updatedAt: text("updated_at").notNull(),
skipHttpsHostnameValidation: integer("skip_https_hostname_validation", { mode: "boolean" })
.notNull()
- .default(false),
- // Response mode: 'proxy' (default) or 'static'
- responseMode: text("response_mode").notNull().default("proxy"),
- // Static response fields (used when responseMode is 'static')
- staticStatusCode: integer("static_status_code").default(200),
- staticResponseBody: text("static_response_body")
+ .default(false)
});
export const redirectHosts = sqliteTable("redirect_hosts", {
diff --git a/src/lib/models/proxy-hosts.ts b/src/lib/models/proxy-hosts.ts
index b5bb4f91..2760ece7 100644
--- a/src/lib/models/proxy-hosts.ts
+++ b/src/lib/models/proxy-hosts.ts
@@ -176,8 +176,6 @@ type ProxyHostMeta = {
dns_resolver?: DnsResolverMeta;
};
-export type ResponseMode = "proxy" | "static";
-
export type ProxyHost = {
id: number;
name: string;
@@ -199,15 +197,12 @@ export type ProxyHost = {
authentik: ProxyHostAuthentikConfig | null;
load_balancer: LoadBalancerConfig | null;
dns_resolver: DnsResolverConfig | null;
- response_mode: ResponseMode;
- static_status_code: number | null;
- static_response_body: string | null;
};
export type ProxyHostInput = {
name: string;
domains: string[];
- upstreams?: string[];
+ upstreams: string[];
certificate_id?: number | null;
access_list_id?: number | null;
ssl_forced?: boolean;
@@ -222,9 +217,6 @@ export type ProxyHostInput = {
authentik?: ProxyHostAuthentikInput | null;
load_balancer?: LoadBalancerInput | null;
dns_resolver?: DnsResolverInput | null;
- response_mode?: ResponseMode;
- static_status_code?: number | null;
- static_response_body?: string | null;
};
type ProxyHostRow = typeof proxyHosts.$inferSelect;
@@ -1141,7 +1133,6 @@ function dehydrateDnsResolver(config: DnsResolverConfig | null): DnsResolverMeta
function parseProxyHost(row: ProxyHostRow): ProxyHost {
const meta = parseMeta(row.meta ?? null);
- const responseMode = row.responseMode === "static" ? "static" : "proxy";
return {
id: row.id,
name: row.name,
@@ -1162,10 +1153,7 @@ function parseProxyHost(row: ProxyHostRow): ProxyHost {
custom_pre_handlers_json: meta.custom_pre_handlers_json ?? null,
authentik: hydrateAuthentik(meta.authentik),
load_balancer: hydrateLoadBalancer(meta.load_balancer),
- dns_resolver: hydrateDnsResolver(meta.dns_resolver),
- response_mode: responseMode,
- static_status_code: row.staticStatusCode ?? null,
- static_response_body: row.staticResponseBody ?? null
+ dns_resolver: hydrateDnsResolver(meta.dns_resolver)
};
}
@@ -1179,22 +1167,18 @@ export async function createProxyHost(input: ProxyHostInput, actorUserId: number
throw new Error("At least one domain must be specified");
}
- const responseMode = input.response_mode === "static" ? "static" : "proxy";
-
- // Only require upstreams in proxy mode
- if (responseMode === "proxy" && (!input.upstreams || input.upstreams.length === 0)) {
- throw new Error("At least one upstream must be specified for proxy mode");
+ if (!input.upstreams || input.upstreams.length === 0) {
+ throw new Error("At least one upstream must be specified");
}
const now = nowIso();
const meta = buildMeta({}, input);
- const upstreams = input.upstreams ?? [];
const [record] = await db
.insert(proxyHosts)
.values({
name: input.name.trim(),
domains: JSON.stringify(Array.from(new Set(input.domains.map((d) => d.trim().toLowerCase())))),
- upstreams: JSON.stringify(Array.from(new Set(upstreams.map((u) => u.trim())))),
+ upstreams: JSON.stringify(Array.from(new Set(input.upstreams.map((u) => u.trim())))),
certificateId: input.certificate_id ?? null,
accessListId: input.access_list_id ?? null,
ownerUserId: actorUserId,
@@ -1207,10 +1191,7 @@ export async function createProxyHost(input: ProxyHostInput, actorUserId: number
skipHttpsHostnameValidation: input.skip_https_hostname_validation ?? false,
enabled: input.enabled ?? true,
createdAt: now,
- updatedAt: now,
- responseMode,
- staticStatusCode: input.static_status_code ?? 200,
- staticResponseBody: input.static_response_body ?? null
+ updatedAt: now
})
.returning();
@@ -1244,10 +1225,6 @@ export async function updateProxyHost(id: number, input: Partial
throw new Error("Proxy host not found");
}
- const responseMode = input.response_mode !== undefined
- ? (input.response_mode === "static" ? "static" : "proxy")
- : existing.response_mode;
-
const domains = input.domains ? JSON.stringify(Array.from(new Set(input.domains))) : JSON.stringify(existing.domains);
const upstreams = input.upstreams ? JSON.stringify(Array.from(new Set(input.upstreams))) : JSON.stringify(existing.upstreams);
const existingMeta: ProxyHostMeta = {
@@ -1276,10 +1253,7 @@ export async function updateProxyHost(id: number, input: Partial
meta,
skipHttpsHostnameValidation: input.skip_https_hostname_validation ?? existing.skip_https_hostname_validation,
enabled: input.enabled ?? existing.enabled,
- updatedAt: now,
- responseMode,
- staticStatusCode: input.static_status_code !== undefined ? input.static_status_code : existing.static_status_code,
- staticResponseBody: input.static_response_body !== undefined ? input.static_response_body : existing.static_response_body
+ updatedAt: now
})
.where(eq(proxyHosts.id, id));