mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-19 08:02:30 +00:00
docs(configuration): expand "Environment Variables for Secrets" section
- Note that any string field supports ${VAR_NAME} and resolved values are
never written back to disk.
- Document the failure mode for unset variables.
- Add MCP (stdio env + HTTP headers) and web-search examples.
- Add Docker, direnv, and secret-manager (1Password / pass / Bitwarden)
delivery patterns alongside the existing systemd example.
- Replace plaintext apiKey values in tools.web.search examples (Brave,
Tavily, Jina, Kagi, Olostep) with ${PROVIDER_API_KEY} placeholders so
the docs stop modelling the anti-pattern.
- Cross-link from the Security section.
Refs: HKUDS/nanobot#2172
This commit is contained in:
parent
175b58e259
commit
5a34504b76
@ -26,7 +26,52 @@ Instead of storing secrets directly in `config.json`, you can use `${VAR_NAME}`
|
||||
}
|
||||
```
|
||||
|
||||
For **systemd** deployments, use `EnvironmentFile=` in the service unit to load variables from a file that only the deploying user can read:
|
||||
Any string value in `config.json` can use `${VAR_NAME}`. Resolution runs once at startup, in memory only — resolved values are never written back to disk, so editing config through `nanobot onboard` or the WebUI preserves the placeholder.
|
||||
|
||||
If a referenced variable is unset, nanobot fails fast at startup with `ValueError: Environment variable 'NAME' referenced in config is not set`.
|
||||
|
||||
### More examples
|
||||
|
||||
**MCP servers** — both stdio `env` and HTTP `headers`:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"mcpServers": {
|
||||
"github": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||||
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" }
|
||||
},
|
||||
"remote": {
|
||||
"url": "https://example.com/mcp/",
|
||||
"headers": { "Authorization": "Bearer ${REMOTE_MCP_TOKEN}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Web search providers:**
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "brave",
|
||||
"apiKey": "${BRAVE_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Loading variables at startup
|
||||
|
||||
Pick whatever fits your deployment — nanobot only reads `os.environ` at startup, so any mechanism that populates the process environment works.
|
||||
|
||||
**systemd** — use `EnvironmentFile=` in the service unit to load variables from a file that only the deploying user can read:
|
||||
|
||||
```ini
|
||||
# /etc/systemd/system/nanobot.service (excerpt)
|
||||
@ -42,6 +87,33 @@ TELEGRAM_TOKEN=your-token-here
|
||||
IMAP_PASSWORD=your-password-here
|
||||
```
|
||||
|
||||
**Docker** — `--env-file` (one `KEY=VALUE` per line) or `-e KEY=value`:
|
||||
|
||||
```bash
|
||||
docker run --env-file=./nanobot.env nanobot/nanobot
|
||||
```
|
||||
|
||||
**direnv** — drop a `.envrc` in your working directory and run `direnv allow`:
|
||||
|
||||
```bash
|
||||
# .envrc (auto-loaded by direnv)
|
||||
export TELEGRAM_TOKEN=your-token-here
|
||||
export ANTHROPIC_API_KEY=...
|
||||
```
|
||||
|
||||
**Secret managers (1Password, Bitwarden, pass)** — wrap the process so secrets only exist as env vars for the lifetime of the run, never on disk:
|
||||
|
||||
```bash
|
||||
# 1Password — references in .env.tpl look like `op://Vault/Item/field`
|
||||
op run --env-file=.env.tpl -- nanobot agent
|
||||
|
||||
# pass (passwordstore.org)
|
||||
ANTHROPIC_API_KEY="$(pass show api/anthropic)" nanobot agent
|
||||
|
||||
# Bitwarden
|
||||
ANTHROPIC_API_KEY="$(bw get password api/anthropic)" nanobot agent
|
||||
```
|
||||
|
||||
## Providers
|
||||
|
||||
> [!TIP]
|
||||
@ -917,7 +989,7 @@ By default, web search uses `duckduckgo`, and it works out of the box without an
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "brave",
|
||||
"apiKey": "BSA..."
|
||||
"apiKey": "${BRAVE_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -931,7 +1003,7 @@ By default, web search uses `duckduckgo`, and it works out of the box without an
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "tavily",
|
||||
"apiKey": "tvly-..."
|
||||
"apiKey": "${TAVILY_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -945,7 +1017,7 @@ By default, web search uses `duckduckgo`, and it works out of the box without an
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "jina",
|
||||
"apiKey": "jina_..."
|
||||
"apiKey": "${JINA_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -959,7 +1031,7 @@ By default, web search uses `duckduckgo`, and it works out of the box without an
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "kagi",
|
||||
"apiKey": "your-kagi-api-key"
|
||||
"apiKey": "${KAGI_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -973,7 +1045,7 @@ By default, web search uses `duckduckgo`, and it works out of the box without an
|
||||
"web": {
|
||||
"search": {
|
||||
"provider": "olostep",
|
||||
"apiKey": "YOUR_OLOSTEP_API_KEY"
|
||||
"apiKey": "${OLOSTEP_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1136,6 +1208,8 @@ MCP tools are automatically discovered and registered on startup. The LLM can us
|
||||
> [!TIP]
|
||||
> For production deployments, set `"restrictToWorkspace": true` and `"tools.exec.sandbox": "bwrap"` in your config to sandbox the agent.
|
||||
|
||||
For API keys, tokens, and other secrets, see [Environment Variables for Secrets](#environment-variables-for-secrets) — avoid storing them directly in `config.json`.
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `tools.restrictToWorkspace` | `false` | When `true`, restricts **all** agent tools (shell, file read/write/edit, list) to the workspace directory. Prevents path traversal and out-of-scope access. |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user