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.
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.
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.
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.
What do you need to run Clawdbot with Docker and Ollama?
Note: OpenClaw requires a 64k context window, which roughly doubles memory use compared to a 4k default.
|
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.
Get dedicated resources and KVM isolation for experiments worldwide.
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
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"
{
"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:
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.
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
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 |
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.
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.
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 you@your-domain.com --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
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:
docker compose up -d
docker compose exec clawdbot wget -qO- http://ollama:11434/api/tags
ss -ltnp | grep -E '8080|11434|80|443'
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.