Clawdbot combined with Docker and Ollama is a self-hosted AI agent stack that runs local language models on your own VPS without touching the OpenAI API. OpenClaw handles agent logic, Docker keeps everything isolated, and Ollama runs inference locally.
Why Docker + Ollama for Clawdbot?
What Docker Adds
Pinned dependencies, reproducible behavior, and two-second restarts. OpenClaw had a command-injection advisory in 2026 (GHSA-mc68-q9jw-2h3v), so pin versions; don't use latest.
What Ollama Adds
Ollama runs LLaMA, Mistral, Qwen, and Phi locally. It exposes a native /api/chat endpoint (required for tool calling) and an OpenAI-compatible /v1. Use /api/chat.
Clawdbot + OpenAI API vs. Clawdbot + Ollama
Self-hosting trades metered API bills for flat hardware costs. Data stays on your server, which matters if you're working under GDPR or HIPAA. The tradeoff: local models aren't GPT-4, but qwen2.5-coder:32b or gpt-oss:20b handle most agent loops just fine.
Server Requirements
What do you need to run Clawdbot with Docker and Ollama?
- Memory: 16 GB RAM minimum for 8B models
- OS: Ubuntu 22.04 LTS or Debian 12
- Software: Docker Engine 24+ and Docker Compose v2
- Storage: 80 GB free disk
- Network: Domain name for SSL
- Processor: CPU with AVX2 (cat /proc/cpuinfo | grep -m1 avx2)
- GPU (optional): On a 4–6 vCPU CPU-only machine with 16 GB RAM, an 8B Q4 model outputs 2–6 tokens/sec. A GPU card typically gets you 10–20x that, though exact numbers depend on the card.
Note: OpenClaw requires a 64k context window, which roughly doubles memory use compared to a 4k default.
Minimum, Recommended, and Heavy-Load Configurations
|
Tier |
vCPU |
RAM |
Storage |
Model capacity |
is*hosting VPS |
|
Minimum |
4 |
16 GB |
80 GB SSD |
7B Q4, short context |
|
|
Recommended |
6 |
24–32 GB |
120 GB NVMe |
8B–14B Q4 at 64k context |
|
|
Heavy (CPU) |
8 |
64 GB |
200 GB NVMe |
32B Q4 or 70B Q4 with offload |
VPS Exclusive + RAM and drive upgrade |
|
GPU |
8 vCPU + 24 GB VRAM |
32 GB |
200 GB NVMe |
14B–32B at full speed |
is*hosting GPU server |
|
Heavy GPU |
8 vCPU + 48 GB VRAM |
64 GB |
400 GB NVMe |
70B Q4 (~40 GB VRAM for weights) |
GPU server (top tier) |
70B Q4 needs ~40 GB VRAM for weights alone. A 16 GB card will OOM.
VPS in 5-15 minutes
Get dedicated resources and KVM isolation for experiments worldwide.
Step 1: Setting Up Docker and the Clawdbot Container
Installing Docker on Ubuntu 22.04
Don't use apt install docker.io; use the official repo:
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker
docker-compose.yml: Base Config
OpenClaw ignores LLM_PROVIDER. Config lives in ~/.openclaw/openclaw.json.
services:
clawdbot:
image: openclaw/openclaw:0.17
container_name: clawdbot
restart: unless-stopped
environment:
OLLAMA_API_KEY: "ollama-local"
volumes:
- ./data:/home/openclaw/.openclaw
- ./openclaw.json:/home/openclaw/.openclaw/openclaw.json:ro
- ./logs:/home/openclaw/.openclaw/logs
ports:
- "127.0.0.1:8080:8080"
Create openclaw.json
{
"agents": {
"defaults": { "model": { "primary": "ollama/llama3.1:8b" } }
},
"models": {
"providers": {
"ollama": {
"baseUrl": "http://ollama:11434",
"apiKey": "ollama-local",
"api": "ollama",
"models": [
{
"id": "llama3.1:8b",
"name": "LLaMA 3.1 8B",
"contextWindow": 65536,
"maxTokens": 8192,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}
]
}
}
}
}
Two mistakes that kill the setup immediately:
- Binding to 0.0.0.0. Using ports: - "8080:8080" exposes the agent port directly and bypasses UFW via Docker iptables. Always bind to 127.0.0.1:8080:8080.
- Skipping restart policy. Without restart: unless-stopped, crashed containers stay down until you notice.
Step 2: Installing Ollama and Choosing Your Model
Note: This systemd setup only covers the host-Ollama option. If you are going straight to the Full Stack docker-compose.yml in Step 4, skip this step; Ollama runs as a container there.
Installing Ollama as a Systemd Service
curl -fsSL https://ollama.com/install.sh | sh
sudo systemctl edit ollama
Add the following environment variables:
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_NUM_PARALLEL=2"
Environment="OLLAMA_KEEP_ALIVE=30m"
Restart and pull your desired model:
sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama pull llama3.1:8b
LLaMA 3.1 vs. Mistral vs. Qwen2.5: Which Fits Your RAM?
OpenClaw requires tool-capable models. Check support before committing:
ollama show qwen2.5-coder:7b --modelfile | grep -i tool
|
Model |
File size (Q4) |
RAM at 64k context |
Notes |
|
Mistral 7B |
4.1 GB |
~10 GB |
Weaker tool calling |
|
LLaMA 3.1 8B |
4.7 GB |
~12 GB |
Strong tool calling |
|
Qwen2.5-Coder 7B |
4.4 GB |
~11 GB |
OpenClaw's pick for coding |
|
gpt-oss 20B |
12 GB |
~20 GB |
OpenClaw's recommended default |
Step 3: Connecting Clawdbot to Ollama
Config Details
Use "api": "ollama". The native /api/chat endpoint supports tools and streaming; /v1 does not. Don't put /v1 in baseUrl. Set contextWindow to 65536 explicitly.
Docker Networking: Host vs. Bridge
localhost inside a bridge-network container resolves to the container itself, not the host. http://localhost:11434 will fail.
The fix: run Ollama as a container on the same Compose network and connect via http://ollama:11434.
Step 4: Production Hardening
SSL with Nginx + Certbot
Nginx won't start without certs; Certbot needs port 80 open first. Bootstrap with HTTP, then swap to SSL.
Create nginx/conf.d/clawdbot.conf:
server {
listen 80;
server_name your-domain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://clawdbot:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 300s;
}
}
Start Nginx, then issue certs:
sudo apt install -y certbot
sudo mkdir -p /var/www/certbot
sudo certbot certonly --webroot -w /var/www/certbot -d your-domain.com --agree-tos -m [email protected] --non-interactive
Note: /var/www/certbot on the host is mounted into the Nginx container via the volume declared in docker-compose.yml. Start Nginx with the HTTP-only config first, then run certbot, then swap to the SSL config and reload.
Swap to the SSL config:
server {
listen 80;
server_name your-domain.com;
location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://clawdbot:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 300s;
}
}
Reload Nginx:
docker compose exec nginx nginx -s reload
Auth, Backups, and Firewall
- Auth: Add Nginx basic auth or an IP allowlist.
- Backups: tar the ./data, openclaw.json, and nginx/conf.d directories. Store off-box.
- Memory limits: Add them in Compose to prevent OOM kills.
- Firewall: Docker-mapped ports bypass UFW. Keep Ollama on the internal Compose network only; don't expose port 11434.
Full Stack docker-compose.yml
services:
clawdbot:
image: openclaw/openclaw:0.17
container_name: clawdbot
restart: unless-stopped
environment:
OLLAMA_API_KEY: "ollama-local"
volumes:
- ./data:/home/openclaw/.openclaw
- ./openclaw.json:/home/openclaw/.openclaw/openclaw.json:ro
- ./logs:/home/openclaw/.openclaw/logs
depends_on:
ollama:
condition: service_healthy
ollama-bootstrap:
condition: service_completed_successfully
networks:
- agentnet
deploy:
resources:
limits:
memory: 2g
ollama:
image: ollama/ollama:0.5.4
container_name: ollama
restart: unless-stopped
environment:
OLLAMA_KEEP_ALIVE: "30m"
OLLAMA_NUM_PARALLEL: "2"
volumes:
- ollama_models:/root/.ollama
healthcheck:
test: ["CMD-SHELL", "ollama list >/dev/null 2>&1 || exit 1"]
interval: 10s
timeout: 5s
retries: 12
start_period: 60s
networks:
- agentnet
deploy:
resources:
limits:
memory: 14g
ollama-bootstrap:
image: ollama/ollama:0.5.4
depends_on:
ollama:
condition: service_healthy
entrypoint: ["/bin/sh", "-c"]
command: ["OLLAMA_HOST=http://ollama:11434 ollama pull llama3.1:8b"]
networks:
- agentnet
restart: "no"
nginx:
image: nginx:1.27-alpine
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
- /var/www/certbot:/var/www/certbot:ro
depends_on:
- clawdbot
networks:
- agentnet
networks:
agentnet:
driver: bridge
volumes:
ollama_models:
Start and Verify
docker compose up -d
docker compose exec clawdbot wget -qO- http://ollama:11434/api/tags
ss -ltnp | grep -E '8080|11434|80|443'
Wrapping Up
Rent a 16–32 GB VPS, install Docker, run Ollama and OpenClaw in a shared Compose network, and proxy via Nginx with HTTPS. Use the native /api/chat, and set the context window to 64k or higher.
The recommended setup maps to is*hosting's Elite or Exclusive VPS: enough RAM for an 8B–14B model at full 64k context. For 32B+ models, jump to Exclusive with RAM upgrade or move to a GPU server.