-
Notifications
You must be signed in to change notification settings - Fork 2
Add Docker image bundling SAW + OpenClaw #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
3ffde67
Add Docker image bundling SAW + OpenClaw (#12)
frontboat 10923be
Make openclaw onboarding the default CMD (#12)
frontboat 59dff1b
Fix entrypoint daemon lifecycle, improve docs (#12)
frontboat 507f1d7
entrypoint: fix policy overwrite and daemon orphan on early exit
frontboat 187c82d
docker: switch to OpenClaw gateway mode with .env config (#12)
frontboat 0fd0ce5
entrypoint: add token guard, exit code propagation, input validation
frontboat 357a597
docker: privilege separation, cleanup, and docs overhaul
frontboat f628bb5
fix: propagate CMD exit code, fix Docker anchor in README
frontboat f95dba2
fix: propagate SAW daemon exit code during onboarding wait
frontboat 2b5f8e1
docs: restructure README into slim quick-start + docs/
frontboat 2382977
feat: setup.sh pulls pre-built image instead of building from source
frontboat 6cfe308
fix: always regenerate docker-compose.yml to pick up SAW_IMAGE changes
frontboat 4e3c7e8
fix: suppress stderr from docker exec in onboarding check
frontboat d12e377
fix: detect TTY and skip interactive onboarding when piped
frontboat cbbb9fb
feat: auto-onboard with defaults when run non-interactively
frontboat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| .env | ||
| target/ | ||
| .git/ | ||
| .github/ | ||
| *.md | ||
| !README.md | ||
| docs/ | ||
| install.sh | ||
| install-openclaw-fork.sh | ||
| packages/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| /target/ | ||
| .DS_Store | ||
| .env |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## Project Overview | ||
|
|
||
| Secure Agent Wallet (SAW) — a local signing service for AI agents. Private keys never leave the daemon process. Policy rules gate every signing request. All access is via Unix domain sockets. | ||
|
|
||
| ## Build & Test Commands | ||
|
|
||
| ```bash | ||
| # Build all Rust crates | ||
| cargo build --workspace | ||
|
|
||
| # Run all tests (CI runs this) | ||
| cargo test --workspace | ||
|
|
||
| # Run a single test by name | ||
| cargo test --workspace -- test_name | ||
|
|
||
| # Run tests for a specific crate | ||
| cargo test -p saw # CLI crate | ||
| cargo test -p saw-daemon # daemon crate | ||
|
|
||
| # Build the Node.js client | ||
| cd packages/saw && npm install && npm run build | ||
|
|
||
| # Run Node.js client tests (requires vitest) | ||
| cd packages/saw && npm test | ||
|
|
||
| # Docker (SAW daemon + OpenClaw gateway) | ||
| ./setup.sh # build, onboard (first run), start | ||
| docker compose logs -f # watch startup | ||
| ``` | ||
|
|
||
| ## Architecture | ||
|
|
||
| **Rust workspace** with two crates: | ||
|
|
||
| - **`crates/saw-cli`** (`saw` binary) — Key generation (EVM via k256/secp256k1, Solana via ed25519-dalek), policy management (YAML with `serde_yaml`, `deny_unknown_fields`), directory layout setup. The `lib.rs` exposes core types (`Chain`, `Policy`, `WalletPolicy`, `GenKeyResult`) and functions (`gen_key`, `validate_policy`, `get_address`, `list_wallets`, `install_layout`). The `cli` module parses args manually (no clap). | ||
|
|
||
| - **`crates/saw-daemon`** (`saw-daemon` binary) — AF_UNIX server that accepts JSON requests, enforces policy checks (chain allowlist, address allowlist, value limits, contract call restriction, rate limiting), signs transactions, and writes to `audit.log`. The `Server` struct in `lib.rs` holds mutable rate-limit state. Public API: `serve_once`, `serve_n`, `serve_forever`, `serve_forever_with_shutdown`. Daemon tests use `serve_n` or `serve_once` with temp directories. | ||
|
|
||
| - **`packages/saw`** (`@daydreamsai/saw` npm package) — TypeScript client that talks to the daemon over the Unix socket. Built with tsup, tested with vitest. | ||
|
|
||
| **Data layout** (default `~/.saw/`): | ||
| - `keys/{evm,sol}/<wallet>.key` — raw binary private keys (0600) | ||
| - `policy.yaml` — per-wallet signing rules (strict schema, unknown fields rejected) | ||
| - `audit.log` — append-only request log | ||
| - `saw.sock` — Unix domain socket (0660) | ||
|
|
||
| **Key patterns:** | ||
| - Both crates duplicate `Chain`, `WalletPolicy`, `Policy` types (no shared crate). The daemon re-reads `policy.yaml` on every request. | ||
| - Wallet names are validated: alphanumeric, `_`, `-`, 1-64 chars. | ||
| - EVM signing uses `secp256k1` crate for recoverable ECDSA (not k256's signer). EIP-1559 (type 2) transactions only. | ||
| - Solana signing operates on raw message bytes — no transaction parsing or policy enforcement beyond rate limits. | ||
| - Tests create isolated temp directories and use the library API directly (not shelling out to binaries). | ||
| - No async runtime — the daemon uses blocking I/O with non-blocking listener accept loop and `set_read_timeout`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # ── Stage 1: Build SAW binaries from source ────────────────────────────── | ||
| FROM rust:1.85-slim-bookworm AS builder | ||
|
|
||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| pkg-config libssl-dev \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| WORKDIR /src | ||
| COPY Cargo.toml Cargo.lock ./ | ||
| COPY crates/ crates/ | ||
|
|
||
| RUN cargo build --release --workspace \ | ||
| && strip target/release/saw target/release/saw-daemon | ||
|
|
||
| # ── Stage 2: Runtime image ──────────────────────────────────────────────── | ||
| FROM node:22-slim AS runtime | ||
|
|
||
| # SAW configuration (override at runtime) | ||
| ENV SAW_ROOT=/opt/saw \ | ||
| SAW_SOCKET=/run/saw/saw.sock \ | ||
| SAW_WALLET=main \ | ||
| SAW_CHAIN=evm \ | ||
| SAW_POLICY_TEMPLATE=conservative | ||
|
|
||
| # OpenClaw paths | ||
| ENV HOME=/home/node \ | ||
| XDG_CONFIG_HOME=/home/node/.openclaw | ||
|
|
||
| # OpenClaw build args | ||
| ARG OPENCLAW_REF=v2026.2.9-dreamclaw.14 | ||
| ARG OPENCLAW_RELEASE_REPO=https://github.com/RedBeardEth/clawdbot | ||
|
|
||
| # System deps: curl for tarball download, git for fallback source install | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| curl git ca-certificates \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Force HTTPS for GitHub (npm git tries SSH by default) | ||
| RUN git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" | ||
|
|
||
| # Install SAW binaries | ||
| COPY --from=builder /src/target/release/saw /usr/local/bin/saw | ||
| COPY --from=builder /src/target/release/saw-daemon /usr/local/bin/saw-daemon | ||
|
|
||
| # Install OpenClaw globally (try release tarball first, fallback to git) | ||
| RUN set -eux; \ | ||
| tarball_url="${OPENCLAW_RELEASE_REPO}/releases/download/${OPENCLAW_REF}/openclaw-${OPENCLAW_REF}.tgz"; \ | ||
| if curl -fsSL --head --connect-timeout 5 "$tarball_url" >/dev/null 2>&1; then \ | ||
| echo "==> Installing OpenClaw from release tarball"; \ | ||
| npm install -g "$tarball_url"; \ | ||
| else \ | ||
| echo "==> Installing OpenClaw from git source"; \ | ||
| npm install -g "git+${OPENCLAW_RELEASE_REPO}.git#${OPENCLAW_REF}"; \ | ||
| fi \ | ||
| && npm cache clean --force \ | ||
| && openclaw --version | ||
|
|
||
| # Create SAW system user and agent group; add node to saw-agent for socket access | ||
| RUN groupadd --system saw-agent \ | ||
| && useradd --system --no-create-home --shell /usr/sbin/nologin --groups saw-agent saw \ | ||
| && usermod -aG saw-agent node | ||
|
|
||
| # Initialize SAW data directory and OpenClaw config directory | ||
| RUN saw install --root "$SAW_ROOT" \ | ||
| && mkdir -p /run/saw /home/node/.openclaw/workspace \ | ||
| && chown -R saw:saw "$SAW_ROOT" /run/saw | ||
|
|
||
| COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh | ||
| RUN chmod +x /usr/local/bin/docker-entrypoint.sh | ||
|
|
||
| EXPOSE 18789 | ||
|
|
||
| HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ | ||
| CMD test -S "$SAW_SOCKET" || exit 1 | ||
|
|
||
| ENTRYPOINT ["docker-entrypoint.sh"] | ||
| CMD ["openclaw", "gateway", "--bind", "lan", "--port", "18789", "--allow-unconfigured"] | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CMD hardcodes
--bind lan --port 18789, ignoring the env vars defined above.OPENCLAW_GATEWAY_BINDandOPENCLAW_GATEWAY_PORTare set in theENVblock and can be overridden at runtime, but theCMDuses literal values. A user changing the env vars would get no effect on the gateway's actual bind/port.Switch to shell-form or reference the variables:
Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents