9.0 KiB
OpenClaw + Claude Max API Proxy
All-in-one Docker container that runs OpenClaw powered by your Claude Max subscription through the wende/claude-max-api-proxy fork. No separate API key costs.
Architecture
Discord / Telegram / WhatsApp
↕
OpenClaw Gateway (:18789)
↓
claude-max-api-proxy (:3456)
↓
Claude Code CLI (OAuth)
↓
Anthropic API (via Max subscription)
Prerequisites
- A server running Docker (tested on Debian Trixie with CasaOS)
- A Claude Max subscription
- A Discord bot token (or Telegram/WhatsApp — see OpenClaw docs)
- Node.js 22+ is handled inside the container — no host dependency
Container Image
The image is built via Gitea Actions and pushed to the Gitea Container Registry:
gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
Deployment
1. Create data directories
sudo mkdir -p /DATA/AppData/openclaw/{claude,config,workspace}
sudo chown -R 1000:1000 /DATA/AppData/openclaw
2. Log into the Gitea container registry
docker login gitea.pitthappens.dyndns.org
Use your Gitea username and a personal access token with package:read scope.
3. Deploy the container
Use Docker Compose or paste into CasaOS Custom Install:
services:
openclaw:
image: gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
container_name: openclaw
restart: unless-stopped
ports:
- "3456:3456"
- "18789:18789"
- "18790:18790"
volumes:
- /DATA/AppData/openclaw/claude:/home/node/.claude
- /DATA/AppData/openclaw/config:/home/node/.openclaw
- /DATA/AppData/openclaw/workspace:/home/node/.openclaw/workspace
environment:
- HOME=/home/node
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=lan
- OPENCLAW_GATEWAY_TOKEN=your-secure-token-here
- OPENAI_API_KEY=not-needed
- OPENAI_BASE_URL=http://127.0.0.1:3456/v1
- TZ=America/Chicago
healthcheck:
test: ["CMD", "curl", "-sf", "http://127.0.0.1:3456/health"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
init: true
Generate a secure gateway token with:
openssl rand -hex 32
4. Authenticate Claude Code (one-time)
The container will boot-loop until Claude is authenticated. Stop it first, then run auth in a one-off container:
docker stop openclaw
docker run -it --rm \
-v /DATA/AppData/openclaw/claude:/home/node/.claude \
gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest \
/usr/local/bin/entrypoint.sh auth
This starts the Claude Code OAuth flow. You'll get a URL to open in your browser — sign in with your Claude Max account. Credentials are saved to the mounted volume and persist across container restarts.
Start the container after auth completes:
docker start openclaw
5. Configure OpenClaw
Edit the config file directly:
cat > /DATA/AppData/openclaw/config/openclaw.json << 'EOF'
{
"env": {
"OPENAI_API_KEY": "not-needed"
},
"models": {
"providers": {
"claude-proxy": {
"api": "openai-completions",
"baseUrl": "http://127.0.0.1:3456/v1",
"apiKey": "not-needed",
"models": [
{
"id": "claude-sonnet-4",
"name": "Claude Sonnet 4"
}
]
}
}
},
"agents": {
"defaults": {
"workspace": "/home/node/.openclaw/workspace",
"model": {
"primary": "claude-proxy/claude-sonnet-4"
}
}
},
"gateway": {
"mode": "local",
"bind": "lan"
}
}
EOF
To add more models (e.g. Opus), add entries to the models array:
{
"id": "claude-opus-4",
"name": "Claude Opus 4"
}
Then set the primary model to claude-proxy/claude-opus-4.
Restart after editing config:
docker restart openclaw
6. Connect Discord
docker exec -it openclaw bash -c \
"cd /opt/openclaw && node dist/index.js channels add --channel discord --token YOUR_DISCORD_BOT_TOKEN"
Then DM or mention the bot on Discord. It will respond with a pairing code. Approve it:
docker exec openclaw bash -c \
"cd /opt/openclaw && node dist/index.js pairing approve discord YOUR_CODE"
Send another message — the bot should now respond.
7. Verify everything is working
# Check logs
docker logs -f openclaw
# Test the proxy directly
docker exec openclaw curl -s http://127.0.0.1:3456/health
# Test a completion
docker exec openclaw curl -s http://127.0.0.1:3456/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4","messages":[{"role":"user","content":"Hello"}]}'
# Check OpenClaw status
docker exec openclaw bash -c "cd /opt/openclaw && node dist/index.js status"
Updating
After a new image is built by CI:
docker pull gitea.pitthappens.dyndns.org/ragincajunbanjo/openclaw-proxy:latest
docker restart openclaw
Or from CasaOS, use the container's rebuild/update button.
Your config, credentials, and workspace are on persistent volumes and survive updates.
CI/CD Pipeline
Gitea Actions
The repo includes a workflow at .gitea/workflows/build-deploy.yml that builds the Docker image and pushes it to the Gitea Container Registry on every push to main.
Required Gitea Setup
-
Enable packages and actions in Gitea's
app.ini:[packages] ENABLED = true [actions] ENABLED = true DEFAULT_ACTIONS_URL = https://github.comRestart Gitea after editing.
-
Install and register an Act Runner on the server:
sudo wget -O /usr/local/bin/act_runner \ https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64 sudo chmod +x /usr/local/bin/act_runner sudo mkdir -p /opt/gitea-runner cd /opt/gitea-runner sudo act_runner register \ --instance https://gitea.pitthappens.dyndns.org \ --name local-runner \ --labels ubuntu-latest:hostGet the registration token from Gitea → Site Administration → Actions → Runners.
-
Create a systemd service for the runner:
sudo tee /etc/systemd/system/gitea-runner.service << 'SVCEOF' [Unit] Description=Gitea Act Runner After=docker.service Requires=docker.service [Service] Type=simple User=root WorkingDirectory=/opt/gitea-runner ExecStart=/usr/local/bin/act_runner daemon Restart=always RestartSec=5 [Install] WantedBy=multi-user.target SVCEOF sudo systemctl daemon-reload sudo systemctl enable --now gitea-runner -
Add repo secrets (Repo → Settings → Actions → Secrets):
REGISTRY_TOKEN— Gitea personal access token withpackage:writescopeDOCKERHUB_USERNAME— Docker Hub username (avoids pull rate limits during builds)DOCKERHUB_TOKEN— Docker Hub access token
Persistent Volumes
| Host Path | Container Path | Purpose |
|---|---|---|
/DATA/AppData/openclaw/claude |
/home/node/.claude |
Claude Code OAuth credentials |
/DATA/AppData/openclaw/config |
/home/node/.openclaw |
OpenClaw settings and memory |
/DATA/AppData/openclaw/workspace |
/home/node/.openclaw/workspace |
Agent working directory |
Troubleshooting
| Problem | Solution |
|---|---|
| Container boot-loops with "No Claude credentials" | Run the one-off auth container (Step 4) |
| "Unknown model" on startup | Ensure models.providers is defined in openclaw.json with the correct structure (Step 5) |
Proxy returns [object Object] |
You may have the broken original npm package — rebuild with --no-cache |
| OAuth token expired | Re-run the auth step: docker run -it --rm -v /DATA/AppData/openclaw/claude:/home/node/.claude <image> /usr/local/bin/entrypoint.sh auth |
| Discord bot doesn't respond | Check pairing: docker exec openclaw bash -c "cd /opt/openclaw && node dist/index.js pairing list" and approve any pending codes |
| "Control UI build failed" in logs | Cosmetic only — the gateway works fine without it |
| Docker Hub rate limit during CI build | Add DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets to the repo |
| OpenClaw requires Node >= 22 | Make sure the Dockerfile uses node:22-bookworm-slim as the base image |
env: node: No such file or directory |
Background services (LaunchAgent/systemd) don't inherit shell PATH — use full paths to node |
Important Notes
- The
claude-max-api-proxyis a community tool, not officially supported by Anthropic or OpenClaw. It wraps the Claude Code CLI to expose an OpenAI-compatible API using your Max subscription's OAuth credentials. - The proxy binds to
127.0.0.1:3456inside the container. Port 3456 is exposed for debugging but the proxy is only used internally by OpenClaw. - This setup uses the wende fork which fixes a serialization bug in the original package that caused responses to return
[object Object].