mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
docs(start): correct headless credential handoff to the SQLite auth store (#131024)
This commit is contained in:
committed by
GitHub
parent
59488aa80b
commit
ff3cf3de3b
@@ -124,7 +124,7 @@ Applies safe, deterministic remediations:
|
||||
|
||||
- flips common `groupPolicy="open"` to `groupPolicy="allowlist"` (including account variants in supported channels)
|
||||
- when WhatsApp group policy flips to `allowlist`, seeds `groupAllowFrom` from the stored `allowFrom` file when that list exists and config does not already define `allowFrom`
|
||||
- tightens permissions for state/config and common sensitive files (`credentials/*.json`, `auth-profiles.json`, `openclaw-agent.sqlite`, and legacy session artifacts)
|
||||
- tightens permissions for state/config and common sensitive files (`credentials/*.json`, legacy `auth-profiles.json`, `openclaw-agent.sqlite`, and legacy session artifacts)
|
||||
- also tightens config include files referenced from `openclaw.json`
|
||||
- uses `chmod` on POSIX hosts and `icacls` resets on Windows
|
||||
|
||||
|
||||
@@ -238,14 +238,14 @@ Route inbound messages to the delegate agent using [Multi-Agent Routing](/concep
|
||||
|
||||
### 4. Add credentials to the delegate agent
|
||||
|
||||
Copy or create auth profiles for the delegate's own `agentDir`:
|
||||
Agents read shared auth profiles without copying them. To give the delegate an
|
||||
independent provider account, sign in on the Gateway host for that agent:
|
||||
|
||||
```bash
|
||||
# Delegate reads from its own auth store
|
||||
~/.openclaw/agents/delegate/agent/auth-profiles.json
|
||||
openclaw models auth login --provider <providerId> --agent delegate
|
||||
```
|
||||
|
||||
Never share the main agent's `agentDir` with the delegate. See [Multi-Agent Routing](/concepts/multi-agent) for auth isolation details.
|
||||
The login writes the delegate's SQLite auth store at `~/.openclaw/agents/delegate/agent/openclaw-agent.sqlite`; its local profiles override the shared read-through base. Never share the main agent's `agentDir` with the delegate. See [Auth credential semantics](/auth-credential-semantics#agent-copy-portability) and [Multi-Agent Routing](/concepts/multi-agent) for auth isolation details.
|
||||
|
||||
## Example: organizational assistant
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ Configures inbound media understanding (image/audio/video):
|
||||
|
||||
- `provider`: API provider id (`openai`, `anthropic`, `google`/`gemini`, `groq`, etc.)
|
||||
- `model`: model id override
|
||||
- `profile` / `preferredProfile`: `auth-profiles.json` profile selection
|
||||
- `profile` / `preferredProfile`: stored auth-profile selection
|
||||
|
||||
**CLI entry** (`type: "cli"`):
|
||||
|
||||
@@ -383,7 +383,7 @@ Configures inbound media understanding (image/audio/video):
|
||||
- Matching image model `timeoutSeconds` entries also apply when the agent calls the explicit `view_image` tool. For image understanding, this timeout applies to the request itself and is not reduced by earlier preparation work.
|
||||
- Failures fall back to the next entry.
|
||||
|
||||
Provider auth follows standard order: `auth-profiles.json` → env vars → `models.providers.*.apiKey`.
|
||||
Provider auth follows standard order: SQLite auth profiles → env vars → `models.providers.*.apiKey`.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -75,7 +75,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
|
||||
},
|
||||
},
|
||||
|
||||
// Auth profile metadata (secrets live in auth-profiles.json)
|
||||
// Auth profile metadata (secrets live in SQLite auth stores)
|
||||
auth: {
|
||||
profiles: {
|
||||
"anthropic:default": { provider: "anthropic", mode: "api_key" },
|
||||
|
||||
@@ -479,7 +479,7 @@ That stages grounded durable candidates into the short-term dreaming store while
|
||||
|
||||
Doctor also reports auth profiles that are temporarily unusable due to short cooldowns (rate limits/timeouts/auth failures) or longer disables (billing/credit failures).
|
||||
|
||||
Legacy Codex OAuth profiles whose tokens live in macOS Keychain (older onboarding before the file-based sidecar layout) are repaired only by doctor. Run `openclaw doctor --fix` once from an interactive terminal to migrate Keychain-backed legacy tokens inline into `auth-profiles.json`; after that, embedded turns (Telegram, cron, sub-agent dispatch) resolve them as canonical OpenAI OAuth profiles.
|
||||
Legacy Codex OAuth profiles with encrypted sidecar credentials are repaired only by doctor. Run `openclaw doctor --fix` from an interactive terminal on the original host so it can recover the legacy encryption key, including from macOS Keychain when needed, and import supported credentials into the SQLite auth store. If the legacy material cannot be recovered, sign in again with `openclaw models auth login --provider openai` on the Gateway host.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="6. Hooks model validation">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
summary: "Contract for `secrets apply` plans: target validation, path matching, and `auth-profiles.json` target scope"
|
||||
summary: "Contract for `secrets apply` plans: target validation, path matching, and SQLite auth-profile target scope"
|
||||
read_when:
|
||||
- Generating or reviewing `openclaw secrets apply` plans
|
||||
- Debugging `Invalid plan target path` errors
|
||||
@@ -105,8 +105,8 @@ Each target is validated with all of the following:
|
||||
- Forbidden segments are rejected: `__proto__`, `prototype`, `constructor`.
|
||||
- The normalized path must match the registered path shape for the target type.
|
||||
- If `providerId` or `accountId` is set, it must match the id encoded in the path.
|
||||
- `auth-profiles.json` targets require `agentId`.
|
||||
- When creating a new `auth-profiles.json` mapping, include `authProfileProvider`.
|
||||
- SQLite auth-profile targets require `agentId`.
|
||||
- When creating a new auth-profile mapping, include `authProfileProvider`.
|
||||
|
||||
## Failure behavior
|
||||
|
||||
@@ -116,7 +116,7 @@ If a target fails validation, apply exits with an error like:
|
||||
Invalid plan target path for models.providers.apiKey: models.providers.openai.baseUrl
|
||||
```
|
||||
|
||||
No writes are committed for an invalid plan: target resolution and path validation run before any file is touched. Separately, once a valid plan starts writing, apply snapshots every touched file first and restores those snapshots if a later write in the same run fails, so a partial write never leaves config, auth-profile, or env state out of sync.
|
||||
No writes are committed for an invalid plan: target resolution and path validation run before any state is changed. For a valid plan, apply captures file snapshots and SQLite auth-store snapshots before writing. If a later write fails, it attempts to restore the files and conditionally roll back the auth-store writes without overwriting concurrent credential changes.
|
||||
|
||||
## Exec provider consent behavior
|
||||
|
||||
@@ -126,8 +126,9 @@ No writes are committed for an invalid plan: target resolution and path validati
|
||||
|
||||
## Runtime and audit scope notes
|
||||
|
||||
- Ref-only `auth-profiles.json` entries (`keyRef`/`tokenRef`) are included in runtime credential resolution and audit coverage.
|
||||
- `secrets apply` writes supported `openclaw.json` targets, supported `auth-profiles.json` targets, and three optional scrub passes, each on by default: `scrubEnv` (removes migrated plaintext values from `.env` files in the effective state and active-config directories), `scrubAuthProfilesForProviderTargets` (clears plaintext/unused-ref residue in `auth-profiles.json` for providers a plan just migrated), and `scrubLegacyAuthJson` (drops migrated `api_key` entries from legacy `auth.json` stores). Set any of `options.scrubEnv`, `options.scrubAuthProfilesForProviderTargets`, `options.scrubLegacyAuthJson` to `false` in the plan to skip that pass.
|
||||
- Ref-only SQLite auth-profile entries (`keyRef`/`tokenRef`) are included in runtime credential resolution and audit coverage.
|
||||
- `secrets apply` writes supported `openclaw.json` targets and SQLite auth-profile targets. Two optional scrub passes are on by default: `scrubEnv` removes migrated plaintext values from `.env` files in the effective state and active-config directories; `scrubAuthProfilesForProviderTargets` clears plaintext/unused-ref residue in auth stores for providers a plan just migrated. Set either option to `false` in the plan to skip that pass.
|
||||
- `scrubLegacyAuthJson` is a deprecated plan input and is always disabled. Doctor owns legacy `auth.json` migration; `secrets apply` does not read or rewrite it.
|
||||
|
||||
## Operator checks
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
summary: "Secrets management: SecretRef contract, shared secret store, runtime snapshots, and safe one-way scrubbing"
|
||||
read_when:
|
||||
- Configuring SecretRefs for provider credentials and `auth-profiles.json` refs
|
||||
- Configuring SecretRefs for provider credentials and SQLite auth-profile refs
|
||||
- Storing team-wide secrets and environment values in the shared SQLite store
|
||||
- Operating secrets reload, audit, configure, and apply safely in production
|
||||
- Understanding startup fail-fast, inactive-surface filtering, and last-known-good behavior
|
||||
|
||||
@@ -34,8 +34,8 @@ exhaustive):
|
||||
| `fs.config_include.perms_writable` | critical | Config include file can be modified by others | include-file perms referenced from `openclaw.json` | yes |
|
||||
| `fs.config_include.perms_group_readable` | warn | Group users can read included secrets/settings | include-file perms referenced from `openclaw.json` | yes |
|
||||
| `fs.config_include.perms_world_readable` | critical | Included secrets/settings are world-readable | include-file perms referenced from `openclaw.json` | yes |
|
||||
| `fs.auth_profiles.perms_writable` | critical | Others can inject or replace stored model credentials | `agents/<agentId>/agent/auth-profiles.json` perms | yes |
|
||||
| `fs.auth_profiles.perms_readable` | warn | Others can read API keys and OAuth tokens | `agents/<agentId>/agent/auth-profiles.json` perms | yes |
|
||||
| `fs.auth_profiles.perms_writable` | critical | Others can inject or replace stored model credentials | Agent-local SQLite auth database/sidecar perms and legacy `auth-profiles.json` perms | yes |
|
||||
| `fs.auth_profiles.perms_readable` | warn | Others can read API keys and OAuth tokens | Agent-local SQLite auth database/sidecar perms and legacy `auth-profiles.json` perms | yes |
|
||||
| `fs.credentials_dir.perms_writable` | critical | Others can modify channel pairing/credential state | filesystem perms on `~/.openclaw/credentials` | yes |
|
||||
| `fs.credentials_dir.perms_readable` | warn | Others can read channel credential state | filesystem perms on `~/.openclaw/credentials` | yes |
|
||||
| `fs.sessions_store.perms_readable` | warn | Others can read session transcripts/metadata | session store perms | yes |
|
||||
|
||||
@@ -862,7 +862,7 @@ For phone-number-based channels, consider running the assistant on a separate nu
|
||||
|
||||
1. Rotate Gateway auth (`gateway.auth.token` / `OPENCLAW_GATEWAY_PASSWORD`) and restart.
|
||||
2. Rotate remote client secrets (`gateway.remote.token` / `.password`) on any machine that can call the Gateway.
|
||||
3. Rotate provider/API credentials (WhatsApp creds, Slack/Discord tokens, model/API keys in `auth-profiles.json`, and encrypted secrets payload values when used).
|
||||
3. Rotate provider/API credentials (WhatsApp creds, Slack/Discord tokens, model/API keys in SQLite auth stores, and encrypted secrets payload values when used).
|
||||
|
||||
### Audit
|
||||
|
||||
|
||||
+20
-20
@@ -323,16 +323,16 @@ troubleshooting, see the main [FAQ](/help/faq).
|
||||
|
||||
**No API key found for provider after adding a new agent**
|
||||
|
||||
A new agent has an empty auth store — auth is per-agent, stored at:
|
||||
A new agent can read shared auth profiles without copying them. Its
|
||||
own profiles live in `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`
|
||||
and override the shared read-through base. See
|
||||
[Auth credential semantics](/auth-credential-semantics#agent-copy-portability).
|
||||
|
||||
```text
|
||||
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
|
||||
```
|
||||
|
||||
Fix: run `openclaw agents add <id>` and configure auth in the wizard, or
|
||||
copy only portable static `api_key`/`token` profiles from the main
|
||||
agent's store. For OAuth, sign in from the new agent when it needs its
|
||||
own account. See [Multi-Agent Routing](/concepts/multi-agent) for the
|
||||
Fix: run `openclaw models auth login --provider <providerId> --agent <agentId>`
|
||||
on the Gateway host when the agent needs its own credentials. You can also
|
||||
configure auth when creating an agent with `openclaw agents add <id>`.
|
||||
For OAuth, sign in separately when the agent needs its own account.
|
||||
See [Multi-Agent Routing](/concepts/multi-agent) for the
|
||||
full `agentDir` reuse and credential-sharing rules — never reuse
|
||||
`agentDir` across agents.
|
||||
|
||||
@@ -391,14 +391,14 @@ troubleshooting, see the main [FAQ](/help/faq).
|
||||
|
||||
**Fix checklist:**
|
||||
|
||||
- Confirm where profiles live — current:
|
||||
`~/.openclaw/agents/<agentId>/agent/auth-profiles.json`; legacy:
|
||||
`~/.openclaw/agent/*` (migrated by `openclaw doctor`).
|
||||
- Confirm where profiles live: shared and agent-local SQLite auth stores.
|
||||
Run `openclaw doctor --fix` if an older install still has
|
||||
`auth-profiles.json`; it is a migration source, not the runtime store.
|
||||
- Confirm the Gateway loads your env var. `ANTHROPIC_API_KEY` set only in
|
||||
your shell won't reach a Gateway run via systemd/launchd — put it in
|
||||
`~/.openclaw/.env` or enable `env.shellEnv`.
|
||||
- Confirm you're editing the right agent — multi-agent setups have
|
||||
multiple `auth-profiles.json` files.
|
||||
- Confirm you're configuring the right agent — use `--agent <agentId>`
|
||||
with `openclaw models auth login` to select its local store.
|
||||
- Run `openclaw models status` to see configured models and provider
|
||||
auth state.
|
||||
|
||||
@@ -445,12 +445,12 @@ Related: [/concepts/oauth](/concepts/oauth) (OAuth flows, token storage, multi-a
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is an auth profile?">
|
||||
A named credential record (OAuth or API key) tied to a provider, stored
|
||||
at:
|
||||
|
||||
```text
|
||||
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
|
||||
```
|
||||
A named credential record (API key, token, or OAuth) tied to a provider,
|
||||
stored in SQLite. Agent-local profiles in
|
||||
`~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite` override the
|
||||
shared read-through base in `~/.openclaw/state/openclaw.sqlite`.
|
||||
Older installs keep the shared store in the main agent's database until
|
||||
`openclaw doctor --fix` relocates it.
|
||||
|
||||
Inspect saved profiles without dumping secrets: `openclaw models auth
|
||||
list` (optionally `--provider <id>` or `--json`). See
|
||||
|
||||
+10
-5
@@ -462,17 +462,22 @@ First-run Q&A - install, onboard, auth routes, subscriptions, initial failures -
|
||||
| Path | Purpose |
|
||||
| ------------------------------------------------------------------ | ------------------------------------------------------------------ |
|
||||
| `$OPENCLAW_STATE_DIR/openclaw.json` | Main config (JSON5) |
|
||||
| `$OPENCLAW_STATE_DIR/credentials/oauth.json` | Legacy OAuth import (copied into auth profiles on first use) |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/agent/auth-profiles.json` | Auth profiles (OAuth, API keys, optional `keyRef`/`tokenRef`) |
|
||||
| `$OPENCLAW_STATE_DIR/credentials/oauth.json` | Legacy OAuth migration source for `openclaw doctor --fix` |
|
||||
| `$OPENCLAW_STATE_DIR/state/openclaw.sqlite` | Shared SQLite state, including shared auth profiles |
|
||||
| `$OPENCLAW_STATE_DIR/secrets.json` | Optional file-backed secret payload for `file` SecretRef providers |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/agent/auth.json` | Legacy compatibility file (static `api_key` entries scrubbed) |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/agent/auth.json` | Legacy auth migration source for `openclaw doctor --fix` |
|
||||
| `$OPENCLAW_STATE_DIR/credentials/` | Provider state (for example `whatsapp/<accountId>/creds.json`) |
|
||||
| `$OPENCLAW_STATE_DIR/agents/` | Per-agent state (agentDir + legacy/archive session artifacts) |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/agent/openclaw-agent.sqlite` | Per-agent SQLite state, including session rows and transcripts |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/agent/openclaw-agent.sqlite` | Per-agent SQLite state, including local auth profiles, sessions, and transcripts |
|
||||
| `$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/` | Legacy session migration sources and archive/support artifacts |
|
||||
|
||||
Legacy single-agent path `~/.openclaw/agent/*` is migrated by `openclaw doctor`.
|
||||
|
||||
Legacy `auth-profiles.json` files are imported by `openclaw doctor --fix`;
|
||||
new logins write SQLite. Agent-local profiles override the shared read-through
|
||||
base. Older installs keep that shared store in the main agent's database until
|
||||
doctor relocates it; see [Auth credential semantics](/auth-credential-semantics#agent-copy-portability).
|
||||
|
||||
Your **workspace** (AGENTS.md, memory files, skills, etc.) is separate, configured via `agents.defaults.workspace` (default: `~/.openclaw/workspace`).
|
||||
|
||||
</Accordion>
|
||||
@@ -1571,7 +1576,7 @@ Model Q&A - defaults, selection, aliases, switching, failover, auth profiles - l
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title='What is the default model for Anthropic with an API key?'>
|
||||
Credentials and model selection are separate. Setting `ANTHROPIC_API_KEY` (or storing an Anthropic API key in auth profiles) enables authentication, but the actual default model is whatever you configure in `agents.defaults.model.primary` (for example `anthropic/claude-sonnet-4-6` or `anthropic/claude-opus-4-6`). `No credentials found for profile "anthropic:default"` means the Gateway could not find Anthropic credentials in the expected `auth-profiles.json` for the running agent.
|
||||
Credentials and model selection are separate. Setting `ANTHROPIC_API_KEY` (or storing an Anthropic API key in auth profiles) enables authentication, but the actual default model is whatever you configure in `agents.defaults.model.primary` (for example `anthropic/claude-sonnet-4-6` or `anthropic/claude-opus-4-6`). `No credentials found for profile "anthropic:default"` means the Gateway could not find Anthropic credentials in the SQLite auth stores available to the running agent.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
|
||||
@@ -667,10 +667,10 @@ Live tests discover credentials the same way the CLI does. Practical implication
|
||||
- If the CLI works, live tests should find the same keys.
|
||||
- If a live test says "no creds", debug the same way you'd debug `openclaw models list` / model selection.
|
||||
|
||||
- Per-agent auth profiles: `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (this is what "profile keys" means in the live tests)
|
||||
- Per-agent auth profiles: SQLite credential rows in `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite` (this is what "profile keys" means in the live tests)
|
||||
- Config: `~/.openclaw/openclaw.json` (or `OPENCLAW_CONFIG_PATH`)
|
||||
- Legacy OAuth dir: `~/.openclaw/credentials/` (copied into the staged live home when present, but not the main profile-key store)
|
||||
- Local live runs copy the active config (with `agents.*.workspace` / `agentDir` overrides stripped) and each agent's `auth-profiles.json` - not the rest of that agent's directory, so `workspace/` and `sandboxes/` data never reaches the staged home - plus the legacy `credentials/` dir and supported external CLI auth files/dirs (`.claude.json`, `.claude/.credentials.json`, `.claude/settings*.json`, `.claude/backups`, `.codex/auth.json`, `.codex/config.toml`, `.gemini`, `.minimax`) into a temp test home.
|
||||
- Local live runs copy the active config (with `agents.*.workspace` / `agentDir` overrides stripped) and stage each agent's canonical SQLite auth credential/state rows through the auth-store reader/writer APIs, not by copying its database or the rest of its directory. Agent sessions, `workspace/`, and `sandboxes/` data are not staged. The runner also copies the legacy `credentials/` dir and supported external CLI auth files/dirs (`.claude.json`, `.claude/.credentials.json`, `.claude/settings*.json`, `.claude/backups`, `.codex/auth.json`, `.codex/config.toml`, `.gemini`, `.minimax`) into a temp test home.
|
||||
|
||||
If you want to rely on env keys, export them before local tests or use the
|
||||
Docker runners below with an explicit `OPENCLAW_PROFILE_FILE`.
|
||||
@@ -703,7 +703,7 @@ Docker runners below with an explicit `OPENCLAW_PROFILE_FILE`.
|
||||
- Scope:
|
||||
- Enumerates every registered image-generation provider plugin
|
||||
- Uses already-exported provider env vars before probing
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in SQLite auth stores do not mask real shell credentials
|
||||
- Skips providers with no usable auth/profile/model
|
||||
- Runs each configured provider through the shared image-generation runtime:
|
||||
- `<provider>:generate`
|
||||
@@ -751,7 +751,7 @@ request. Plugin dependencies are expected to be present before runtime load.
|
||||
- Exercises the shared bundled music-generation provider path
|
||||
- Currently covers `fal`, `google`, `minimax`, and `openrouter`
|
||||
- Uses already-exported provider env vars before probing
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in SQLite auth stores do not mask real shell credentials
|
||||
- Skips providers with no usable auth/profile/model
|
||||
- Runs both declared runtime modes when available:
|
||||
- `generate` with prompt-only input
|
||||
@@ -773,7 +773,7 @@ request. Plugin dependencies are expected to be present before runtime load.
|
||||
- Defaults to the release-safe smoke path: one text-to-video request per provider, one-second lobster prompt, and a per-provider operation cap from `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (`180000` by default)
|
||||
- Skips FAL by default because provider-side queue latency can dominate release time; pass `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"` (or clear the skip list) to run it explicitly
|
||||
- Uses already-exported provider env vars before probing
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in SQLite auth stores do not mask real shell credentials
|
||||
- Skips providers with no usable auth/profile/model
|
||||
- Runs only `generate` by default
|
||||
- Set `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1` to also run declared transform modes when available:
|
||||
|
||||
@@ -92,7 +92,7 @@ clawdock-approve <request-id>
|
||||
ClawDock reads two separate `.env` files, matching the split described in [Docker](/install/docker):
|
||||
|
||||
- The project `.env` next to `docker-compose.yml`: Docker-specific values like image name, ports, and `OPENCLAW_GATEWAY_TOKEN`. `clawdock-token` reads the token from here.
|
||||
- `~/.openclaw/.env` (mounted into the container): env-backed secrets OpenClaw itself manages, alongside `openclaw.json` and `agents/<agentId>/agent/auth-profiles.json`.
|
||||
- `~/.openclaw/.env` (mounted into the container): env-backed secrets OpenClaw itself manages, alongside `openclaw.json` and the shared and per-agent SQLite auth stores.
|
||||
|
||||
`clawdock-fix-token` copies the token from the project `.env` into the container's `gateway.remote.token` and `gateway.auth.token` config values and restarts the gateway.
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ DigitalOcean is a straightforward paid VPS path. For cheaper or free options:
|
||||
|
||||
OpenClaw state lives under:
|
||||
|
||||
- `~/.openclaw/` -- `openclaw.json`, channel/provider credentials, per-agent `auth-profiles.json`, and session data.
|
||||
- `~/.openclaw/` -- `openclaw.json`, channel/provider credentials, shared and per-agent SQLite auth stores, and session data.
|
||||
- `~/.openclaw/workspace/` -- the agent workspace (SOUL.md, memory, artifacts).
|
||||
|
||||
These survive Droplet reboots. To take a portable snapshot:
|
||||
|
||||
@@ -154,17 +154,17 @@ docker compose run --rm openclaw-cli devices approve <requestId>
|
||||
OpenClaw runs in Docker, but the container filesystem is not the source of
|
||||
truth. Long-lived state must survive restarts, rebuilds, and reboots.
|
||||
|
||||
| Component | Container location | Persistence mechanism | Notes |
|
||||
| -------------------- | ----------------------------------- | --------------------------- | -------------------------------------------------------------------------- |
|
||||
| Gateway state/config | `/home/node/.openclaw/` | `OPENCLAW_CONFIG_DIR` mount | Includes `openclaw.json`, shared state, and installed plugin package roots |
|
||||
| Agent workspace | `/home/node/.openclaw/workspace/` | Workspace mount | Code and agent artifacts |
|
||||
| Channel credentials | `/home/node/.openclaw/credentials/` | Config mount | Channel credential material |
|
||||
| Model auth profiles | `/home/node/.openclaw/agents/` | Config mount | `agents/<agentId>/agent/auth-profiles.json` |
|
||||
| Auth-profile key | `/home/node/.config/openclaw/` | Secret-directory mount | Encryption key material; keep separate from the config mount |
|
||||
| Skill state | `/home/node/.openclaw/skills/` | Config mount | Skill-level state |
|
||||
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
|
||||
| Node and OS packages | Container filesystem | Docker image | Rebuilt with the image; do not install at runtime |
|
||||
| Docker container | Ephemeral | Restartable | Safe to replace after mounted state is verified |
|
||||
| Component | Container location | Persistence mechanism | Notes |
|
||||
| -------------------- | ----------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| Gateway state/config | `/home/node/.openclaw/` | `OPENCLAW_CONFIG_DIR` mount | Includes `openclaw.json`, shared state, and installed plugin package roots |
|
||||
| Agent workspace | `/home/node/.openclaw/workspace/` | Workspace mount | Code and agent artifacts |
|
||||
| Channel credentials | `/home/node/.openclaw/credentials/` | Config mount | Channel credential material |
|
||||
| Model auth profiles | `/home/node/.openclaw/` | Config mount | Shared `state/openclaw.sqlite`; agent-local `agents/<agentId>/agent/openclaw-agent.sqlite` |
|
||||
| Auth-profile key | `/home/node/.config/openclaw/` | Secret-directory mount | Encryption key material; keep separate from the config mount |
|
||||
| Skill state | `/home/node/.openclaw/skills/` | Config mount | Skill-level state |
|
||||
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
|
||||
| Node and OS packages | Container filesystem | Docker image | Rebuilt with the image; do not install at runtime |
|
||||
| Docker container | Ephemeral | Restartable | Safe to replace after mounted state is verified |
|
||||
|
||||
## Update OpenClaw
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ Docker Compose bind-mounts `OPENCLAW_CONFIG_DIR` to `/home/node/.openclaw`, `OPE
|
||||
That mounted config directory holds:
|
||||
|
||||
- `openclaw.json` for behavior config
|
||||
- `agents/<agentId>/agent/auth-profiles.json` for stored provider OAuth/API-key auth
|
||||
- `state/openclaw.sqlite` for shared provider auth and `agents/<agentId>/agent/openclaw-agent.sqlite` for agent-local OAuth/API-key profiles
|
||||
- `.env` for env-backed runtime secrets such as `OPENCLAW_GATEWAY_TOKEN`
|
||||
|
||||
The auth-profile secret directory stores the local encryption key for OAuth-backed auth profile token material. Keep it with your Docker host state, but separate from `OPENCLAW_CONFIG_DIR`.
|
||||
|
||||
@@ -48,7 +48,7 @@ Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-inter
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Keep this VM **stateful**. OpenClaw stores `openclaw.json`, per-agent `auth-profiles.json`, sessions, and channel/provider state under `~/.openclaw/`, plus the workspace under `~/.openclaw/workspace/`.
|
||||
Keep this VM **stateful**. OpenClaw stores `openclaw.json`, shared and per-agent SQLite auth stores, sessions, and channel/provider state under `~/.openclaw/`, plus the workspace under `~/.openclaw/workspace/`.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
@@ -29,7 +29,7 @@ The CLI entry point is [`openclaw migrate`](/cli/migrate). Onboarding can also o
|
||||
Copy the **state directory** (`~/.openclaw/` by default) and your **workspace** to preserve:
|
||||
|
||||
- **Config** — `openclaw.json` and all gateway settings.
|
||||
- **Auth** — per-agent `auth-profiles.json` (API keys plus OAuth), plus any channel or provider state under `credentials/`.
|
||||
- **Auth** — shared and per-agent SQLite auth stores (API keys plus OAuth), plus any channel or provider state under `credentials/`.
|
||||
- **Sessions** — conversation history and agent state.
|
||||
- **Channel state** — WhatsApp login, Telegram session, and similar.
|
||||
- **Workspace files** — `MEMORY.md`, `USER.md`, skills, and prompts.
|
||||
@@ -112,7 +112,7 @@ awk -F= '/^(TELEGRAM_BOT_TOKEN|DISCORD_BOT_TOKEN)=/ { print $1 "=present" }' ~/.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Copying only openclaw.json">
|
||||
The config file alone is not enough. Model auth profiles live under `agents/<agentId>/agent/auth-profiles.json`, and channel and provider state lives under `credentials/`. Always migrate the **entire** state directory.
|
||||
The config file alone is not enough. Shared model auth lives in `state/openclaw.sqlite`, agent-local profiles live in `agents/<agentId>/agent/openclaw-agent.sqlite`, and channel and provider state lives under `credentials/`. Always migrate the **entire** state directory using the backup and restore flow above.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Permissions and ownership">
|
||||
|
||||
@@ -31,7 +31,7 @@ openclaw doctor --json
|
||||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Persistent storage via a Northflank Volume (`/data`) so `openclaw.json`, per-agent `auth-profiles.json`, channel/provider state, sessions, and workspace survive redeploys
|
||||
- Persistent storage via a Northflank Volume (`/data`) so `openclaw.json`, shared and per-agent SQLite auth stores, channel/provider state, sessions, and workspace survive redeploys
|
||||
|
||||
## Connect a channel
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ Verify the architecture with `uname -m` (should print `aarch64`). For binaries w
|
||||
|
||||
OpenClaw state lives under:
|
||||
|
||||
- `~/.openclaw/` -- `openclaw.json`, per-agent `auth-profiles.json`, channel/provider state, and session data.
|
||||
- `~/.openclaw/` -- `openclaw.json`, shared and per-agent SQLite auth stores, channel/provider state, and session data.
|
||||
- `~/.openclaw/workspace/` -- the agent workspace (SOUL.md, memory, artifacts).
|
||||
|
||||
These survive reboots. To take a portable snapshot:
|
||||
|
||||
@@ -145,7 +145,7 @@ The generated Quadlet service keeps a fixed, hardened default shape: `127.0.0.1`
|
||||
- **Token file:** `~/.openclaw/.env`
|
||||
- **Launch helper:** `./scripts/run-openclaw-podman.sh`
|
||||
|
||||
The launch script and Quadlet bind-mount host state into the container: `OPENCLAW_CONFIG_DIR` -> `/home/node/.openclaw`, `OPENCLAW_WORKSPACE_DIR` -> `/home/node/.openclaw/workspace`. By default those are host directories, not anonymous container state, so `openclaw.json`, per-agent `auth-profiles.json`, channel/provider state, sessions, and workspace survive container replacement. Setup also seeds `gateway.controlUi.allowedOrigins` for `127.0.0.1` and `localhost` on the published gateway port so the local dashboard works with the container's non-loopback bind.
|
||||
The launch script and Quadlet bind-mount host state into the container: `OPENCLAW_CONFIG_DIR` -> `/home/node/.openclaw`, `OPENCLAW_WORKSPACE_DIR` -> `/home/node/.openclaw/workspace`. By default those are host directories, not anonymous container state, so `openclaw.json`, shared and per-agent SQLite auth stores, channel/provider state, sessions, and workspace survive container replacement. Setup also seeds `gateway.controlUi.allowedOrigins` for `127.0.0.1` and `localhost` on the published gateway port so the local dashboard works with the container's non-loopback bind.
|
||||
|
||||
Useful env vars for the manual launcher (persist these in `~/.openclaw/.env`; the launcher reads that file before finalizing container/image defaults):
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ openclaw doctor --json
|
||||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Persistent storage via the Railway Volume (`/data`), so `openclaw.json`, per-agent `auth-profiles.json`, channel/provider state, sessions, and workspace survive redeploys
|
||||
- Persistent storage via the Railway Volume (`/data`), so `openclaw.json`, shared and per-agent SQLite auth stores, channel/provider state, sessions, and workspace survive redeploys
|
||||
|
||||
## Connect a channel
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ Most OpenClaw features work on ARM64 without changes (Node.js, Telegram, WhatsAp
|
||||
|
||||
OpenClaw state lives under:
|
||||
|
||||
- `~/.openclaw/` -- `openclaw.json`, per-agent `auth-profiles.json`, channel/provider state, sessions.
|
||||
- `~/.openclaw/` -- `openclaw.json`, shared and per-agent SQLite auth stores, channel/provider state, sessions.
|
||||
- `~/.openclaw/workspace/` -- agent workspace (SOUL.md, memory, artifacts).
|
||||
|
||||
These survive reboots and benefit from SSD over SD card for both performance and longevity. Take a portable snapshot with:
|
||||
|
||||
@@ -97,8 +97,8 @@ SecretRef, plugin, or channel auth failures.
|
||||
|
||||
- Pull or build the new OpenClaw image, then redeploy the EasyRunner app.
|
||||
- Back up the `openclaw-config` volume before updates. It holds
|
||||
`openclaw.json`, `agents/<agentId>/agent/auth-profiles.json`, and installed
|
||||
plugin package state.
|
||||
`openclaw.json`, shared auth in `state/openclaw.sqlite`, agent-local profiles
|
||||
in `agents/<agentId>/agent/openclaw-agent.sqlite`, and installed plugin package state.
|
||||
- Back up `openclaw-workspace` if agents write durable project data there.
|
||||
- Run `openclaw doctor` after major updates to catch config migrations and
|
||||
service warnings.
|
||||
|
||||
@@ -182,7 +182,7 @@ Precedence, applied per agent during `runCopilotAttempt`:
|
||||
Each agent gets its own `copilotHome` so Copilot CLI tokens, sessions, and
|
||||
config never leak between agents on the same machine. Default:
|
||||
`<agentDir>/copilot` (keeps SDK state out of the same directory as
|
||||
OpenClaw's `models.json` / `auth-profiles.json`), or
|
||||
OpenClaw's `models.json` / `openclaw-agent.sqlite`), or
|
||||
`~/.openclaw/agents/<agentId>/copilot` when no agent directory is supplied.
|
||||
Override with `copilotHome: <path>` on the attempt input for a custom
|
||||
location (for example, a shared mount for migration).
|
||||
|
||||
@@ -237,7 +237,7 @@ openclaw vault setup \
|
||||
```
|
||||
|
||||
Bare target paths apply to `openclaw.json`. Use
|
||||
`auth-profiles:<agentId>:<path>` for existing `auth-profiles.json` targets.
|
||||
`auth-profiles:<agentId>:<path>` for existing SQLite auth-profile targets.
|
||||
The target path must be a registered OpenClaw SecretRef target. The setup
|
||||
command does not create arbitrary named secrets in OpenClaw; Vault remains the
|
||||
secret store, and OpenClaw stores SecretRefs only on supported config fields.
|
||||
|
||||
@@ -40,7 +40,7 @@ OpenAI-SDK-style examples, but new config should use `baseUrl`.
|
||||
A custom provider with `api: "ollama"` follows the same rules. For example, an `ollama-remote` provider pointed at a private LAN host can use `apiKey: "ollama-local"`; sub-agents resolve that marker through the Ollama provider hook instead of treating it as a missing credential. `memory.search.provider` can also point at a custom provider id so embeddings use that Ollama endpoint.
|
||||
</Accordion>
|
||||
<Accordion title="Auth profiles">
|
||||
`auth-profiles.json` stores the credential for a provider id; put endpoint settings (`baseUrl`, `api`, models, headers, timeouts) in `models.providers.<id>`. Older flat files such as `{ "ollama-windows": { "apiKey": "ollama-local" } }` are not a runtime format; `openclaw doctor --fix` rewrites them into a canonical `ollama-windows:default` API-key profile with a backup. A `baseUrl` value in that legacy file is noise and should move to provider config.
|
||||
SQLite auth stores hold the credential for a provider id; put endpoint settings (`baseUrl`, `api`, models, headers, timeouts) in `models.providers.<id>`. Older flat `auth-profiles.json` files such as `{ "ollama-windows": { "apiKey": "ollama-local" } }` are not a runtime format; `openclaw doctor --fix` imports them into SQLite as a canonical `ollama-windows:default` API-key profile with a backup. A `baseUrl` value in that legacy file is noise and should move to provider config.
|
||||
</Accordion>
|
||||
<Accordion title="Memory embedding scope">
|
||||
Bearer auth for Ollama memory embeddings is scoped to the host it was declared for:
|
||||
|
||||
@@ -46,7 +46,7 @@ Anthropic has confirmed that Claude CLI reuse (including `claude -p`) is a sanct
|
||||
|
||||
## How keys are discovered
|
||||
|
||||
- **Auth profiles**: per-agent, stored in `auth-profiles.json`.
|
||||
- **Auth profiles**: SQLite stores, with agent-local profiles overriding the shared read-through base. See [Auth credential semantics](/auth-credential-semantics#agent-copy-portability).
|
||||
- **Environment variables**: for example `OPENAI_API_KEY`, `BRAVE_API_KEY`, `FIRECRAWL_API_KEY`.
|
||||
- **Config**: `models.providers.*.apiKey`, `plugins.entries.*.config.webSearch.apiKey`, `plugins.entries.firecrawl.config.webFetch.apiKey`, `memory.search.*`, `talk.providers.*.apiKey`.
|
||||
- **Skills**: `skills.entries.<name>.apiKey`, which may export the key to the skill process env.
|
||||
|
||||
@@ -128,7 +128,7 @@ The lists below are generated from the source target registry and checked agains
|
||||
- `channels.googlechat.serviceAccount`
|
||||
- `channels.googlechat.accounts.*.serviceAccount`
|
||||
|
||||
### `auth-profiles.json` targets (`secrets configure` + `secrets apply` + `secrets audit`)
|
||||
### SQLite auth-profile targets (`secrets configure` + `secrets apply` + `secrets audit`)
|
||||
|
||||
- `profiles.*.keyRef` (`type: "api_key"`; unsupported when `auth.profiles.<id>.mode = "oauth"`)
|
||||
- `profiles.*.tokenRef` (`type: "token"`; unsupported when `auth.profiles.<id>.mode = "oauth"`)
|
||||
|
||||
+2
-2
@@ -136,7 +136,7 @@ openclaw health
|
||||
- **Wrong port:** Gateway WS defaults to `ws://127.0.0.1:18789`; keep app + CLI on the same port.
|
||||
- **Where state lives:**
|
||||
- Channel/provider state: `~/.openclaw/credentials/`
|
||||
- Model auth profiles: `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
|
||||
- Model auth profiles: SQLite auth stores (shared: `~/.openclaw/state/openclaw.sqlite`; agent-local: `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`)
|
||||
- Sessions and transcripts: `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`
|
||||
- Legacy/archive session artifacts: `~/.openclaw/agents/<agentId>/sessions/`
|
||||
- Logs: `/tmp/openclaw/`
|
||||
@@ -152,7 +152,7 @@ Use this when debugging auth or deciding what to back up:
|
||||
- **Pairing allowlists**:
|
||||
- `~/.openclaw/credentials/<channel>-allowFrom.json` (default account)
|
||||
- `~/.openclaw/credentials/<channel>-<accountId>-allowFrom.json` (non-default accounts)
|
||||
- **Model auth profiles**: `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
|
||||
- **Model auth profiles**: shared and agent-local SQLite auth stores; see [Auth credential semantics](/auth-credential-semantics#agent-copy-portability) for inheritance and legacy shared-store relocation
|
||||
- **File-backed secrets payload (optional)**: `~/.openclaw/secrets.json`
|
||||
- **Legacy OAuth import**: `~/.openclaw/credentials/oauth.json`
|
||||
More detail: [Security](/gateway/security#credential-storage-map).
|
||||
|
||||
@@ -340,8 +340,11 @@ Model behavior:
|
||||
|
||||
Credential and profile paths:
|
||||
|
||||
- Auth profiles (API keys + OAuth): `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
|
||||
- Legacy OAuth import: `~/.openclaw/credentials/oauth.json`
|
||||
- Agent-local auth profiles (API keys, tokens, and OAuth): `~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite` (`auth_profile_store`).
|
||||
- Shared auth profiles: `~/.openclaw/state/openclaw.sqlite`; agent-local profiles override this read-through base. Older installs keep the shared store in the main agent's database until `openclaw doctor --fix` relocates it.
|
||||
- Legacy import only: `auth-profiles.json`, per-agent `auth.json`, and `~/.openclaw/credentials/oauth.json`. Run `openclaw doctor --fix` to import them into SQLite; new logins do not write these files.
|
||||
|
||||
Paths respect `$OPENCLAW_STATE_DIR`. See [Auth credential semantics](/auth-credential-semantics#agent-copy-portability) for shared-store and agent-local behavior.
|
||||
|
||||
Credential storage mode:
|
||||
|
||||
@@ -369,13 +372,36 @@ Credential storage mode:
|
||||
`--gateway-token` and `--gateway-token-ref-env` are mutually exclusive.
|
||||
- Existing plaintext setups continue to work unchanged.
|
||||
|
||||
<Note>
|
||||
Headless and server tip: complete OAuth on a machine with a browser, then copy
|
||||
that agent's `auth-profiles.json` (for example
|
||||
`~/.openclaw/agents/<agentId>/agent/auth-profiles.json`, or the matching
|
||||
`$OPENCLAW_STATE_DIR/...` path) to the gateway host. `credentials/oauth.json`
|
||||
is only a legacy import source.
|
||||
</Note>
|
||||
## Headless and server setup
|
||||
|
||||
Run auth setup **on the Gateway host**, using the same OS user and state directory
|
||||
as the Gateway. Over SSH, use an interactive terminal:
|
||||
|
||||
```bash
|
||||
openclaw configure --section model
|
||||
```
|
||||
|
||||
Choose your provider's supported auth method. For a browser OAuth flow, open the
|
||||
displayed URL in your local browser and paste the redirect URL or authorization
|
||||
code back into the terminal on the Gateway host when prompted. If the provider
|
||||
offers device-code login, complete the displayed URL/code in your local browser
|
||||
while the Gateway host's login process waits. The completed login persists the
|
||||
credential on that host in SQLite; no credential file handoff is needed.
|
||||
|
||||
For a specific agent, run `openclaw models auth login --provider <id> --agent <agentId>`
|
||||
on the Gateway host. See [Models CLI](/cli/models#auth-profiles) and
|
||||
[OAuth](/concepts/oauth).
|
||||
|
||||
For unattended setup, use a provider API key with
|
||||
[non-interactive onboarding](/cli/onboard#non-interactive-setup). If you use
|
||||
`--secret-input-mode ref`, make the referenced environment variable available to
|
||||
the Gateway service as well as the onboarding process. See
|
||||
[Authentication](/gateway/authentication).
|
||||
|
||||
Verify the result on the Gateway host with `openclaw models status` (add
|
||||
`--agent <agentId>` for a specific agent). Remote-client onboarding only configures
|
||||
the local client connection; it does not set up provider credentials on the server.
|
||||
Do not copy `auth-profiles.json` or replace a SQLite database to transfer a login.
|
||||
|
||||
## Outputs and internals
|
||||
|
||||
|
||||
Reference in New Issue
Block a user