fix(config): allow custom bind with loopback IP for tailscale compat validator

This commit is contained in:
Aaron Aronchick 2026-03-06 06:23:35 +00:00
parent ece6dccd50
commit 45a525d374

View File

@ -1,4 +1,5 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
import { isLoopbackHost } from "../net.js";
import { listChannelPlugins } from "../../channels/plugins/index.js";
import {
CONFIG_PATH,
@ -249,7 +250,7 @@ function loadSchemaWithPlugins(): ConfigSchemaResponse {
* which defaults to "loopback"). Rejecting at config-write time prevents the
* gateway from entering an unrecoverable crash loop on next restart.
*/
function validateTailscaleBindCompat(config: OpenClawConfig): string | null {
export function validateTailscaleBindCompat(config: OpenClawConfig): string | null {
const tailscaleMode = config.gateway?.tailscale?.mode;
if (tailscaleMode !== "serve" && tailscaleMode !== "funnel") {
return null;
@ -258,6 +259,15 @@ function validateTailscaleBindCompat(config: OpenClawConfig): string | null {
if (bind === "loopback") {
return null;
}
// A custom bind with a loopback IP is equivalent to bind=loopback at runtime
// (server-runtime-config.ts uses isLoopbackHost on the resolved IP). Allow it
// at write-time too so we don't reject a valid config.
if (bind === "custom") {
const customBindHost = config.gateway?.customBindHost?.trim();
if (customBindHost && isLoopbackHost(customBindHost)) {
return null;
}
}
return `gateway.tailscale.mode="${tailscaleMode}" requires gateway.bind="loopback", but gateway.bind="${bind}". Change gateway.bind to "loopback" or set gateway.tailscale.mode to "off".`;
}