OpenClaw Deploy¶
OpenClaw Deploy Role¶
Deploys the OpenClaw gateway on Ubuntu using Docker Compose and systemd. The gateway supports multiple messaging channels (Telegram, WhatsApp) with AI-powered replies via configured providers (Anthropic/OpenAI/OpenRouter/Ollama).
Key Difference¶
Unlike other service roles, OpenClaw has no prebuilt Docker image. This role clones the source repo and runs docker build on-host using the upstream Dockerfile. The build is skipped when the image+tag already exists and the source hasn’t changed.
Lifecycle Exception (Backup/Restore)¶
OpenClaw intentionally does not provide openclaw_backup or openclaw_restore roles.
Backup/restore is centralized through Echoport.
Do not use
just backup openclaworjust restore openclaw.Use the operator commands and restore-drill workflow in
ops-control/docs/OPENCLAW_RUNBOOK.md(privateops-controlrepo).
Quick Start¶
- hosts: macmini
become: true
roles:
- role: local.ops_library.openclaw_deploy
vars:
openclaw_version: "v2026.5.7"
openclaw_data_dir: "/mnt/cryptdata/openclaw/data"
openclaw_gateway_token: "{{ sops_secrets.gateway_token }}"
openclaw_anthropic_api_key: "{{ sops_secrets.anthropic_api_key }}"
openclaw_telegram_enabled: true
openclaw_telegram_bot_token: "{{ sops_secrets.telegram_bot_token }}"
openclaw_telegram_allow_from:
- 304012876
openclaw_traefik_enabled: true
openclaw_traefik_host: "openclaw.macmini.tailde2ec.ts.net"
Architecture¶
OpenClaw runs as a Docker container managed by a systemd oneshot unit.
The source repo is cloned to a build directory and
docker buildcreates the image using the upstream Dockerfile. The container uses the upstreamCMD— no command override in compose.The gateway handles all messaging channels internally (Telegram via grammY, etc.).
AI replies are handled by the gateway using configured provider APIs — no external scripts needed.
Optional model policy patching can enforce a default model and ordered fallback chain under
agents.defaults.model.Persistent state (sessions, config) is stored in a bind-mounted directory owned by container uid 1000.
The container binds to
127.0.0.1:18789by default, with optional Traefik reverse proxy for external access. When Traefik is enabled, the bind host is validated to be loopback.When Traefik is enabled, role-managed config sets
gateway.bind: "lan"andgateway.controlUi.allowedOriginstohttps://<openclaw_traefik_host>so the host-side reverse proxy can reach the gateway UI safely.Role-managed gateway hardening sets explicit
gateway.trustedProxies, disablesgateway.allowRealIpFallback, and configuresgateway.auth.rateLimit.Gateway config (
openclaw.json) is seeded once on first deploy and not overwritten on subsequent runs (useopenclaw_force_config: trueto overwrite). Existing configs are patched to ensure unused plugins (WhatsApp) are explicitly disabled.Logs are written to a bind-mounted log directory with automatic logrotate.
Optional: an authenticated loopback HTTP endpoint (
/.well-known/openclaw-health) can be enabled for Nyxmonjson-metricschecks.
Role Variables¶
Required Variables¶
Variable |
Description |
|---|---|
|
Git tag to checkout and build (e.g. |
|
Gateway authentication token |
|
Anthropic API key for AI replies |
Networking¶
Variable |
Default |
Description |
|---|---|---|
|
|
Host IP to bind the container port |
|
|
Host port for the gateway |
|
|
Container port for the gateway |
Gateway Hardening¶
Variable |
Default |
Description |
|---|---|---|
|
|
File mode used for |
|
|
Trusted proxy IP/CIDR list written to |
|
|
Controls |
|
|
Enable |
|
|
Failed auth attempts per window |
|
|
Rate-limit window in ms |
|
|
Lockout duration in ms after threshold |
|
|
Exempt loopback clients from auth rate limiting |
Telegram Channel¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable Telegram channel |
|
|
Telegram bot token (required when enabled) |
|
|
DM policy: |
|
|
Numeric Telegram user IDs for allowlist |
AI Configuration¶
Variable |
Default |
Description |
|---|---|---|
|
|
Optional OpenAI API key ( |
|
|
Optional OpenRouter API key ( |
|
|
Optional Ollama API key ( |
|
|
Optional Ollama endpoint ( |
|
|
System prompt for AI replies |
Model Routing Policy¶
Variable |
Default |
Description |
|---|---|---|
|
|
Optional default model ( |
|
|
Optional ordered fallback list ( |
Build Configuration¶
Variable |
Default |
Description |
|---|---|---|
|
|
Shallow checkout depth for the tag-pinned upstream source |
|
|
Limit source checkout to the requested tag/branch instead of all upstream refs |
|
|
Docker image name |
|
|
Docker image tag |
|
|
Force Docker image rebuild even if image exists |
Traefik Reverse Proxy¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable Traefik reverse proxy configuration |
|
|
Hostname for Traefik router (required when enabled) |
|
|
Path for Traefik dynamic config |
|
|
Traefik entrypoints to listen on |
|
|
TLS cert resolver (empty = default TLS) |
Nyxmon Metrics Endpoint¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable OpenClaw JSON metrics endpoint for Nyxmon |
|
|
Bind address for endpoint service |
|
|
Endpoint port |
|
|
Endpoint path |
|
|
Basic-auth username (required when enabled) |
|
|
Basic-auth password (required when enabled) |
|
|
Collector timer interval in seconds |
|
|
OpenClaw container queried by collector |
|
|
Remove |
|
|
Enable synthetic real agent-turn canary collection in metrics payload |
|
|
Optional agent id for canary command; leave empty to route by |
|
|
Session id prefix used for stateless canary attempts; each due run appends epoch/attempt suffixes to avoid context growth and lock contention |
|
|
Deterministic prompt for canary request |
|
|
Expected canary marker text (success when present as a standalone trimmed line) |
|
|
Minimum seconds between canary executions (collector cycles in between use cached result) |
|
|
Per-attempt timeout (seconds) for canary command |
|
|
Max attempts per due canary run |
|
|
Delay between failed canary attempts |
|
|
Local state file for last canary result |
|
|
Host OpenClaw sessions directory used to clean generated canary session files |
|
|
Seconds to retain generated canary session/trajectory files; set |
|
|
Max response chars persisted from canary output |
Mail Skill (/mail): IMAP Read + SMTP Send¶
When openclaw_imap_enabled: true, the role deploys the /mail command skill and handler. IMAP
command surface:
/mail unread [--account <name>]/mail list [--account <name>] [--limit N]/mail read <uid> [--account <name>]/mail search <query> [--account <name>] [--limit N]
Optional phase-2 SMTP send command (requires openclaw_smtp_enabled: true):
/mail send --to <email[,email...]> --subject <text> --body <text> [--account <name>] [--cc <email[,email...]>] [--bcc <email[,email...]>]
Safety guarantees:
IMAP path remains read-only (
SELECT ...readonly +SEARCH/FETCHonly).SMTP path supports plain-text send only (no attachments, no HTML composition).
Body formatting supports real newlines and escaped
\n/\r\nsequences in/mail send --body.Strict recipient/address validation with newline/header-injection rejection.
Bounded recipients/subject/body lengths with explicit limits.
SMTP body normalization handles common shell/LLM artifacts in
--body, including:shell-quoted wrappers (
$'...'/$"..."),escaped newline/tab tokens (
\n,\r,\t),mixed payloads with both escaped tokens and real newlines.
Sender identity is account-configured only: optional
from_nameandreply_toare static per account (not user-provided at command time).SMTP success confirms handoff acceptance to the configured relay/MTA; final inbox placement depends on downstream recipient filtering.
Per-account credentials are split by purpose:
IMAP readers:
imap_accounts.jsonSMTP senders:
smtp_accounts.json
IMAP Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
IMAP host reachable from OpenClaw container |
|
|
IMAP port |
|
|
TLS mode: |
|
|
Mailbox opened in read-only mode |
|
|
Account map ( |
|
|
Default logical account name |
|
|
Handler skill directory name |
|
|
Slash command skill directory name |
|
|
Host skill root for IMAP skill files |
|
|
Rendered credential map (mode |
|
|
Container path used by IMAP handler |
|
|
IMAP connection timeout |
|
|
IMAP command timeout |
|
|
Default message listing limit |
|
|
Max allowed |
|
|
Max chars for header fields in output |
|
|
Max chars for subject in output |
|
|
Max bytes fetched for read snippet |
|
|
Max chars returned in |
|
|
Max |
SMTP Variables (Phase-2 Send)¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
SMTP host reachable from OpenClaw container |
|
|
SMTP submission port |
|
|
TLS mode: |
|
|
Account map ( |
|
|
Default sender account for |
|
|
Rendered SMTP credential map (mode |
|
|
Container path used by SMTP handler branch |
|
|
SMTP connection timeout |
|
|
SMTP command timeout |
|
|
Max total recipients across To/Cc/Bcc |
|
|
Max length for sender/recipient address fields |
|
|
Max configured sender display-name length ( |
|
|
Max |
|
|
Max |
Calendar Skill (/calendar): CalDAV Read + Guarded Create/Edit/Delete¶
When openclaw_calendar_enabled: true, the role deploys a /calendar command skill and handler
using CalDAV calendars with explicit read/write allowlists per calendar id.
Command surface:
/calendar today/calendar tomorrow/calendar on <YYYY-MM-DD>/calendar week [--start <YYYY-MM-DD>]/calendar free --at <datetime> [--duration <minutes>]/calendar create --calendar <id> --title <text> --start <datetime> [--duration <minutes>] [--repeat daily|weekly|monthly] [--count N | --until YYYY-MM-DD]/calendar edit <event_id> [--title <text>] [--start <datetime>] [--duration <minutes>]/calendar delete <event_id> --confirm
Safety guarantees:
Read and write access are configured per calendar entry in
openclaw_calendar_map.Write attempts to non-writable calendars are denied deterministically.
Event IDs are generated from calendar-local CalDAV resource paths and are required for edit/delete.
Delete always requires explicit
--confirm.Edit handles stale-write conflicts explicitly: CalDAV
HTTP 412returns a retry guidance message.Recurrence is bounded to
daily|weekly|monthlywith optionalcountoruntil.Recurring-event reads/free-time checks use CalDAV expansion for occurrence-correct results.
Event creation uses UTC timestamps (
DTSTART/DTEND ...Z) to avoid timezone-component interoperability issues.iCalendar lines are folded to RFC-friendly lengths for better CalDAV compatibility.
Read commands use bounded parallelism with explicit aggregate timeout handling.
Read commands degrade gracefully: if one calendar fails/times out, results from healthy calendars are still returned with warnings.
Aggregate timeout applies to fan-out coordination; effective wall time can exceed it by up to one per-calendar request timeout.
CalDAV
401/403responses are tracked in a bounded health-state cache for operational alerting.Bounded output and strict datetime/date validation.
Sanitized operational errors (no credential leakage).
Calendar Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
Timezone used for parsing/rendering and event creation |
|
|
Handler skill directory name |
|
|
Slash command skill directory name |
|
|
Host skill root for calendar skill files |
|
|
Container path used by calendar command skill |
|
|
Rendered runtime calendar config ( |
|
|
Container runtime config path used by handler |
|
|
Optional credential map ( |
|
|
Optional default account id used when a calendar entry omits |
|
|
Calendar map ( |
|
|
Default duration for |
|
|
CalDAV request timeout |
|
|
Max concurrent per-calendar read requests for |
|
|
Aggregate timeout for multi-calendar read fan-out |
|
|
Default list limit for |
|
|
Maximum list limit for |
|
|
Max rendered/stored title chars |
|
|
Max rendered location chars |
|
|
Host path for sanitized calendar auth-failure health cache ( |
|
|
Container path for calendar auth-failure health cache |
|
|
Rolling window used to count recent calendar auth failures |
|
|
Threshold for repeated calendar auth failures in the rolling window |
Credential resolution order for each openclaw_calendar_map entry:
accountfield (oropenclaw_calendar_default_account) referencingopenclaw_calendar_account_map.Inline
username+passwordon the calendar entry (backward compatibility path).
Paperless Skill (/paperless): Read-Only Search + Telegram Delivery¶
When openclaw_paperless_enabled: true, the role deploys a /paperless command skill and handler
using the Paperless-ngx REST API with read-only endpoint usage.
Command surface:
/paperless search <query> [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--limit N]/paperless get <document_id> [--original|--archived](defaults to original file)/paperless latest [--query <text>] [--days N] [--limit N]
Safety guarantees:
Handler uses stdlib HTTP client (
urllib.request) with explicit redirect deny.Endpoint surface is read-only (
GET /api/documents/,GET /api/documents/<id>/,GET /api/documents/<id>/download/).Command skill execution assumes argv-style invocation by OpenClaw (no shell interpolation of raw user input).
Metadata-only search output format:
#{id} | {title} | {correspondent} | {created_date}
Bounded limits (
default=5,max=10) and bounded field lengths.Separate search timeout and download timeout.
Download guardrails enforce Telegram upload cap behavior:
if
Content-Lengthis known and exceeds cap, skip body download and return deterministic URL fallback;if
Content-Lengthis absent, stream with hard cap and abort deterministically when exceeded.
Delivery target resolution is bounded and deterministic:
runtime invocation context/env (preferred),
recent OpenClaw session-state target when uniquely resolvable,
otherwise URL fallback with explicit reason.
HTTP 401/403auth failures are tracked in rolling-window health state for metrics/Nyxmon alerting.Sanitized errors only (no token/header leakage).
Paperless Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
Paperless base URL reachable from OpenClaw container |
|
|
Paperless API token (required when enabled) |
|
|
Handler skill directory name |
|
|
Slash command skill directory name |
|
|
Host skill root for Paperless skill files |
|
|
Container path used by Paperless command skill |
|
|
Rendered Paperless runtime config ( |
|
|
Container runtime config path used by handler |
|
|
Host path for Paperless auth-failure rolling state ( |
|
|
Container path for Paperless auth-failure rolling state |
|
|
Search/list request timeout |
|
|
Download request timeout |
|
|
Telegram media-send timeout |
|
|
Default search/list limit |
|
|
Maximum search/list limit |
|
|
Default lookback window for |
|
|
Maximum allowed |
|
|
Max rendered title chars |
|
|
Max rendered correspondent chars |
|
|
Max file size cap in bytes (50 MB hard limit) |
|
|
Stream chunk size used for capped downloads |
|
|
Host temp downloads directory for handler |
|
|
Container temp downloads directory used by handler |
|
|
Host OpenClaw session-state JSON used for delivery-target fallback |
|
|
Container path to OpenClaw session-state JSON used by handler |
|
|
Max age for session-state target fallback candidates |
|
|
Delivery channel (fixed to Telegram) |
|
|
Rolling window used to count recent Paperless auth failures |
|
|
Threshold for repeated Paperless auth failures in rolling window |
Home Assistant Skill (/homeassistant): Read + Guarded Write¶
When openclaw_homeassistant_enabled: true, the role deploys a /homeassistant command skill and handler
using the Home Assistant REST API with a tightly restricted command surface.
Command surface:
/homeassistant state <entity_id>/homeassistant list [--domain <domain>] [--limit N]/homeassistant turn_on <entity_id>/homeassistant turn_off <entity_id>
Safety guarantees:
Read endpoint usage is restricted to
GET /api/statesandGET /api/states/<entity_id>.Write endpoint usage is restricted to:
POST /api/services/homeassistant/turn_onPOST /api/services/homeassistant/turn_off
Explicit read and write allowlists are enforced separately in-handler.
Write policy is entity-first: prefer
openclaw_homeassistant_allow_write_entitiesand keepopenclaw_homeassistant_allow_write_domainsempty unless a reviewed exception is required.Strict entity/domain input validation.
Bounded output (limit/field truncation/attribute cap) and request timeout.
Sanitized operational errors (no token/header leakage).
Operational note:
OpenClaw caches skill snapshots per session. The role now invalidates cached
skillsSnapshotentries and rotates existing session bindings automatically when the managed slash-skill set changes, so pre-existing sessions pick up newly deployed commands in a fresh session context on the next message.
Home Assistant Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
Home Assistant base URL reachable from OpenClaw container |
|
|
Home Assistant long-lived API token (required when enabled) |
|
|
Handler skill directory name |
|
|
Slash command skill directory name |
|
|
Host skill root for Home Assistant skill files |
|
|
Container path used by Home Assistant command skill |
|
|
Rendered Home Assistant runtime config ( |
|
|
Container runtime config path used by handler |
|
|
Allowed Home Assistant domains (for example |
|
|
Allowed full entity IDs (for example |
|
|
Exception path: allowed write domains for `/homeassistant turn_on |
|
|
Primary write allowlist: explicit entity IDs for `/homeassistant turn_on |
|
|
Home Assistant HTTP timeout per request |
|
|
Default |
|
|
Maximum |
|
|
Max chars for rendered state values |
|
|
Max chars for rendered friendly names |
|
|
Max rendered attribute key/value pairs in |
|
|
Max chars per rendered attribute value |
OpsGate Skill (/opsgate): Explicit Investigator Ticket Submit¶
When openclaw_opsgate_enabled: true, the role deploys a /opsgate command skill, a
deterministic local plugin tool, and the audited submit handler that creates a new OpsGate
ticket through the existing submit-token API.
Command surface:
/opsgate create [--title <text>] [--task-ref <text>] <issue description>
Safety guarantees:
The handler submits exactly one fixed workflow shape:
one step
role
investigatoragent
codex
/opsgate ...is wired to a deterministic local plugin tool instead of relying on prompt-only inference.The handler cannot approve, reject, cancel, archive, or mutate existing OpsGate tickets.
The skill does not submit arbitrary execution plans or reviewer/implementer workflows.
OpsGate approval is still required before any execution happens.
Approval links can use a different base URL from the internal submit endpoint, which matches the current split deploy model (
submitvia internal service URL,approve/viewvia operator HTTPS URL).
Operational note:
Both
openclaw agent --message '/opsgate ...' --jsonand long-lived Telegram chats use the same deterministic local plugin path.When the managed slash-skill set changes, the role automatically invalidates cached skill snapshots and rotates existing session bindings so pre-existing Telegram sessions pick up
/opsgateand other managed slash skills on the next message.
OpsGate Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable |
|
|
OpsGate API base URL reachable from the OpenClaw container |
|
|
Optional operator-facing base URL used for returned ticket links (defaults to submit base URL) |
|
|
OpsGate submit token for source |
|
|
Local OpenClaw plugin id used for deterministic slash-command dispatch |
|
|
Tool name registered by the local OpsGate plugin |
|
|
Host root for local OpenClaw extensions |
|
|
Host path for the OpsGate local plugin |
|
|
Handler skill directory name |
|
|
Slash command skill directory name |
|
|
Host skill root for OpsGate skill files |
|
|
Container path used by OpsGate command skill |
|
|
Rendered OpsGate runtime config ( |
|
|
Container runtime config path used by handler |
|
|
HTTP timeout for OpsGate ticket creation |
|
|
Ticket expiry window in seconds ( |
|
|
Max generated or user-supplied title length |
|
|
Max generated summary length |
|
|
Max captured issue description length |
|
|
Max |
Handler unit tests for managed OpenClaw integration handlers live at:
tests/unit/test_openclaw_homeassistant_handler.pytests/unit/test_openclaw_calendar_handler.pytests/unit/test_openclaw_opsgate_handler.pytests/unit/test_openclaw_paperless_handler.py
Advanced¶
Variable |
Default |
Description |
|---|---|---|
|
|
Full config override — rendered directly as |
|
|
Overwrite |
|
|
Host session-state JSON patched when managed slash-skill snapshots must be invalidated |
|
|
Host manifest file used to detect managed slash-skill set changes across deploys |
|
|
Extra environment variables merged into the container env |
|
|
Persistent data directory (bind-mounted into container) |
|
|
Log directory (bind-mounted to |
|
|
Docker container memory limit |
|
|
Docker container CPU limit |
|
|
Docker container PID limit |
|
|
Node.js memory limit (MB) |
|
|
Days to retain rotated log files |
Feature Flags¶
Variable |
Default |
Description |
|---|---|---|
|
|
Install Docker via docker_install role |
|
|
Create system user/group |
|
|
Run post-deploy health check (TCP + container) |
For a complete list, see defaults/main.yml.
Gateway Configuration¶
The role seeds openclaw.json into the data directory on first deploy. By default, it builds the config from individual openclaw_telegram_* variables with explicit plugin control (unused channels like WhatsApp are disabled). Once seeded, the config is not overwritten on subsequent deploys — set openclaw_force_config: true to re-render. Existing configs are still patched for role-managed plugin entries and legacy Telegram streaming aliases required by newer OpenClaw schemas.
To provide a full custom config, set openclaw_gateway_config:
openclaw_gateway_config:
channels:
telegram:
enabled: true
dmPolicy: allowlist
allowFrom: [304012876]
plugins:
load:
paths:
- /home/openclaw/data/extensions/opsgate-submit
entries:
telegram:
enabled: true
opsgate-submit:
enabled: true
whatsapp:
enabled: false
Health Check¶
The role performs a two-stage health check after deploy:
TCP port check —
wait_foron the bound host/port (TCP connect)Container check — verifies the Docker container is in running state
Note: The deploy health check intentionally uses TCP + container state. OpenClaw also serves a control UI over HTTP, but role health checks avoid endpoint/auth coupling.
Nyxmon Monitoring Integration¶
When openclaw_metrics_endpoint_enabled: true:
a root collector timer (
openclaw-metrics-collector.timer) runsdocker exec <container> node dist/index.js ... --jsonand writes JSON to:{{ openclaw_metrics_endpoint_json_path }}
an unprivileged HTTP server (
{{ openclaw_metrics_endpoint_service_name }}) serves the JSON with basic auth at:http://{{ openclaw_metrics_endpoint_bind }}:{{ openclaw_metrics_endpoint_port }}{{ openclaw_metrics_endpoint_path }}
response includes
meta.age_secondsto detect stale collector output.the collector timer schedules from timer activation and from collector completion, so post-reboot timer activation cannot leave the unit in an elapsed state with no next run.
collector runs that execute the synthetic canary can take longer than one timer tick (
openclaw_metrics_endpoint_timer_interval); systemd oneshot does not overlap runs.$.openclaw.collector_okmeans the collector executed and parsed required metrics inputs. A nonzerohealth --jsonresult with parseable JSON is still collected so warning-class health sub-signals, such as Telegram Bot API probe failures, do not masquerade as collector failures.optional synthetic canary mode executes a real
agent --jsonliveness turn at a conservative cadence and stores:uses a dedicated canary session id prefix (
probe-openclaw-canaryby default)appends epoch/attempt suffixes to each due canary attempt so stale canary history cannot grow the prompt or leave retry attempts contending on an abandoned session lock
removes generated canary session and trajectory files after
openclaw_metrics_endpoint_synthetic_canary_session_retention_secondstreats files beginning with the configured canary prefix as generated canary artifacts; do not create long-lived manual sessions under that prefix
does not edit OpenClaw’s lightweight
sessions.jsonindex; old canary index entries may remain after backing session files are removedpasses
--timeoutto the OpenClaw CLI and keeps a short outer subprocess grace window$.openclaw.synthetic.canary.last_run.ok$.openclaw.synthetic.canary.last_run.expected_match$.openclaw.synthetic.canary.last_run.session_id$.openclaw.synthetic.canary.last_success_epoch$.openclaw.synthetic.canary.last_success_age_secondslast_success_age_secondsis always numeric (2147483647sentinel when there is no successful run yet)
Designed for Nyxmon json-metrics checks, for example:
$.openclaw.collector_ok == true$.openclaw.health.telegram_probe_ok == true(warning)$.openclaw.channels.telegram.running == true$.openclaw.calendar.auth.has_repeated_failures == false$.openclaw.calendar.auth.has_recent_failures == false$.openclaw.paperless.auth.has_repeated_failures == false$.openclaw.paperless.auth.has_recent_failures == false$.meta.age_seconds < 600$.openclaw.synthetic.canary.last_run.ok == true(synthetic check)
Weeknotes/Todo Automation¶
When openclaw_weeknotes_enabled: true, the role deploys a weeknotes handler plus command skills (/todo, /note, /snooze) that provide chat-driven todo and journal management. Weeknotes data is stored under a dedicated directory with pre-edit snapshots and an append-only operation log.
Commands: /todo add, /todo list, /note add, /note find, /snooze. A daily cron reminder summarizes open todos on weekdays (noise-suppressed when empty; can be snoozed per-day with /snooze).
Weeknotes Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Enable weeknotes/todo skill |
|
|
Timezone for the container ( |
|
|
Handler directory name under |
|
|
Slash command skill names deployed as |
|
|
Host path for custom skills |
|
|
Host path for weeknotes data |
|
|
Container mount for weeknotes |
|
|
Container mount for skills |
|
|
Storage backend: |
|
|
Max snapshots retained per file |
|
|
Max snapshot age in days |
|
|
File lock timeout in seconds |
|
|
Max payload length for write operations |
|
|
Max writes per rate-limit window |
|
|
Rate-limit window in seconds |
|
|
Cron schedule for daily reminder |
|
|
System-event text sent by reminder cron job |
Weeknotes S3 Backend Variables¶
Used when openclaw_weeknotes_backend: s3.
Variable |
Default |
Description |
|---|---|---|
|
|
S3/MinIO endpoint URL |
|
|
S3 region string |
|
|
Bucket name |
|
|
Optional object key prefix |
|
|
Access key for weeknotes service account |
|
|
Secret key for weeknotes service account |
|
|
|
|
|
Todo-list source mode: |
|
|
Regex used in |
|
|
Cache refresh interval for |
|
|
MinIO client alias name used by handler |
|
|
Host path to MinIO client binary (bind-mounted read-only) |
|
|
Container path for MinIO client binary |
Storage Model¶
localbackend: weekly filesYYYY-Www.md(e.g.,2026-W09.md)s3backend: direct object-store reads/writes usingopenclaw_weeknotes_s3_note_key_format(default daily keys like2026-02-25.md)Pre-edit snapshots:
.snapshots/<file-or-key>.<timestamp>.bakOperation log:
.ops-log.jsonl(append-only)
Docker Compose Services¶
openclaw-gateway: Main gateway service, starts with
docker compose upopenclaw-cli: CLI utility, available via
docker compose run --rm openclaw-cli <subcommand>(usesprofiles: [cli], does not auto-start, and shares the gateway network namespace so CLI commands can reachws://127.0.0.1:18789)
Post-Deploy: Telegram¶
If using allowlist dm_policy with allowFrom, messages from listed users should work immediately. If pairing is needed:
docker compose -f /home/openclaw/site/docker-compose.yml \
run --rm openclaw-cli pairing list telegram
docker compose -f /home/openclaw/site/docker-compose.yml \
run --rm openclaw-cli pairing approve telegram <CODE>
Handlers¶
reload systemd— Daemon reload after unit file changesrestart openclaw— Restart the systemd servicereload traefik— Restart Traefik after config changes
Testing¶
# Check container status
systemctl status openclaw
docker compose -f /home/openclaw/site/docker-compose.yml ps
# View logs
docker logs openclaw-gateway --tail 50
docker compose -f /home/openclaw/site/docker-compose.yml logs -f
# CLI access
docker compose -f /home/openclaw/site/docker-compose.yml run --rm openclaw-cli <subcommand>
# Verify Traefik routing (from Tailscale device)
curl -k https://openclaw.macmini.tailde2ec.ts.net/
License¶
MIT