OpenClaw LXC Build And llama.cpp Integration

Create the OpenClaw container on Proxmox, install Node.js and OpenClaw, and register the existing llama.cpp Router Mode endpoint as the assistant's local model backend.

Published January 23, 2025 ยท Updated January 31, 2025

OpenClaw LXC Build And llama.cpp Integration

This page gets the assistant online inside the homelab.

By the end, CT 106 exists, OpenClaw is installed, the workspace exists, and the gateway can talk to the existing llama.cpp Router Mode endpoint without adding new GPU passthrough or a second inference stack.

If Router Mode is not in place yet, start with llama.cpp Router Mode On Proxmox first. If Router Mode is not in place yet, start with llama.cpp Router Mode On Proxmox first.

Create The LXC Container

Container Sizing

SettingValueRationale
Container ID106next available service container
Hostnameopenclawdescriptive role
Disk Size10 GBruntime, workspace, logs
CPU Cores2enough for the gateway and tool handling
RAM2048 MiBNode.js plus assistant workspace
Swap512 MiBsafety net
OSDebian 13modern stable base
Bridgevmbr0same LAN as the rest of the stack
IPv4192.168.50.85/24stable internal target
Gateway192.168.50.1router
UnprivilegedYescleaner security boundary
NestingEnabledneeded for the service model used here
Start on bootYesassistant should survive host reboots

Create Via CLI

Run on the Proxmox host:

# Download Debian 13 template if not present
pveam update
pveam available | grep debian-13
pveam download local debian-13-standard_13.1-2_amd64.tar.zst
 
# Create the container
# Replace local-zfs with your storage backend (check: pvesm status)
pct create 106 local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \
  --hostname openclaw \
  --memory 2048 \
  --swap 512 \
  --cores 2 \
  --rootfs local-zfs:10 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.50.85/24,gw=192.168.50.1 \
  --unprivileged 1 \
  --features nesting=1 \
  --onboot 1 \
  --password 'your-secure-password'
 
# Start the container
pct start 106
 
# Verify it's running
pct status 106
# Expected: status: running

Verify Network Connectivity

# Enter the container
pct enter 106
 
# Verify network
ping -c 3 192.168.50.1
ping -c 3 192.168.50.45
ping -c 3 1.1.1.1
 
# Verify llama.cpp is reachable
apt update && apt install -y curl
curl -s http://192.168.50.45:8012/v1/models | head -20
# Should return JSON with your registered models

Install Node.js And OpenClaw

All commands in this section run inside CT 106.

Install System Dependencies

apt update && apt upgrade -y
apt install -y curl git ca-certificates gnupg

Install Node.js 22

# Add NodeSource repository (Node.js 22.x)
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
 
# Install Node.js
apt install -y nodejs
 
# Verify
node --version
npm --version

Enable Corepack And Install pnpm

corepack enable
corepack prepare pnpm@latest --activate
 
# Verify
pnpm --version

Set Up pnpm Global Bin Directory

pnpm setup
source /root/.bashrc
 
echo $PNPM_HOME

Install OpenClaw

pnpm install -g openclaw@latest
 
# Verify installation
openclaw --version

Approve Native Build Scripts

# Show packages that need build approval and select which to allow
pnpm approve-builds -g

Approve at minimum sharp, koffi, and protobufjs.

Run The Onboarding Wizard

openclaw onboard --install-daemon

Choose the custom OpenAI-compatible provider path during onboarding and point it at:

  • base URL: http://192.168.50.45:8012/v1
  • API key: the same key used by llama-server
  • default model: model:qwen3-8b or the preferred primary model in Router Mode

If the wizard fails or is interrupted, continue with the manual path below.

Manual OpenClaw Configuration

If the onboarding wizard does not complete, create the OpenClaw home manually:

mkdir -p ~/.openclaw/workspace

Create a minimal config file using the newer configuration surface where messaging tokens come from environment variables instead of JSON keys:

cat > ~/.openclaw/openclaw.json << 'OCEOF'
{
  agents: {
    defaults: {
      model: { primary: "llamacpp/model:qwen3-8b" },
      workspace: "~/.openclaw/workspace",
      models: {
        "llamacpp/model:qwen3-8b":             { alias: "Qwen3-8B" },
        "llamacpp/model:glm-4-9b":             { alias: "GLM-4-9B" },
        "llamacpp/model:deepseek-r1-qwen3-8b": { alias: "DeepSeek-R1" },
        "llamacpp/model:gpt-oss-20b":          { alias: "GPT-OSS-20B" },
      },
    },
  },
 
  channels: {
    telegram: {
      enabled: true,
      dmPolicy: "pairing",
      groupPolicy: "open",
      streaming: "off",
    },
    discord: {
      enabled: true,
      dmPolicy: "pairing",
      groupPolicy: "open",
      streaming: "off",
    },
  },
 
  gateway: {
    mode: "local",
    port: 18789,
    bind: "lan",
    controlUi: {
      dangerouslyAllowHostHeaderOriginFallback: true,
    },
  },
}
OCEOF

Verify the structure:

ls -la ~/.openclaw/
cat ~/.openclaw/openclaw.json
openclaw doctor

Create Workspace Memory Directory

mkdir -p ~/.openclaw/workspace/memory
touch ~/.openclaw/workspace/MEMORY.md
touch ~/.openclaw/workspace/memory/$(date +%Y-%m-%d).md

Connect OpenClaw To llama.cpp Router Mode

Verify llama.cpp Is Healthy

# From inside CT 106
curl -s http://192.168.50.45:8012/v1/models | python3 -m json.tool
 
curl -s http://192.168.50.45:8012/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-secret-key" \
  -d '{
    "model": "model:glm-4-9b",
    "messages": [{"role": "user", "content": "Say hello in one sentence."}],
    "max_tokens": 50
  }' | python3 -m json.tool

Register The Custom Provider

Edit the config file:

nano ~/.openclaw/openclaw.json

Use the full model-provider block below:

{
  agents: {
    defaults: {
      model: { primary: "llamacpp/model:qwen3-8b" },
      workspace: "~/.openclaw/workspace",
      models: {
        "llamacpp/model:qwen3-8b":             { alias: "Qwen3-8B" },
        "llamacpp/model:glm-4-9b":             { alias: "GLM-4-9B" },
        "llamacpp/model:deepseek-r1-qwen3-8b": { alias: "DeepSeek-R1" },
        "llamacpp/model:gpt-oss-20b":          { alias: "GPT-OSS-20B" },
      },
    },
  },
 
  models: {
    mode: "merge",
    providers: {
      llamacpp: {
        baseUrl: "http://192.168.50.45:8012/v1",
        apiKey: "your-secret-key",
        api: "openai-completions",
        models: [
          {
            id: "model:glm-4-9b",
            name: "GLM-4-9B",
            reasoning: false,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 131072,
            maxTokens: 16384,
          },
          {
            id: "model:qwen3-8b",
            name: "Qwen3-8B",
            reasoning: false,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 131072,
            maxTokens: 16384,
          },
          {
            id: "model:deepseek-r1-qwen3-8b",
            name: "DeepSeek-R1-Qwen3-8B",
            reasoning: true,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 131072,
            maxTokens: 16384,
          },
          {
            id: "model:gpt-oss-20b",
            name: "GPT-OSS-20B",
            reasoning: true,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 131072,
            maxTokens: 16384,
          },
        ],
      },
    },
  },
 
  gateway: {
    mode: "local",
    port: 18789,
    bind: "lan",
    controlUi: {
      dangerouslyAllowHostHeaderOriginFallback: true,
    },
  },
}

Why Qwen3-8B As Primary

ModelBest ForTradeoff
Qwen3-8Bfast general assistant behavior and low-friction tool useless headroom for heavier reasoning
GLM-4-9Bstrong instruction followingcan over-trigger tool calls as a primary assistant
GPT-OSS-20Bheavier reasoning and longer chainsslower and more expensive in VRAM
DeepSeek-R1-Qwen3-8Bdeliberate reasoning tasksless ideal for everyday assistant flow

Qwen3-8B is the best default when the assistant needs to answer quickly in Telegram or Discord instead of treating every message like a research project.

Verify Model Registration

openclaw models status
openclaw models list
openclaw agent --agent main --message "What time is it?"

If openclaw models status reports missing auth for llamacpp, verify:

  • the apiKey matches the llama-server service
  • curl http://192.168.50.45:8012/v1/models works from CT 106
  • the baseUrl uses http:// rather than https://

Continue with OpenClaw Channels, Daemon, And Secure Exposure once the assistant can talk to the local inference stack.

Comments

Sign in with GitHub to leave a comment or reaction.