mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 00:48:07 +00:00
feat(logging): add startup log truncation env flag and sync docs
This commit is contained in:
@@ -15,7 +15,9 @@ ComfyUI-OpenClaw is a **security-first orchestration layer** for ComfyUI that co
|
||||
|
||||
This project is designed to make **ComfyUI a reliable automation target** with an explicit admin boundary and hardened defaults.
|
||||
|
||||
---
|
||||
<center>
|
||||
<img src="assets/adminMobileConsole.png" width="70%" />
|
||||
</center>
|
||||
|
||||
## Security stance (how this project differs from convenience-first automation packs):
|
||||
|
||||
@@ -48,6 +50,8 @@ This project is designed to make **ComfyUI a reliable automation target** with a
|
||||
Deployment profiles and hardening checklists:
|
||||
- [Security Deployment Guide](docs/security_deployment_guide.md) (local / LAN / public templates + self-check command)
|
||||
- [Security Key/Token Lifecycle SOP](docs/security_key_lifecycle_sop.md) (trust-root, secrets key, and bridge token rotation/revocation/disaster recovery)
|
||||
- [Security Checklist](docs/security_checklist.md) (pre-exposure operational checklist for connector and ingress boundaries)
|
||||
- [Runtime Hardening and Startup](docs/runtime_hardening_and_startup.md) (runtime profile, startup gate, and hardened baseline behaviors)
|
||||
|
||||
|
||||
|
||||
@@ -475,11 +479,13 @@ Remote admin actions are denied by default. If you understand the risk and need
|
||||
- PowerShell (current session only):
|
||||
- `$env:OPENCLAW_LLM_API_KEY="<YOUR_API_KEY>"`
|
||||
- `$env:OPENCLAW_ADMIN_TOKEN="<YOUR_ADMIN_TOKEN>"`
|
||||
- `$env:OPENCLAW_LOG_TRUNCATE_ON_START="1"` (optional: clear previous `openclaw.log` at startup)
|
||||
- PowerShell (persistent; takes effect in new shells):
|
||||
- `setx OPENCLAW_LLM_API_KEY "<YOUR_API_KEY>"`
|
||||
- `setx OPENCLAW_ADMIN_TOKEN "<YOUR_ADMIN_TOKEN>"`
|
||||
- `setx OPENCLAW_LOG_TRUNCATE_ON_START "1"` (optional)
|
||||
- CMD (current session only): `set OPENCLAW_LLM_API_KEY=<YOUR_API_KEY>`
|
||||
- Portable `.bat` launchers: add `set OPENCLAW_LLM_API_KEY=...` / `set OPENCLAW_ADMIN_TOKEN=...` before launching ComfyUI.
|
||||
- Portable `.bat` launchers: add `set OPENCLAW_LLM_API_KEY=...` / `set OPENCLAW_ADMIN_TOKEN=...` (optionally `set OPENCLAW_LOG_TRUNCATE_ON_START=1`) before launching ComfyUI.
|
||||
- ComfyUI Desktop: if env vars are not passed through reliably, prefer the Settings UI key store for localhost-only convenience, or set system-wide env vars.
|
||||
|
||||
## Remote Admin Console (Mobile UI)
|
||||
@@ -933,6 +939,7 @@ Override:
|
||||
Logs:
|
||||
|
||||
- `openclaw.log` (legacy `moltbot.log` is still supported)
|
||||
- Optional startup truncation: set `OPENCLAW_LOG_TRUNCATE_ON_START=1` to clear the active log file once at process startup (useful to avoid stale-history noise in UI log views).
|
||||
- Optional structured JSON logs for selected core paths:
|
||||
- set `OPENCLAW_LOG_FORMAT=json` (or `OPENCLAW_STRUCTURED_LOGS=1`) before startup
|
||||
- default behavior remains plain text logs (no structured log emission unless opt-in)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
@@ -84,6 +84,40 @@ else:
|
||||
DATA_DIR = os.path.join(PACK_DIR, "data")
|
||||
LOG_FILE = os.path.join(DATA_DIR, "openclaw.log")
|
||||
|
||||
# IMPORTANT: startup log truncation must run once per process.
|
||||
# Multiple module-level loggers call setup_logger(); repeated truncation would
|
||||
# erase fresh logs emitted after the first logger initialization.
|
||||
_LOG_TRUNCATE_APPLIED = False
|
||||
|
||||
|
||||
def _is_env_enabled(*keys: str) -> bool:
|
||||
for key in keys:
|
||||
val = (os.environ.get(key) or "").strip().lower()
|
||||
if val in {"1", "true", "yes", "on"}:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _maybe_truncate_log_on_start(logger: logging.Logger) -> None:
|
||||
global _LOG_TRUNCATE_APPLIED
|
||||
if _LOG_TRUNCATE_APPLIED:
|
||||
return
|
||||
if not _is_env_enabled(
|
||||
"OPENCLAW_LOG_TRUNCATE_ON_START", "MOLTBOT_LOG_TRUNCATE_ON_START"
|
||||
):
|
||||
return
|
||||
try:
|
||||
os.makedirs(DATA_DIR, exist_ok=True)
|
||||
with open(LOG_FILE, "w", encoding="utf-8"):
|
||||
pass
|
||||
logger.info(
|
||||
f"Startup log truncation applied for {LOG_FILE} "
|
||||
"(OPENCLAW_LOG_TRUNCATE_ON_START=1)"
|
||||
)
|
||||
_LOG_TRUNCATE_APPLIED = True
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to truncate startup log file {LOG_FILE}: {e}")
|
||||
|
||||
|
||||
class RedactedFormatter(logging.Formatter):
|
||||
"""
|
||||
@@ -136,6 +170,7 @@ def setup_logger(name: str = "ComfyUI-OpenClaw") -> logging.Logger:
|
||||
|
||||
# Only add handler if not already added to avoid duplicates on reload
|
||||
if not logger.handlers:
|
||||
_maybe_truncate_log_on_start(logger)
|
||||
api_key = get_api_key()
|
||||
sensitive = [api_key] if api_key else []
|
||||
formatter = RedactedFormatter(
|
||||
|
||||
@@ -7,6 +7,7 @@ This guide covers optional, high-control features that are disabled by default.
|
||||
- Remote registry sync uses quarantine and trust policy controls.
|
||||
- Constrained transforms execute trusted Python modules with strict runtime limits.
|
||||
- Both features are fail-closed when disabled.
|
||||
- Optional operational log hygiene: `OPENCLAW_LOG_TRUNCATE_ON_START=1` clears stale `openclaw.log` at backend startup (once per process).
|
||||
|
||||
## Remote registry sync
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ Set the following environment variables (or put them in a `.env` file if you use
|
||||
- `OPENCLAW_CONNECTOR_DEBUG`: Set to `1` for verbose logs.
|
||||
- `OPENCLAW_CONNECTOR_ADMIN_USERS`: Comma-separated list of user IDs allowed to run admin commands (for example `/stop`, approvals, schedules). Admin users are also treated as trusted senders for `/run`.
|
||||
- `OPENCLAW_CONNECTOR_ADMIN_TOKEN`: Admin token sent to OpenClaw (`X-OpenClaw-Admin-Token`).
|
||||
- `OPENCLAW_LOG_TRUNCATE_ON_START`: Optional backend runtime flag. Set `1` to clear `openclaw.log` once at backend startup to avoid stale-history noise in UI log panels.
|
||||
|
||||
**Admin token behavior:**
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ OPENCLAW_ALLOW_REMOTE_ADMIN=1
|
||||
|
||||
# Require a token for Logs/Config viewing
|
||||
OPENCLAW_OBSERVABILITY_TOKEN=observability-secret
|
||||
|
||||
# Optional startup log hygiene (avoid stale historical error lines in UI)
|
||||
OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
### 3. Firewall Rules (Host)
|
||||
|
||||
@@ -40,6 +40,8 @@ No special configuration is required.
|
||||
- Keep SSRF relax flags disabled:
|
||||
- `OPENCLAW_ALLOW_ANY_PUBLIC_LLM_HOST=0`
|
||||
- `OPENCLAW_ALLOW_INSECURE_BASE_URL=0`
|
||||
- **Optional log hygiene**:
|
||||
- `OPENCLAW_LOG_TRUNCATE_ON_START=1` clears stale `openclaw.log` content once at startup.
|
||||
|
||||
### 3. "Red Lines" (What NOT to do)
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ Only do this on trusted/private access planes and keep backend protection enable
|
||||
|
||||
- `OPENCLAW_ADMIN_TOKEN=<strong-secret>`
|
||||
- `OPENCLAW_ALLOW_REMOTE_ADMIN=1`
|
||||
- `OPENCLAW_LOG_TRUNCATE_ON_START=1` (optional, startup log hygiene)
|
||||
|
||||
Use one more auth boundary at proxy layer (IP allowlist, SSO, or basic auth), for example:
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ OPENCLAW_OBSERVABILITY_TOKEN=change-me-too
|
||||
OPENCLAW_BRIDGE_ENABLED=0
|
||||
# OPENCLAW_BRIDGE_DEVICE_TOKEN=
|
||||
|
||||
# Optional startup log hygiene (truncate openclaw.log once per process start)
|
||||
# OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
|
||||
# Network
|
||||
# Bind to localhost by default
|
||||
COMFYUI_LISTEN=127.0.0.1
|
||||
|
||||
@@ -46,6 +46,7 @@ To be safe:
|
||||
|
||||
1. Set `OPENCLAW_ADMIN_TOKEN` to a strong secret.
|
||||
2. Enforce `OPENCLAW_OBSERVABILITY_TOKEN` if you plan to view logs remotely.
|
||||
3. Optional: set `OPENCLAW_LOG_TRUNCATE_ON_START=1` to clear stale `openclaw.log` at startup.
|
||||
|
||||
### 4. "Red Lines"
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ To set OpenClaw security tokens in the portable version, edit your `run_nvidia_g
|
||||
set OPENCLAW_ADMIN_TOKEN=my-secret-token
|
||||
set OPENCLAW_ALLOW_REMOTE_ADMIN=1
|
||||
set OPENCLAW_OBSERVABILITY_TOKEN=observability-token
|
||||
set OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
|
||||
:: Run ComfyUI
|
||||
.\python_embeded\python.exe -s ComfyUI\main.py --windows-standalone-build
|
||||
@@ -25,6 +26,7 @@ pause
|
||||
```powershell
|
||||
$env:OPENCLAW_ADMIN_TOKEN="my-secret-token"
|
||||
$env:OPENCLAW_ALLOW_REMOTE_ADMIN="1"
|
||||
$env:OPENCLAW_LOG_TRUNCATE_ON_START="1"
|
||||
./python_embeded/python.exe -s ComfyUI/main.py
|
||||
```
|
||||
|
||||
@@ -35,6 +37,7 @@ If you want to open the standalone remote admin page from another device in your
|
||||
```powershell
|
||||
$env:OPENCLAW_ADMIN_TOKEN="my-secret-token"
|
||||
$env:OPENCLAW_ALLOW_REMOTE_ADMIN="1"
|
||||
$env:OPENCLAW_LOG_TRUNCATE_ON_START="1"
|
||||
./python_embeded/python.exe -s ComfyUI/main.py --listen 0.0.0.0 --port 8188
|
||||
```
|
||||
|
||||
|
||||
+45
-98
@@ -1,14 +1,24 @@
|
||||
openapi: "3.0.3"
|
||||
info:
|
||||
title: "ComfyUI-OpenClaw API"
|
||||
version: "1.0.2"
|
||||
description: "Generated from docs/release/api_contract.md (v1.0.2 baseline)."
|
||||
version: "1.0.0"
|
||||
description: "Generated from docs/release/api_contract.md (R66 baseline)."
|
||||
servers:
|
||||
- url: "/openclaw"
|
||||
description: "Direct OpenClaw prefix"
|
||||
- url: "/api/openclaw"
|
||||
description: "ComfyUI /api shim"
|
||||
paths:
|
||||
/admin:
|
||||
get:
|
||||
operationId: "get_admin"
|
||||
summary: "Standalone remote admin console HTML shell (mobile-friendly)."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "None*"
|
||||
x-openclaw-section: "1.0 UI Entry Points"
|
||||
x-openclaw-legacy-path: "/moltbot/admin"
|
||||
/health:
|
||||
get:
|
||||
operationId: "get_health"
|
||||
@@ -31,17 +41,6 @@ paths:
|
||||
x-openclaw-section: "1.1 Core Observability & System"
|
||||
x-openclaw-legacy-path: "/moltbot/capabilities"
|
||||
x-openclaw-auth-tier: "none"
|
||||
/admin:
|
||||
get:
|
||||
operationId: "get_admin_console"
|
||||
summary: "Standalone remote admin console HTML shell (mobile-friendly)."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "None*"
|
||||
x-openclaw-section: "1.0 UI Entry Points"
|
||||
x-openclaw-legacy-path: "/moltbot/admin"
|
||||
x-openclaw-auth-tier: "none"
|
||||
/logs/tail:
|
||||
get:
|
||||
operationId: "get_logs_tail"
|
||||
@@ -260,7 +259,7 @@ paths:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
x-openclaw-streaming: true
|
||||
/llm/chat:
|
||||
/chat:
|
||||
post:
|
||||
operationId: "post_chat"
|
||||
summary: "Unified chat interface for assistant interactions."
|
||||
@@ -274,7 +273,7 @@ paths:
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
/llm/test:
|
||||
/test:
|
||||
post:
|
||||
operationId: "post_test"
|
||||
summary: "Test LLM connectivity and configuration."
|
||||
@@ -288,7 +287,7 @@ paths:
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
/llm/models:
|
||||
/models:
|
||||
get:
|
||||
operationId: "get_models"
|
||||
summary: "List available models from configured provider."
|
||||
@@ -437,44 +436,32 @@ paths:
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
/schedules:
|
||||
/openclaw/schedules:
|
||||
get:
|
||||
operationId: "get_schedules"
|
||||
operationId: "get_openclaw_schedules"
|
||||
summary: "List all schedules."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
post:
|
||||
operationId: "post_schedules"
|
||||
operationId: "post_openclaw_schedules"
|
||||
summary: "Create a new schedule."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
/schedules/{id}:
|
||||
/openclaw/schedules/{id}:
|
||||
get:
|
||||
operationId: "get_schedules_id"
|
||||
operationId: "get_openclaw_schedules_id"
|
||||
summary: "Get schedule details."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
@@ -482,17 +469,13 @@ paths:
|
||||
schema:
|
||||
type: "string"
|
||||
put:
|
||||
operationId: "put_schedules_id"
|
||||
operationId: "put_openclaw_schedules_id"
|
||||
summary: "Update a schedule."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
@@ -500,106 +483,82 @@ paths:
|
||||
schema:
|
||||
type: "string"
|
||||
delete:
|
||||
operationId: "delete_schedules_id"
|
||||
operationId: "delete_openclaw_schedules_id"
|
||||
summary: "Delete a schedule."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
/schedules/{id}/run:
|
||||
/openclaw/schedules/{id}/run:
|
||||
post:
|
||||
operationId: "post_schedules_id_run"
|
||||
operationId: "post_openclaw_schedules_id_run"
|
||||
summary: "Manually trigger a schedule."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
/schedules/{id}/runs:
|
||||
/openclaw/schedules/{id}/runs:
|
||||
get:
|
||||
operationId: "get_schedules_id_runs"
|
||||
operationId: "get_openclaw_schedules_id_runs"
|
||||
summary: "Get run history for a schedule."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
/approvals:
|
||||
/openclaw/approvals:
|
||||
get:
|
||||
operationId: "get_approvals"
|
||||
operationId: "get_openclaw_approvals"
|
||||
summary: "List pending approvals (includes pagination/scan diagnostics; bounded serialization scan on malformed records)."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
/approvals/{id}/approve:
|
||||
/openclaw/approvals/{id}/approve:
|
||||
post:
|
||||
operationId: "post_approvals_id_approve"
|
||||
operationId: "post_openclaw_approvals_id_approve"
|
||||
summary: "Approve a pending request."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
/approvals/{id}/reject:
|
||||
/openclaw/approvals/{id}/reject:
|
||||
post:
|
||||
operationId: "post_approvals_id_reject"
|
||||
operationId: "post_openclaw_approvals_id_reject"
|
||||
summary: "Reject a pending request."
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Admin"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.5 Schedules & Approvals"
|
||||
x-openclaw-auth-tier: "admin"
|
||||
security:
|
||||
- OpenClawAdminToken:
|
||||
[]
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
@@ -613,12 +572,8 @@ paths:
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Bridge Auth (Device Check)"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.6 Bridge (Sidecar)"
|
||||
x-openclaw-auth-tier: "bridge"
|
||||
security:
|
||||
- OpenClawBridgeAuth:
|
||||
[]
|
||||
/bridge/submit:
|
||||
post:
|
||||
operationId: "post_bridge_submit"
|
||||
@@ -626,12 +581,8 @@ paths:
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Bridge Auth (Device Check)"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.6 Bridge (Sidecar)"
|
||||
x-openclaw-auth-tier: "bridge"
|
||||
security:
|
||||
- OpenClawBridgeAuth:
|
||||
[]
|
||||
/bridge/deliver:
|
||||
post:
|
||||
operationId: "post_bridge_deliver"
|
||||
@@ -639,12 +590,8 @@ paths:
|
||||
responses:
|
||||
200:
|
||||
description: "OK"
|
||||
x-openclaw-auth: "Bridge Auth (Device Check)"
|
||||
x-openclaw-auth: "Unknown"
|
||||
x-openclaw-section: "1.6 Bridge (Sidecar)"
|
||||
x-openclaw-auth-tier: "bridge"
|
||||
security:
|
||||
- OpenClawBridgeAuth:
|
||||
[]
|
||||
components:
|
||||
securitySchemes:
|
||||
OpenClawAdminToken:
|
||||
|
||||
@@ -98,6 +98,7 @@ Contractual limits to prevent resource exhaustion.
|
||||
| Variable | Description |
|
||||
| :--- | :--- |
|
||||
| `OPENCLAW_STATE_DIR` | Directory for persistent state (DBs, history, logs). Default: `ComfyUI/user/default/openclaw` |
|
||||
| `OPENCLAW_LOG_TRUNCATE_ON_START` | Set `1` to truncate active log file (`openclaw.log`) once at process startup before new handlers write records. |
|
||||
| `OPENCLAW_DIAGNOSTICS` | Comma-separated list of subsystems to enable debug logging for (e.g. `webhook.*,templates`). Safe-redacted. |
|
||||
| `OPENCLAW_CONNECTOR_DEBUG` | Set `1` to enable verbose debug logging in Connector. |
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ Users should audit these flags before deploying to a public or untrusted network
|
||||
| `OPENCLAW_BRIDGE_ENABLED` | `0` | **High** | Enables the sidecar bridge for remote orchestration. Requires `OPENCLAW_BRIDGE_DEVICE_TOKEN` (and in public posture also mTLS + device allowlist controls). |
|
||||
| `OPENCLAW_ALLOW_ANY_PUBLIC_LLM_HOST` | `0` | **High** | Bypasses the known-host allowlist for LLM `base_url`. Allows SSRF to public IPs. |
|
||||
| `OPENCLAW_ALLOW_INSECURE_BASE_URL` | `0` | **Critical** | Allows HTTP (non-HTTPS) or private IP `base_url` for LLM. Risk of internal network scanning (SSRF). |
|
||||
| `OPENCLAW_LOG_TRUNCATE_ON_START` | `0` | **Low** | Operational log hygiene toggle. If `1`, truncates active `openclaw.log` at startup (once per process). |
|
||||
| `OPENCLAW_CONNECTOR_DISCORD_TOKEN` | *None* | **Medium** | Presence enables Discord Bot gateway. |
|
||||
| `OPENCLAW_CONNECTOR_LINE_CHANNEL_SECRET` | *None* | **Medium** | Presence enables LINE webhook listener. Requires a public HTTPS endpoint. |
|
||||
| `OPENCLAW_CONNECTOR_TELEGRAM_TOKEN` | *None* | **Low** | Presence enables Telegram long-polling. Outbound only. |
|
||||
|
||||
@@ -81,6 +81,8 @@ OPENCLAW_WEBHOOK_AUTH_MODE=hmac
|
||||
OPENCLAW_WEBHOOK_HMAC_SECRET=replace-with-strong-secret
|
||||
OPENCLAW_BRIDGE_ENABLED=1
|
||||
OPENCLAW_BRIDGE_DEVICE_TOKEN=replace-with-bridge-device-token
|
||||
# Optional: clear stale history in startup log views
|
||||
OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
Then validate:
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
- [ ] `OPENCLAW_CONNECTOR_DEBUG=1` logs sensitive data — **disable in production**.
|
||||
- [ ] Ensure no debug flags are set in production environment.
|
||||
- [ ] Optional ops hygiene: if stale historical errors cause confusion in log viewers, use `OPENCLAW_LOG_TRUNCATE_ON_START=1` during controlled restart windows.
|
||||
|
||||
### 7. Tunnel / Reverse Proxy
|
||||
|
||||
|
||||
@@ -55,6 +55,13 @@ Use `--strict-warnings` if you want warnings to fail the check in hardened pipel
|
||||
python scripts/check_deployment_profile.py --profile public --strict-warnings
|
||||
```
|
||||
|
||||
Optional operational log hygiene (all profiles):
|
||||
|
||||
```bash
|
||||
# Clear active openclaw.log once at startup (useful to avoid stale UI log noise)
|
||||
OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
## 3. Local (Single-user)
|
||||
|
||||
### 3.1 Pasteable config template
|
||||
@@ -72,6 +79,8 @@ OPENCLAW_SECURITY_DANGEROUS_BIND_OVERRIDE=0
|
||||
|
||||
# Optional but recommended
|
||||
OPENCLAW_ADMIN_TOKEN=change-this-local-admin-token
|
||||
# Optional startup log hygiene
|
||||
# OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
### 3.2 Checklist
|
||||
@@ -107,6 +116,8 @@ OPENCLAW_ENABLE_TRANSFORMS=0
|
||||
OPENCLAW_ALLOW_ANY_PUBLIC_LLM_HOST=0
|
||||
OPENCLAW_ALLOW_INSECURE_BASE_URL=0
|
||||
OPENCLAW_SECURITY_DANGEROUS_BIND_OVERRIDE=0
|
||||
# Optional startup log hygiene
|
||||
# OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
### 4.2 Checklist
|
||||
@@ -156,6 +167,8 @@ OPENCLAW_ENABLE_TRANSFORMS=0
|
||||
OPENCLAW_ALLOW_ANY_PUBLIC_LLM_HOST=0
|
||||
OPENCLAW_ALLOW_INSECURE_BASE_URL=0
|
||||
OPENCLAW_SECURITY_DANGEROUS_BIND_OVERRIDE=0
|
||||
# Optional startup log hygiene
|
||||
# OPENCLAW_LOG_TRUNCATE_ON_START=1
|
||||
```
|
||||
|
||||
### 5.2 Checklist
|
||||
|
||||
@@ -19,6 +19,9 @@ All paths are relative to `OPENCLAW_STATE_DIR` (legacy fallback: `MOLTBOT_STATE_
|
||||
| Encrypted secret store | `secrets.enc.json` | Encrypted provider secrets |
|
||||
| Bridge token registry | `bridge_tokens.json` | Device token lifecycle state and audit trail |
|
||||
|
||||
Optional startup log hygiene for incident drills:
|
||||
- Set `OPENCLAW_LOG_TRUNCATE_ON_START=1` before restart when you need a clean `openclaw.log` timeline.
|
||||
|
||||
## 2. Global Rules
|
||||
|
||||
1. Always take a timestamped backup before any lifecycle operation.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import config
|
||||
|
||||
|
||||
class TestLogTruncateOnStart(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._orig_log_file = config.LOG_FILE
|
||||
self._orig_data_dir = config.DATA_DIR
|
||||
self._orig_applied = getattr(config, "_LOG_TRUNCATE_APPLIED", False)
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.log_file = os.path.join(self.tmp.name, "openclaw.log")
|
||||
self._logger_names: set[str] = set()
|
||||
|
||||
def tearDown(self):
|
||||
for name in list(self._logger_names):
|
||||
self._reset_logger(name)
|
||||
config.LOG_FILE = self._orig_log_file
|
||||
config.DATA_DIR = self._orig_data_dir
|
||||
config._LOG_TRUNCATE_APPLIED = self._orig_applied
|
||||
self.tmp.cleanup()
|
||||
|
||||
def _reset_logger(self, name: str) -> None:
|
||||
logger = logging.getLogger(name)
|
||||
for h in list(logger.handlers):
|
||||
try:
|
||||
h.close()
|
||||
finally:
|
||||
logger.removeHandler(h)
|
||||
|
||||
def _prepare_log_fixture(self, content: str) -> None:
|
||||
os.makedirs(self.tmp.name, exist_ok=True)
|
||||
with open(self.log_file, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
config.LOG_FILE = self.log_file
|
||||
config.DATA_DIR = self.tmp.name
|
||||
config._LOG_TRUNCATE_APPLIED = False
|
||||
|
||||
def test_no_truncate_when_flag_disabled(self):
|
||||
self._prepare_log_fixture("legacy-line\n")
|
||||
logger_name = "test.log_truncate.disabled"
|
||||
self._reset_logger(logger_name)
|
||||
self._logger_names.add(logger_name)
|
||||
|
||||
with patch.dict(
|
||||
os.environ, {"OPENCLAW_LOG_TRUNCATE_ON_START": "0"}, clear=False
|
||||
):
|
||||
config.setup_logger(logger_name)
|
||||
|
||||
with open(self.log_file, "r", encoding="utf-8") as f:
|
||||
self.assertEqual(f.read(), "legacy-line\n")
|
||||
|
||||
def test_truncate_when_flag_enabled(self):
|
||||
self._prepare_log_fixture("legacy-line\n")
|
||||
logger_name = "test.log_truncate.enabled"
|
||||
self._reset_logger(logger_name)
|
||||
self._logger_names.add(logger_name)
|
||||
|
||||
with patch.dict(
|
||||
os.environ, {"OPENCLAW_LOG_TRUNCATE_ON_START": "1"}, clear=False
|
||||
):
|
||||
config.setup_logger(logger_name)
|
||||
|
||||
with open(self.log_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
self.assertNotIn("legacy-line", content)
|
||||
self.assertEqual(content, "")
|
||||
|
||||
def test_truncate_applies_once_per_process(self):
|
||||
self._prepare_log_fixture("legacy-line\n")
|
||||
logger_name_a = "test.log_truncate.once.a"
|
||||
logger_name_b = "test.log_truncate.once.b"
|
||||
self._reset_logger(logger_name_a)
|
||||
self._reset_logger(logger_name_b)
|
||||
self._logger_names.update({logger_name_a, logger_name_b})
|
||||
|
||||
with patch.dict(
|
||||
os.environ, {"OPENCLAW_LOG_TRUNCATE_ON_START": "1"}, clear=False
|
||||
):
|
||||
logger_a = config.setup_logger(logger_name_a)
|
||||
logger_a.info("after-first-init")
|
||||
logger_b = config.setup_logger(logger_name_b)
|
||||
logger_b.info("after-second-init")
|
||||
|
||||
with open(self.log_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
self.assertIn("after-first-init", content)
|
||||
self.assertIn("after-second-init", content)
|
||||
self.assertNotIn("legacy-line", content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user