mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 01:42:59 +00:00
fix(docker): avoid printing gateway token
This commit is contained in:
@@ -54,6 +54,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Memory/LanceDB: expose public memory artifacts through the active memory provider bridge so memory-wiki imports durable memory files, daily notes, dream reports, and event logs without depending on memory-core internals. Fixes #83604. (#85060) Thanks @brokemac79.
|
||||
- Docker setup: stop printing the Gateway bearer token in setup logs and printed follow-up commands.
|
||||
- Agents: let embedded compaction fallback retries proceed when PI-compatible candidates do not need agent harness plugin preparation.
|
||||
- Agents/tools: honor configured custom provider API keys when deciding whether media, image-generation, video-generation, music-generation, and PDF tools are available. (#85570)
|
||||
- StepFun: stop advertising stale generic API key auth choices so onboarding only offers runtime-backed Standard and Step Plan choices.
|
||||
|
||||
@@ -572,11 +572,17 @@ else
|
||||
else
|
||||
echo "Bonjour/mDNS advertising: explicitly enabled (OPENCLAW_DISABLE_BONJOUR=$OPENCLAW_DISABLE_BONJOUR)."
|
||||
fi
|
||||
echo "Gateway token: $OPENCLAW_GATEWAY_TOKEN"
|
||||
echo "Gateway token: stored in Docker environment/config (not printed)."
|
||||
echo "Tailscale exposure: Off (use host-level tailnet/Tailscale setup separately)."
|
||||
echo "Install Gateway daemon: No (managed by Docker Compose)"
|
||||
echo ""
|
||||
run_prestart_cli onboard --mode local --no-install-daemon
|
||||
run_prestart_cli onboard \
|
||||
--mode local \
|
||||
--no-install-daemon \
|
||||
--gateway-auth token \
|
||||
--gateway-token-ref-env OPENCLAW_GATEWAY_TOKEN \
|
||||
--skip-ui \
|
||||
--suppress-gateway-token-output
|
||||
fi
|
||||
|
||||
echo ""
|
||||
@@ -711,8 +717,8 @@ echo "Gateway running with host port mapping."
|
||||
echo "Access from tailnet devices via the host's tailnet IP."
|
||||
echo "Config: $OPENCLAW_CONFIG_DIR"
|
||||
echo "Workspace: $OPENCLAW_WORKSPACE_DIR"
|
||||
echo "Token: $OPENCLAW_GATEWAY_TOKEN"
|
||||
echo "Token: stored in Docker environment/config (not printed)."
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " ${COMPOSE_HINT} logs -f openclaw-gateway"
|
||||
echo " ${COMPOSE_HINT} exec openclaw-gateway node dist/index.js health --token \"$OPENCLAW_GATEWAY_TOKEN\""
|
||||
echo " ${COMPOSE_HINT} exec openclaw-gateway sh -lc 'node dist/index.js health --token \"\$OPENCLAW_GATEWAY_TOKEN\"'"
|
||||
|
||||
@@ -167,6 +167,7 @@ export function registerOnboardCommand(program: Command): void {
|
||||
.option("--skip-search", "Skip search provider setup")
|
||||
.option("--skip-health", "Skip health check")
|
||||
.option("--skip-ui", "Skip Control UI/TUI prompts")
|
||||
.option("--suppress-gateway-token-output", "Suppress token-bearing Gateway/UI output")
|
||||
.option("--skip-hooks", "Skip hook setup")
|
||||
.option("--node-manager <name>", "Node manager for skills: npm|pnpm|bun")
|
||||
.option("--import-from <provider>", "Migration provider to run during onboarding")
|
||||
@@ -246,6 +247,7 @@ export function registerOnboardCommand(program: Command): void {
|
||||
skipSearch: Boolean(opts.skipSearch),
|
||||
skipHealth: Boolean(opts.skipHealth),
|
||||
skipUi: Boolean(opts.skipUi),
|
||||
suppressGatewayTokenOutput: Boolean(opts.suppressGatewayTokenOutput),
|
||||
skipHooks: Boolean(opts.skipHooks),
|
||||
nodeManager: opts.nodeManager as NodeManagerChoice | undefined,
|
||||
importFrom: opts.importFrom as string | undefined,
|
||||
|
||||
@@ -79,6 +79,7 @@ export type OnboardOptions = OnboardDynamicProviderOptions & {
|
||||
skipSearch?: boolean;
|
||||
skipHealth?: boolean;
|
||||
skipUi?: boolean;
|
||||
suppressGatewayTokenOutput?: boolean;
|
||||
skipHooks?: boolean;
|
||||
nodeManager?: NodeManagerChoice;
|
||||
remoteUrl?: string;
|
||||
|
||||
@@ -141,7 +141,8 @@ function runDockerSetup(
|
||||
cwd: sandbox.rootDir,
|
||||
env: createEnv(sandbox, overrides),
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "ignore", "pipe"],
|
||||
maxBuffer: 4 * 1024 * 1024,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -284,8 +285,11 @@ describe("scripts/docker/setup.sh", () => {
|
||||
const log = await readDockerLog(activeSandbox);
|
||||
expect(log).toContain("--build-arg OPENCLAW_IMAGE_APT_PACKAGES=curl wget");
|
||||
expect(log).toContain(
|
||||
`run --rm --no-deps ${prestartContainerEnvFlags} --entrypoint node openclaw-gateway dist/index.js onboard --mode local --no-install-daemon`,
|
||||
`run --rm --no-deps ${prestartContainerEnvFlags} --entrypoint node openclaw-gateway dist/index.js onboard --mode local --no-install-daemon --gateway-auth token --gateway-token-ref-env OPENCLAW_GATEWAY_TOKEN --skip-ui --suppress-gateway-token-output`,
|
||||
);
|
||||
expect(result.stdout).toContain("Gateway token: stored in Docker environment/config");
|
||||
expect(result.stdout).not.toContain("test-token");
|
||||
expect(result.stdout).not.toContain("#token=");
|
||||
expect(log).toContain(
|
||||
`run --rm --no-deps ${prestartContainerEnvFlags} --entrypoint node openclaw-gateway dist/index.js config set --batch-json [{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]`,
|
||||
);
|
||||
@@ -702,7 +706,9 @@ describe("scripts/docker/setup.sh", () => {
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
const log = await readDockerLog(activeSandbox);
|
||||
expect(log).toContain("onboard --mode local --no-install-daemon");
|
||||
expect(log).toContain(
|
||||
"onboard --mode local --no-install-daemon --gateway-auth token --gateway-token-ref-env OPENCLAW_GATEWAY_TOKEN --skip-ui --suppress-gateway-token-output",
|
||||
);
|
||||
const envFile = await readFile(join(activeSandbox.rootDir, ".env"), "utf8");
|
||||
expect(envFile).toMatch(/OPENCLAW_SKIP_ONBOARDING=\n/);
|
||||
});
|
||||
|
||||
@@ -594,6 +594,43 @@ describe("finalizeSetupWizard", () => {
|
||||
expect(gatewayServiceInstall).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("suppresses token-bearing onboarding output when requested", async () => {
|
||||
const prompter = createLaterPrompter();
|
||||
|
||||
await finalizeSetupWizard({
|
||||
flow: "advanced",
|
||||
opts: {
|
||||
acceptRisk: true,
|
||||
authChoice: "skip",
|
||||
installDaemon: false,
|
||||
skipHealth: true,
|
||||
skipUi: true,
|
||||
suppressGatewayTokenOutput: true,
|
||||
},
|
||||
baseConfig: {},
|
||||
nextConfig: {},
|
||||
workspaceDir: "/tmp",
|
||||
settings: {
|
||||
port: 18789,
|
||||
bind: "loopback",
|
||||
authMode: "token",
|
||||
gatewayToken: "session-token",
|
||||
tailscaleMode: "off",
|
||||
tailscaleResetOnExit: false,
|
||||
},
|
||||
prompter,
|
||||
runtime: createRuntime(),
|
||||
});
|
||||
|
||||
const output = vi
|
||||
.mocked(prompter.note)
|
||||
.mock.calls.map((call) => call.join("\n"))
|
||||
.join("\n");
|
||||
expect(output).toContain("http://127.0.0.1:18789");
|
||||
expect(output).not.toContain("session-token");
|
||||
expect(output).not.toContain("#token=");
|
||||
});
|
||||
|
||||
it("stops after a scheduled restart instead of reinstalling the service", async () => {
|
||||
const progressUpdate = vi.fn();
|
||||
const progressStop = vi.fn();
|
||||
|
||||
@@ -77,6 +77,7 @@ export async function finalizeSetupWizard(
|
||||
options: FinalizeOnboardingOptions,
|
||||
): Promise<{ launchedTui: boolean }> {
|
||||
const { flow, opts, baseConfig, nextConfig, settings, prompter, runtime } = options;
|
||||
const suppressGatewayTokenOutput = opts.suppressGatewayTokenOutput === true;
|
||||
let gatewayProbe: { ok: boolean; detail?: string } = { ok: true };
|
||||
let resolvedGatewayPassword = "";
|
||||
|
||||
@@ -392,7 +393,7 @@ export async function finalizeSetupWizard(
|
||||
tlsEnabled: nextConfig.gateway?.tls?.enabled === true,
|
||||
});
|
||||
const authedUrl =
|
||||
settings.authMode === "token" && settings.gatewayToken
|
||||
settings.authMode === "token" && settings.gatewayToken && !suppressGatewayTokenOutput
|
||||
? `${links.httpUrl}#token=${encodeURIComponent(settings.gatewayToken)}`
|
||||
: links.httpUrl;
|
||||
if (opts.skipHealth || !gatewayProbe.ok) {
|
||||
@@ -419,7 +420,7 @@ export async function finalizeSetupWizard(
|
||||
await prompter.note(
|
||||
[
|
||||
t("wizard.finalize.webUiUrl", { url: links.httpUrl }),
|
||||
settings.authMode === "token" && settings.gatewayToken
|
||||
settings.authMode === "token" && settings.gatewayToken && !suppressGatewayTokenOutput
|
||||
? t("wizard.finalize.webUiWithTokenUrl", { url: authedUrl })
|
||||
: undefined,
|
||||
t("wizard.finalize.gatewayWsUrl", { url: links.wsUrl }),
|
||||
@@ -450,24 +451,22 @@ export async function finalizeSetupWizard(
|
||||
}
|
||||
|
||||
if (gatewayProbe.ok) {
|
||||
await prompter.note(
|
||||
[
|
||||
t("wizard.finalize.gatewayTokenShared"),
|
||||
t("wizard.finalize.gatewayTokenStored"),
|
||||
t("wizard.finalize.gatewayTokenView", {
|
||||
command: formatCliCommand("openclaw config get gateway.auth.token"),
|
||||
}),
|
||||
t("wizard.finalize.gatewayTokenGenerate", {
|
||||
command: formatCliCommand("openclaw doctor --generate-gateway-token"),
|
||||
}),
|
||||
t("wizard.finalize.dashboardTokenMemory"),
|
||||
t("wizard.finalize.dashboardOpenAnytime", {
|
||||
command: formatCliCommand("openclaw dashboard --no-open"),
|
||||
}),
|
||||
t("wizard.finalize.dashboardTokenPrompt"),
|
||||
].join("\n"),
|
||||
"Token",
|
||||
);
|
||||
const tokenNotes = [
|
||||
t("wizard.finalize.gatewayTokenShared"),
|
||||
t("wizard.finalize.gatewayTokenStored"),
|
||||
t("wizard.finalize.gatewayTokenView", {
|
||||
command: formatCliCommand("openclaw config get gateway.auth.token"),
|
||||
}),
|
||||
t("wizard.finalize.gatewayTokenGenerate", {
|
||||
command: formatCliCommand("openclaw doctor --generate-gateway-token"),
|
||||
}),
|
||||
suppressGatewayTokenOutput ? undefined : t("wizard.finalize.dashboardTokenMemory"),
|
||||
t("wizard.finalize.dashboardOpenAnytime", {
|
||||
command: formatCliCommand("openclaw dashboard --no-open"),
|
||||
}),
|
||||
suppressGatewayTokenOutput ? undefined : t("wizard.finalize.dashboardTokenPrompt"),
|
||||
].filter(Boolean);
|
||||
await prompter.note(tokenNotes.join("\n"), "Token");
|
||||
}
|
||||
|
||||
const hatchOptions: { value: "tui" | "web" | "later"; label: string }[] = [
|
||||
@@ -505,14 +504,20 @@ export async function finalizeSetupWizard(
|
||||
controlUiOpenHint = formatControlUiSshHint({
|
||||
port: settings.port,
|
||||
basePath: controlUiBasePath,
|
||||
token: settings.authMode === "token" ? settings.gatewayToken : undefined,
|
||||
token:
|
||||
settings.authMode === "token" && !suppressGatewayTokenOutput
|
||||
? settings.gatewayToken
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
controlUiOpenHint = formatControlUiSshHint({
|
||||
port: settings.port,
|
||||
basePath: controlUiBasePath,
|
||||
token: settings.authMode === "token" ? settings.gatewayToken : undefined,
|
||||
token:
|
||||
settings.authMode === "token" && !suppressGatewayTokenOutput
|
||||
? settings.gatewayToken
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
await prompter.note(
|
||||
@@ -553,6 +558,7 @@ export async function finalizeSetupWizard(
|
||||
gatewayProbe.ok &&
|
||||
settings.authMode === "token" &&
|
||||
Boolean(settings.gatewayToken) &&
|
||||
!suppressGatewayTokenOutput &&
|
||||
hatchChoice === null;
|
||||
if (shouldOpenControlUi) {
|
||||
const browserSupport = await detectBrowserOpenSupport();
|
||||
|
||||
Reference in New Issue
Block a user