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):

  • ansible and ansible-playbook
  • openssl and ssh-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

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-serve exposes 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.