Deployment
Deployment
The A → B → C deployment ladder: from local Claude Code to a persistent, hardened OpenClaw service.
Three Stages
| Stage | Environment | What you get |
|---|---|---|
| (A) Claude Code | Local machine + TypeDB | Interactive, fast iteration, direct file editing. See Getting Started. |
| (B) OpenClaw on Mac Mini | Dedicated Mac + Docker Desktop | Persistent service, Telegram triage, LiteLLM credential brokering, cron foraging |
| (C) OpenClaw on VPS | Hardened Linux server + rootless Podman | Always-on, SSH hardened, UFW firewall, Fail2Ban, Tailscale VPN |
What’s in the deployed stack
All three components (B and C) deploy the same service stack:
| Component | Purpose |
|---|---|
| OpenClaw agent | Main agentic interface; handles requests from Claude |
| TypeDB | Knowledge graph backend (containerized) |
| MCP server | Skills bridge between agent and TypeDB |
| LiteLLM proxy | Credential brokering (requires ≥ 1 GB memory) |
| Squid proxy | Egress filtering for agent network access |
| Dashboard | Next.js UI at port 3001 |
| Telegram bot | Async notifications and triage interface |
Prerequisites
On your control machine (the laptop running deploy.sh):
ansibleandansible-playbookopensslandssh-keygen- SSH access to the target host
On the target (Mac Mini or VPS):
- Docker Desktop (Mac Mini) or Docker Engine (VPS)
- SSH server running; your SSH key in
authorized_keys
Deployment
Interactive (recommended for first run)
cd deploy
./deploy.sh
Prompts for all required values and saves them to deploy/deploy.env for future runs.
Non-interactive (Mac Mini)
./deploy.sh \
-t 10.0.110.100 \
--target-type macmini \
-p anthropic \
-m claude-sonnet-4-6 \
-k "$ANTHROPIC_API_KEY"
Non-interactive (VPS)
./deploy.sh \
-t 5.78.187.158 \
--target-type vps \
-p anthropic \
-m claude-sonnet-4-6 \
-k "$ANTHROPIC_API_KEY"
Make targets (shorthand after deploy.env is configured)
make deploy-macmini # deploy to Mac Mini
make deploy-vps # deploy to VPS (hardened Linux)
Configuration
deploy/deploy.env (gitignored):
| Variable | Description |
|---|---|
DEPLOY_TARGET |
IP address or hostname of target |
DEPLOY_TARGET_TYPE |
macmini or vps |
DEPLOY_PROVIDER |
anthropic or ollama |
DEPLOY_MODEL |
Model ID (e.g. claude-sonnet-4-6) |
DEPLOY_API_KEY |
Anthropic API key (never commit) |
DEPLOY_TELEGRAM_TOKEN |
Optional: Telegram bot token |
DEPLOY_TELEGRAM_USER |
Optional: Your Telegram user ID |
DEPLOY_ASK_PASS |
true to prompt for SSH/sudo password |
VPS Security Features (Stage C)
The VPS deployment applies these hardening measures automatically:
- UFW firewall — only SSH (22), HTTPS (443), and Tailscale (51820) are open
- Fail2Ban — brute-force SSH protection
- SSH key-only auth — password authentication disabled
- Rootless Podman — containers run without root privileges
- Tailscale VPN — dashboard and agent accessible over private network;
make tailscale-serveexposes dashboard over HTTPS
Known Issues
Anthropic SDK proxy bug: The @anthropic-ai/sdk honors HTTP_PROXY but ignores NO_PROXY. The agent container must NOT have proxy environment variables set — it gets direct internet access via the openclaw-external Docker network. The deploy.sh script handles this correctly; avoid manually setting proxy env vars.
LiteLLM memory: LiteLLM needs at least mem_limit: 1g. The 512 MB default causes OOM on startup. The deploy script sets this correctly.
Model IDs: Use exact Anthropic model IDs (claude-sonnet-4-6, claude-opus-4-6, claude-haiku-4-5-20251001). Incorrect IDs return HTTP 404 silently.
Post-Deployment
After deploying, verify the stack:
# Check all containers are running
ssh user@<target> "docker ps"
# Check TypeDB health
ssh user@<target> "docker ps --filter name=alhazen-typedb --format '{{.Status}}'"
# Access dashboard
# Mac Mini: http://<ip>:3001
# VPS with Tailscale: https://<tailscale-hostname>
Updating a Deployment
To push skill or code updates to a deployed instance:
# Re-deploy (pulls latest code, rebuilds containers)
make deploy-macmini # or deploy-vps
The deployment script is idempotent — safe to re-run.