This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Security-focused, fully automated deployment boilerplate for OpenClaw (open-source AI agent framework). Wraps the official OpenClaw installer with server hardening, automated backups, and security update infrastructure. Not a library — this is infrastructure-as-code (shell scripts, Docker, CI).
Boilerplate version is aligned to OpenClaw releases: currently v2026.3.13.
When adapting to a new OpenClaw version:
- Read the upstream changelog: https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md
- Check the config reference: https://docs.openclaw.ai/gateway/configuration-reference
- Check security docs: https://docs.openclaw.ai/gateway/security
- Bump
.release-please-manifest.jsonto match the upstream version - Update this file's version number
shellcheck -S warning setup.sh openclaw-update.sh openclaw-restore.sh test/test-setup.shdocker build -f test/Dockerfile.test -t openclaw-test .
docker run --rm --privileged openclaw-testpython3 -c "import json; json.load(open('openclaw.json.example'))"
python3 -c "import json; json.load(open('.release-please-manifest.json'))"
docker compose config --quiet # validates docker-compose.ymlThe boilerplate has three layers:
-
Bootstrap (
setup.sh) — 21-step idempotent script run as root on a fresh Linux server. Creates theopenclawuser, hardens SSH/firewall, installs Docker/Tailscale/Node.js/OpenClaw (all checksum-verified), generatesopenclaw.json, and starts the daemon. Contains an inline fallback copy ofopenclaw-update.sh— both copies must stay in sync. -
Runtime config (
openclaw.json.example,docker-compose.yml,.env.example) — Templates with hardened defaults.setup.shgenerates the actualopenclaw.jsondynamically (the example file is documentation only). The Docker path is an alternative to the systemd daemon path. -
Maintenance (
openclaw-update.sh,openclaw-restore.sh) — Root-owned scripts installed to/usr/local/bin/. The update script runs weekly via cron with backup, version logging, and post-update security audit.
- Gateway always binds to
127.0.0.1:18789, never0.0.0.0. Remote access is via Tailscale or SSH tunnel only. auth: "none"was permanently removed upstream in v2026.1.29. Config always usesauth.mode: "token".tools.profileis explicitly set to"full"to prevent the v2026.3.2 bug that defaulted to"messaging".plugins.security.autoLoadWorkspaceisfalseto block supply chain attacks from cloned repos.tools.exec.askis"always"— every shell command requires user approval.browser.enabledisfalse— browser automation off by default (SSRF risk).session.maintenance.modeis"enforce"with 30d prune to prevent unbounded disk growth.controlUi.dangerouslyDisableDeviceAuthis explicitlyfalse.- Channel credentials flow through
sanitize_for_json()to prevent JSON injection.
Uses Conventional Commits with release-please:
fix:= patch,feat:= minor,feat!:= majorci:,chore:,docs:,test:= no releasesecurity:= patch (appears under "Security" in changelog)
All GitHub Actions pinned to immutable SHA (not tags). Dependabot updates SHAs weekly.
| Workflow | Tool | Purpose |
|---|---|---|
lint.yml |
ShellCheck | Shell script quality |
security.yml |
TruffleHog + Gitleaks + Trivy | Secrets and misconfig scanning |
test.yml |
Docker | Smoke test setup.sh in simulated VPS |
release.yml |
release-please | Automated versioning gated on all CI passing |
umask 077at top of every scriptset -euo pipefailalways- Separate
localfrom command substitution (SC2155) trapfor temp file cleanupprintf '%s'overechofor variables- File permissions: 600 for secrets/config, 700 for dirs/scripts
When editing docker-compose.yml, these must be preserved:
read_only: true+ explicittmpfsmountscap_drop: ALL, nocap_addno-new-privileges:true- Memory/CPU/PID limits and log rotation
- Health check present
- Port binding to
127.0.0.1only