mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:20:43 +00:00
fix(status): clarify tailscale exposure state
This commit is contained in:
@@ -65,6 +65,10 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- CLI/status: label the OpenClaw Serve/Funnel setting as `Tailscale exposure`
|
||||
and show daemon state separately when available, so `gateway.tailscale.mode:
|
||||
"off"` no longer reads like the Tailscale daemon is stopped. Fixes #71790.
|
||||
Thanks @pesvobodak.
|
||||
- Plugins/Bonjour: stop ciao mDNS watchdog failures from looping forever when
|
||||
the advertiser stays stuck in `probing` or `announcing`; Bonjour now disables
|
||||
itself for the current Gateway process after repeated failed restarts while
|
||||
|
||||
@@ -16,6 +16,10 @@ Tailscale provides HTTPS, routing, and (for Serve) identity headers.
|
||||
- `funnel`: Public HTTPS via `tailscale funnel`. OpenClaw requires a shared password.
|
||||
- `off`: Default (no Tailscale automation).
|
||||
|
||||
Status and audit output use **Tailscale exposure** for this OpenClaw Serve/Funnel
|
||||
mode. `off` means OpenClaw is not managing Serve or Funnel; it does not mean the
|
||||
local Tailscale daemon is stopped or logged out.
|
||||
|
||||
## Auth
|
||||
|
||||
Set `gateway.auth.mode` to control the handshake:
|
||||
|
||||
@@ -63,6 +63,18 @@ function createBaseParams(
|
||||
}
|
||||
|
||||
describe("status-all diagnosis port checks", () => {
|
||||
it("labels OpenClaw Tailscale exposure separately from daemon state", async () => {
|
||||
const params = createBaseParams([]);
|
||||
params.tailscale.backendState = "Running";
|
||||
params.tailscale.dnsName = "box.tail.ts.net";
|
||||
|
||||
await appendStatusAllDiagnosis(params);
|
||||
|
||||
const output = params.lines.join("\n");
|
||||
expect(output).toContain("✓ Tailscale exposure: off · daemon Running · box.tail.ts.net");
|
||||
expect(output).not.toContain("Tailscale: off");
|
||||
});
|
||||
|
||||
it("treats same-process dual-stack loopback listeners as healthy", async () => {
|
||||
const params = createBaseParams([
|
||||
{ pid: 5001, commandLine: "openclaw-gateway", address: "127.0.0.1:18789" },
|
||||
|
||||
@@ -169,8 +169,8 @@ export async function appendStatusAllDiagnosis(params: {
|
||||
const hasDns = Boolean(params.tailscale.dnsName);
|
||||
const label =
|
||||
params.tailscaleMode === "off"
|
||||
? `Tailscale: off · ${backend}${params.tailscale.dnsName ? ` · ${params.tailscale.dnsName}` : ""}`
|
||||
: `Tailscale: ${params.tailscaleMode} · ${backend}${params.tailscale.dnsName ? ` · ${params.tailscale.dnsName}` : ""}`;
|
||||
? `Tailscale exposure: off · daemon ${backend}${params.tailscale.dnsName ? ` · ${params.tailscale.dnsName}` : ""}`
|
||||
: `Tailscale exposure: ${params.tailscaleMode} · daemon ${backend}${params.tailscale.dnsName ? ` · ${params.tailscale.dnsName}` : ""}`;
|
||||
emitCheck(label, okBackend && (params.tailscaleMode === "off" || hasDns) ? "ok" : "warn");
|
||||
if (params.tailscale.error) {
|
||||
lines.push(` ${muted(`error: ${params.tailscale.error}`)}`);
|
||||
|
||||
@@ -145,7 +145,7 @@ describe("status-all format", () => {
|
||||
includeBackendStateWhenOff: true,
|
||||
includeDnsNameWhenOff: true,
|
||||
}),
|
||||
).toBe("off · Stopped · box.tail.ts.net");
|
||||
).toBe("off · daemon Stopped · box.tail.ts.net");
|
||||
});
|
||||
|
||||
it("formats service values across short and detailed runtime surfaces", () => {
|
||||
@@ -301,7 +301,7 @@ describe("status-all format", () => {
|
||||
).toEqual([
|
||||
{ Item: "Version", Value: "1.0.0" },
|
||||
{ Item: "Dashboard", Value: "https://openclaw.local" },
|
||||
{ Item: "Tailscale", Value: "serve · https://tail.example" },
|
||||
{ Item: "Tailscale exposure", Value: "serve · https://tail.example" },
|
||||
{ Item: "Channel", Value: "stable" },
|
||||
{ Item: "Git", Value: "main @ v1.0.0" },
|
||||
{ Item: "Update", Value: "up to date" },
|
||||
@@ -373,7 +373,7 @@ describe("status-all format", () => {
|
||||
).toEqual([
|
||||
{ Item: "Version", Value: "1.0.0" },
|
||||
{ Item: "Dashboard", Value: "http://127.0.0.1:18789/" },
|
||||
{ Item: "Tailscale", Value: "serve · box.tail.ts.net · https://box.tail.ts.net" },
|
||||
{ Item: "Tailscale exposure", Value: "serve · box.tail.ts.net · https://box.tail.ts.net" },
|
||||
{ Item: "Channel", Value: "stable (config)" },
|
||||
{ Item: "Git", Value: "main · tag v1.2.3" },
|
||||
{ Item: "Update", Value: "available · custom update" },
|
||||
|
||||
@@ -112,7 +112,9 @@ export function formatStatusTailscaleValue(params: {
|
||||
const decorateWarn = params.decorateWarn ?? ((value: string) => value);
|
||||
if (params.tailscaleMode === "off") {
|
||||
const suffix = [
|
||||
params.includeBackendStateWhenOff && params.backendState ? params.backendState : null,
|
||||
params.includeBackendStateWhenOff && params.backendState
|
||||
? `daemon ${params.backendState}`
|
||||
: null,
|
||||
params.includeDnsNameWhenOff && params.dnsName ? params.dnsName : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -192,7 +194,7 @@ export function buildStatusOverviewRows(params: {
|
||||
const rows: StatusOverviewRow[] = [...(params.prefixRows ?? [])];
|
||||
rows.push(
|
||||
{ Item: "Dashboard", Value: params.dashboardValue },
|
||||
{ Item: "Tailscale", Value: params.tailscaleValue },
|
||||
{ Item: "Tailscale exposure", Value: params.tailscaleValue },
|
||||
{ Item: "Channel", Value: params.channelLabel },
|
||||
);
|
||||
if (params.gitLabel) {
|
||||
|
||||
@@ -81,7 +81,7 @@ describe("status-overview-surface", () => {
|
||||
).toEqual([
|
||||
{ Item: "OS", Value: "macOS · node 22" },
|
||||
{ Item: "Dashboard", Value: "http://127.0.0.1:18789/" },
|
||||
{ Item: "Tailscale", Value: "muted(off · box.tail.ts.net)" },
|
||||
{ Item: "Tailscale exposure", Value: "muted(off · box.tail.ts.net)" },
|
||||
{ Item: "Channel", Value: "stable (config)" },
|
||||
{ Item: "Git", Value: "main · tag v1.2.3" },
|
||||
{ Item: "Update", Value: "available · custom update" },
|
||||
|
||||
Reference in New Issue
Block a user