Self-host OpenClaw with HTTPS, Brave search, and GitHub access
Run the OpenClaw agent gateway on your Ollama VM behind an nginx TLS reverse proxy. Wire up the Brave search skill, give it authenticated GitHub access for code tasks, and configure a CLAUDE.md so remote Claude Code sessions have persistent context.
- Step 1
Prerequisites
This guide assumes you've already finished Ollama on a dedicated NVMe with performance tuning. That guide covers the underlying setup this one builds on. If you're picking up mid-stack, scan its 'Overview' step to confirm your environment matches.
- Step 2
What is OpenClaw
OpenClaw is a personal AI assistant gateway that connects AI agents running on your own hardware to a web dashboard and external channels. In this setup it manages local model agents on the Ollama inference VM, accessible via the VPN dashboard and Multica board — no cloud inference, no API costs, no data leaving your network. The WhatsApp plugin and channel are disabled. The flow: Multica board or VPN dashboard → OpenClaw gateway (Ollama VM, port 18789) → Ollama inference (RTX 3090) → response.
- Step 3
Prerequisites
- Node.js 22+ installed on the Ollama VM
- Ollama running with models loaded
- WhatsApp account ready to link (dedicated number recommended for long-term use)
- Step 4
Install Node.js
Node.js is not installed by default on Ubuntu. Install it via NodeSource:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt-get install -y nodejs node --version npm --version - Step 5
Install OpenClaw
OpenClaw is installed via Ollama's launch command, which handles npm installation automatically: Note: The ollama launch command prompts interactively — work through the onboarding steps and select qwen3-coder:30b as the model. This is the most tool-calling-reliable model in the stack.
# If npm permissions error occurs, install directly: sudo npm install -g openclaw # Then launch via Ollama ollama launch openclaw # Select qwen3-coder:30b as the primary model when prompted - Step 6
Configure Ollama Provider
OpenClaw must connect to Ollama using localhost, not the VM's network IP. Using the network IP causes ECONNREFUSED errors. Note: Do not use the /v1 OpenAI-compatible URL (http://host:11434/v1) — this breaks tool calling. Use the native Ollama API URL with no path suffix.
# Critical: use 127.0.0.1, NOT 192.168.20.110 openclaw config set models.providers.ollama.baseUrl "http://127.0.0.1:11434" openclaw config set models.providers.ollama.apiKey "ollama-local" openclaw config set models.providers.ollama.api "ollama" # Set primary model and fallback openclaw config set agents.defaults.model.primary "ollama/qwen3-coder:30b" openclaw config set agents.defaults.model.fallbacks '["ollama/qwen3.5:27b"]' # Verify openclaw config get models.providers.ollama.baseUrl openclaw config get agents.defaults.model.primary - Step 7
Update Models to 64K Context
OpenClaw recommends a minimum 64K context window for local models. Recreate each model with 65536 context baked in:
for MODEL in qwen3-coder:30b deepseek-r1:32b dolphin3 qwen2.5-abliterate:32b; do cat > /tmp/modelfile << EOF FROM $MODEL PARAMETER num_ctx 65536 EOF ollama create ${MODEL}-64k -f /tmp/modelfile ollama rm $MODEL ollama create $MODEL -f /tmp/modelfile ollama rm ${MODEL}-64k done # Verify ollama show qwen3-coder:30b | grep num_ctx # should show 65536 - Step 8
OpenClaw Agents
Six named agents are configured in /home/ollama/.openclaw/openclaw.json, each with a dedicated model, tools profile, and thinking mode: Agent Model Tools profile Thinking main qwen3-coder:30b coding adaptive general qwen3.5:27b full adaptive researcher deepseek-r1:32b minimal high analyst huihui_ai/qwen3.5-abliterated:27b minimal adaptive creative dolphin3 minimal off qwen3-coder:30b browser/web off Fallback chain: qwen3-coder:30b → qwen3.5:27b (local only — Claude accessed via dedicated Multica agent) Context windows are set per model in the model registry. huihui_ai/qwen3.5-abliterated:27b has reasoning: true.
browser - Step 9
Agent Orchestration via AGENTS.md
By default the main agent handles all requests itself with qwen3-coder:30b. The allowAgents: ["*"] config permits spawning sub-agents, but automatic delegation only happens when the agent is given explicit instructions.
- Step 10
How OpenClaw Identity Files Work
OpenClaw maintains several identity files per agent. Understanding which does what matters:
- BOOTSTRAP.md — read once on first run of a new workspace, then deleted. Not suitable for persistent instructions.
- AGENTS.md — read at the start of every session. This is the correct place for persistent orchestration rules. Note: BOOTSTRAP.md is a one-time bootstrap file. If an agent workspace already exists, BOOTSTRAP.md is ignored. Persistent instructions must go in AGENTS.md inside the workspace directory.
- Step 11
Configuring Orchestration via AGENTS.md
The persistent workspace files live in /home/ollama/.openclaw/workspace/. Add orchestration rules by appending to the main agent's AGENTS.md: Recommended orchestration section to add: No restart is needed — the rules are loaded at the start of every new session. Start a fresh session with /new in OpenClaw to pick them up immediately.
nano /home/ollama/.openclaw/workspace/main/AGENTS.md # Agent Orchestration ## Delegation rules - Deep reasoning / multi-step logic → delegate to: researcher (deepseek-r1:32b) - General analysis / synthesis / writing → delegate to: general (qwen3.5:27b) - Creative writing / mature themes → delegate to: creative (dolphin3) - Sensitive / unfiltered tasks → delegate to: analyst (qwen3.5-abliterated:27b) - Coding, tool use, short tasks → handle directly (qwen3-coder:30b) - Browser automation, web interaction, Brave-specific tasks → delegate to: browser (qwen3-coder:30b + Brave skill) ## Mixed requests For prompts spanning multiple domains: 1. Decompose into sub-tasks 2. Assign each sub-task to the appropriate agent 3. Synthesise results into a single response - Step 12
What This Sets Up
- Main agent (qwen3-coder:30b) handles coding and tool-use tasks directly
- Delegates deep reasoning → researcher (deepseek-r1:32b)
- Delegates broad analysis / synthesis → general (qwen3.5:27b)
- Delegates creative work → creative (dolphin3)
- Delegates sensitive / unfiltered tasks → analyst (qwen3.5-abliterated:27b)
- Delegates browser / web / Brave tasks → browser (qwen3-coder:30b + Brave skill scoped to this agent only)
- For mixed requests (e.g. "research X then write code for it"), decomposes and assigns each part to the right agent, then synthesises To verify it is working, start a fresh session and give it a mixed request such as "research the tradeoffs between X and Y, then write a script to benchmark them." The agent should explicitly name which sub-tasks it is delegating and to which agent. Note: Delegation quality depends on how well qwen3-coder:30b follows the instructions. If it is not delegating when it should, either make the delegation rules more explicit in AGENTS.md, or switch the main agent to qwen3.5:27b which is a stronger general reasoner.
- Step 13
Multica Agent Roster in AGENTS.md
OpenClaw is the default Multica agent for task orchestration. When assigned an issue to break down and create sub-issues, it uses the Multica Agent Roster in AGENTS.md to assign each issue to the right agent automatically — without needing routing rules in every issue brief. The following section is appended to ~/.openclaw/workspace/main/AGENTS.md: With this in place, when OpenClaw handles a task like "create issues and assign to agents", it will:
- Break the work down into discrete issues
- Use the roster to match each issue to the appropriate agent
- Create and assign them via the multica CLI Note: This only works reliably if AGENTS.md is loaded for the task session. Multica spawns agent tasks with their own context, so it is worth testing with a real task to confirm the roster is in scope before relying on it for critical work.
## Multica Agent Roster When creating and assigning Multica issues, use these routing rules: - OpenClaw → coding, tool use, implementation - Hermes (Ollama VM) → research, reasoning, planning, long-context - Claude (Ollama VM) → tasks exceeding local model capability Use the multica CLI to create and assign issues: multica issue create --title "<title>" --assignee <agent-id> For mixed task sets, decompose first, then assign each issue to the appropriate agent based on the rules above. - Step 14
Scope skills and models to avoid context bloat
Two settings to apply from the start so OpenClaw's system prompts stay within model context windows.
Scope the Brave skill to the browser sub-agent only. The Brave skill adds ~19 KB to every session's system prompt. Installing it scoped to the browser sub-agent keeps it invisible to the main agent — the skill ends up at
~/.openclaw/agents/browser/workspace/skills/brave/rather than~/.openclaw/workspace/skills/brave/.Use a 64K-context model for Multica-dispatched sessions. Multica injects ~11.2 KB of CLI documentation into every OpenClaw session's system prompt. Combined with workspace files and tool schemas this can exceed the 32K context of
qwen3-coder:30b. Set the Multica agent's default model toollama/qwen3.5:27b(64K context) via the Multica UI (Settings → Agents → OpenClaw agent → model field).# Install Brave scoped to the browser sub-agent only openclaw skills install brave --agent browser - Step 15
Install Gateway as a Service
Use OpenClaw's built-in service installer rather than a manual systemd unit — it uses the correct binary path and flags automatically:
- Browser agent workspace: ~/.openclaw/agents/browser/workspace/
- Brave skill (browser agent only): ~/.openclaw/agents/browser/workspace/skills/brave/
- OpenClaw gateway service (Brave API key): /home/ollama/.config/systemd/user/openclaw-gateway.service
- Multica server config: /home/ollama/.multica/server/.env
- Hermes config: ~/.hermes/config.yaml
- Hermes environment: ~/.hermes/.env
- Git credentials (PAT): ~/.git-credentials (chmod 600)
- Multica Docker Compose: docker-compose.selfhost.yml
- Multica systemd service: /etc/systemd/system/multica.service
- Multica daemon service: ~/.config/systemd/user/multica-daemon.service Note: OpenClaw installs as a user systemd service (openclaw-gateway.service), not a system service. Do not create a manual /etc/systemd/system/openclaw.service — the --foreground flag used in manual service files is not valid in this version of OpenClaw.
# Install and start the gateway service openclaw gateway install openclaw gateway start openclaw gateway status # Enable linger so the user service starts at boot without login sudo loginctl enable-linger ollama # Verify service is enabled systemctl --user is-enabled openclaw-gateway.service - Step 16
Install WhatsApp Plugin and Link Account
Have your phone ready before running the configure command — the QR code expires in approximately 20 seconds:
# Install WhatsApp channel plugin openclaw plugins install @openclaw/channel-whatsapp # Begin channel configuration openclaw configure --section channels # Select WhatsApp when prompted # On your phone: # WhatsApp -> Settings -> Linked Devices -> Link a Device -> scan QR code - Step 17
Configure Allowlist (Important)
By default OpenClaw responds to ALL incoming WhatsApp messages. Configure an allowlist immediately after linking to prevent it responding to messages from other people:
# Replace with your number in international format (no + prefix) openclaw config set channels.whatsapp.allowFrom '["<yournumber>@s.whatsapp.net"]' openclaw gateway restart # Verify openclaw channels status # Should show: dm:allowlist, allow:<yournumber>@s.whatsapp.net - Step 18
Dedicated Number Recommendation
Using a personal WhatsApp number means OpenClaw acts as a linked device on your main account. A dedicated number (Google Voice, second SIM, WhatsApp Business) gives cleaner separation and is recommended for long-term use. Switching is straightforward:
# Unlink current number openclaw channels logout --channel whatsapp # Re-link with new number openclaw configure --section channels # Scan QR from new WhatsApp account - Step 19
VM RAM Requirement
qwen3-coder:30b requires approximately 19GB of system RAM to load. The VM must have at least 24GB allocated:
# On Proxmox host — increase VM RAM if needed qm shutdown 100 qm set 100 --memory 24576 qm start 100 - Step 20
Gateway Management
Common gateway lifecycle commands: status, logs, restart, and channel reconfiguration. Use these for routine operations and when troubleshooting.
# Status openclaw gateway status openclaw channels status # Logs openclaw logs --follow journalctl --user -u openclaw-gateway.service -n 50 --no-pager # Stop / start / restart openclaw gateway stop openclaw gateway start openclaw gateway restart # Reconfigure channels openclaw configure --section channels # Check gateway health openclaw gateway health - Step 21
Dashboard Access
The OpenClaw gateway dashboard runs on port 18789 but binds to localhost only. Access it remotely via SSH tunnel from your laptop: The gateway token is required for authentication. Generate and set it once: Note: Store the gateway token in a password manager. It is required every time you access the dashboard via SSH tunnel. The token is stored in /home/ollama/.openclaw/openclaw.json under gateway.auth.token — do not store the actual value in CLAUDE.md.
# Open SSH tunnel (run on your laptop, keep terminal open) ssh -N -L 18789:127.0.0.1:18789 ollama@192.168.20.110 # Then open in browser: http://localhost:18789/#token=<your-gateway-token> # Generate a strong token openssl rand -hex 32 # Set it in OpenClaw config openclaw config set gateway.auth.token "paste-token-here" openclaw gateway restart # Get the dashboard URL (shows token-auth URL format) openclaw dashboard - Step 22
Anthropic API Key (Optional)
Adding an Anthropic API key gives OpenClaw access to Claude models as a fallback when local models fail or a task genuinely needs frontier reasoning. Local models remain the primary route — Claude is only called when both local models fail. Before adding the key, set a spend limit at console.anthropic.com. OpenClaw is an agent and consumes significantly more tokens than regular chat — each task can trigger 5-10 API calls and carries full conversation context into every request.
- Step 23
Anthropic API Key (Optional) — Add the API Key
Add an Anthropic API key via the interactive configure flow or by setting the config value directly. Restart the gateway for the change to take effect. Set a spend limit at console.anthropic.com first — agents consume far more tokens than chat.
# Interactive setup (recommended) openclaw configure # Select Anthropic when prompted, paste API key # Or set directly openclaw config set models.providers.anthropic.apiKey "sk-ant-your-key-here" openclaw gateway restart - Step 24
Anthropic API Key (Optional) — Configure Routing — Local First
After adding the key, restore the correct routing so local models remain primary and Claude is only a last resort: Note: Routing priority: qwen3-coder:30b (local, default) → qwen3.5:27b (local fallback). Claude is accessed explicitly via the "Claude (Ollama VM)" Multica agent for tasks that exceed local model capability — not as a silent API fallback inside OpenClaw.
openclaw config set agents.defaults.model.primary "ollama/qwen3-coder:30b" openclaw config set agents.defaults.model.fallbacks '["ollama/qwen3.5:27b"]' openclaw gateway restart # Verify routing openclaw config get agents.defaults.model.primary openclaw config get agents.defaults.model.fallbacks - Step 25
Troubleshooting — 'Something went wrong' in WhatsApp
Almost always caused by OpenClaw connecting to the wrong Ollama URL. Verify:
openclaw config get models.providers.ollama.baseUrl # Must be http://127.0.0.1:11434 — not 192.168.20.110:11434 # Fix if wrong: openclaw config set models.providers.ollama.baseUrl "http://127.0.0.1:11434" openclaw gateway restart - Step 26
Troubleshooting — Gateway not starting after reboot
Gateway not starting after reboot.
# Confirm linger is enabled loginctl show-user ollama | grep Linger # Should show: Linger=yes # If not: sudo loginctl enable-linger ollama - Step 27
Troubleshooting — QR code expired during WhatsApp link
Run the configure command again — OpenClaw generates a fresh QR code each time:
openclaw configure --section channels - Step 28
VPN → OpenClaw Remote Access
The OpenClaw dashboard (port 18789) is exposed securely over the WireGuard VPN via nginx with TLS, so it can be reached from any connected device without an SSH tunnel.
- Step 29
nginx Reverse Proxy with TLS
nginx is installed on the Ollama VM and configured to proxy HTTPS (443) → 127.0.0.1:18789 with WebSocket support, and redirect HTTP (80) → HTTPS. Self-signed certificate (10-year, SAN: 192.168.20.110): Note: Accept the browser cert warning once per device. After that the connection is encrypted. For LAN-only VPN access a self-signed cert is sufficient — no CA required.
openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/openclaw.key \ -out /etc/ssl/certs/openclaw.crt -days 3650 -nodes \ -subj "/CN=192.168.20.110" \ -addext "subjectAltName=IP:192.168.20.110" - Step 30
OpenClaw Config Updates
Two settings updated in openclaw.json to support the nginx proxy:
openclaw config set gateway.trustedProxies '["127.0.0.1"]' openclaw config set gateway.controlUi.allowedOrigins '["https://192.168.20.110"]' openclaw gateway restart - Step 31
Unifi Firewall Rule
A zone-based rule in the Unifi Dream Router allows VPN clients to reach the dashboard:
- Source zone: VPN (10.99.99.0/24)
- Destination: 192.168.20.110, port 443
- Action: Allow + auto return traffic
- Step 32
Dashboard Access
From any WireGuard-connected device, open: Accept the self-signed cert warning on first visit (one-time per device).
https://192.168.20.110 - Step 33
Device Pairing Workflow
For each new device that needs access:
- Visit https://192.168.20.110 and accept the self-signed cert warning
- On the VM: openclaw devices list
- Approve the pending request: openclaw devices approve <requestId>
- Step 34
Brave Web Search Plugin
The Brave search plugin gives OpenClaw agents the ability to search the web during a session. It is installed as an OpenClaw skill and enabled via configuration.
- Step 35
Installation
Install the Brave search skill into OpenClaw via the built-in skill installer.
openclaw skills install brave - Step 36
Configuration
Two settings to update in openclaw.json: Add the API key to the OpenClaw gateway service environment file: Note: Get a Brave Search API key at api.search.brave.com. The free tier allows 2,000 queries/month which is sufficient for casual homelab use.
openclaw config set plugins.entries.brave.enabled true openclaw config set tools.web.search.provider brave # /home/ollama/.config/systemd/user/openclaw-gateway.service [Service] Environment="BRAVE_API_KEY=<your_key>" systemctl --user daemon-reload && systemctl --user restart openclaw-gateway - Step 37
Troubleshooting: Missing Dependencies
After initial installation the OpenClaw UI may report that the Brave skill has missing dependencies. This is resolved by installing Brave Browser itself on the VM (OpenClaw uses it as a headless dependency) and creating the required config directory. Install Brave Browser (run as root via Proxmox guest exec or with sudo): Create the required config directory and reinstall the plugin: Verify the gateway is healthy after restart: Note: The ollama user is in the sudo group but requires a password interactively. For headless dependency installs, use Proxmox qm guest exec to run commands as root on VM 100.
curl -fsS https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ | gpg --dearmor -o /usr/share/keyrings/brave-browser-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] \ https://brave-browser-apt-release.s3.brave.com/ stable main" \ > /etc/apt/sources.list.d/brave-browser-release.list apt update && apt install -y brave-browser mkdir -p ~/brave openclaw skills install brave systemctl --user status openclaw-gateway - Step 38
GitHub Integration
OpenClaw needs authenticated git access to clone, commit, and push to your private repo when Multica assigns tasks. Configure credentials on the VM using a Personal Access Token (PAT) with repo scope.
- Step 39
Configure Git on the VM
Set the global git identity and store credentials in
~/.git-credentialswith 600 permissions. The PAT-bearing URL pattern is whatcredential.helper storeexpects. Replace the username and PAT placeholders with your actual values.git config --global user.name "Your Name" git config --global user.email "your@email.com" git config --global credential.helper store echo "https://<username>:<PAT>@github.com" > ~/.git-credentials chmod 600 ~/.git-credentials - Step 40
Verify Access
The credentials file must exist at ~/.git-credentials — if the clone fails, confirm the file is present and contains the correct PAT. The test cloning a repo verifies authentication end-to-end even if you do not have a specific target repo URL yet. Note: Credentials are stored in plaintext in ~/.git-credentials. Ensure the file has 600 permissions (chmod 600 ~/.git-credentials). Use a PAT scoped to repo only — do not use your GitHub password.
git clone https://github.com/<username>/<repo> /tmp/test-clone && rm -rf /tmp/test-clone && echo "success" - Step 41
OpenClaw Workspace Permissions
Once git is authenticated, OpenClaw can clone, commit, and push to your private repo when Multica assigns tasks. The ollama user under which OpenClaw runs inherits the git config and credentials. Your collaborator should perform the same git setup on their MacBook with their own credentials, and you should add them as a collaborator on the repo in GitHub Settings → Collaborators if you have not already.
- Step 42
Purpose
Claude Code reads CLAUDE.md automatically at the start of every session. Placing one in the claude-code home directory gives Claude persistent context about the homelab without requiring re-explanation each time.
- Step 43
Create the File
Create
CLAUDE.mdin the claude-code home directory and chown it to the user so Claude Code can read it on session start.nano /home/claude-code/CLAUDE.md chown claude-code:claude-code /home/claude-code/CLAUDE.md - Step 44
Recommended Contents
A starter template for
CLAUDE.md. Adjust IPs, hardware specs, model list, and the routing guidance to match your build. Claude Code reads this file at the start of every session, giving it persistent context about the homelab without re-explanation.# Homelab AI — Claude Code context ## Overview Self-hosted AI workstation running Proxmox VE 9.x with GPU passthrough to an Ollama inference VM. Claude handles planning and reasoning via the API; bulk/private tasks route to local models via Ollama. ## Proxmox host - Hostname: pve.homelab.local - IP: 192.168.20.6 - OS: Proxmox VE 9.1 (Debian Trixie) - CPU: Intel i7-8700K (6c/12t) - RAM: 32GB DDR4 - User for Claude Code: claude-code (scoped sudo) ## Storage layout | Mount | Device | Purpose | |---------------|-------------|--------------------------------| | / (pve-root) | nvme0n1 | Proxmox OS + VM pool | | /mnt/backups | sda1 | Daily VM backups (backup-hdd) | | /mnt/models | nvme1n1p1 | Ollama model weights | ## VM: ollama (ID 100) - IP: 192.168.20.110 - OS: Ubuntu 24.04.4 LTS - GPU: RTX 3090 24GB (vfio passthrough) - NVIDIA: 595.58.03, CUDA 13.2 - Ollama: systemd service, models at /mnt/models/ollama - SSH alias from Proxmox host: ssh ollama-vm ## Ollama models - llama3.2:1b — sanity check / GPU test, Q8_0, 32K ctx - qwen3-coder:30b — default / coding / tool calls, MoE, ~147 tok/s, 32K ctx - qwen3.5:27b — general reasoning, thinking adaptive, 64K ctx - deepseek-r1:32b — deep reasoning, avoid tool-use, capped 12K ctx - dolphin3 — uncensored / fast, ~149 tok/s, 32K ctx - huihui_ai/qwen3.5-abliterated:27b — uncensored reasoning, 64K ctx ## Model routing guidance - Default local route: qwen3-coder:30b (best tool calling, coding, MCP) - General reasoning: qwen3.5:27b (adaptive thinking, 64K ctx) - Deep reasoning: deepseek-r1:32b (avoid tool-use tasks, capped 12K ctx) - Uncensored general: dolphin3 - Uncensored reasoning: huihui_ai/qwen3.5-abliterated:27b - Quick tests: llama3.2:1b - Leave 2-3GB VRAM headroom — do not load multiple large models simultaneously - Route to uncensored models only for legitimate tasks blocked by content filters, mature creative writing, or security research ## Key commands qm start 100 / qm shutdown 100 / qm status 100 qm snapshot 100 <name> --description '...' # VM must be stopped ssh ollama@192.168.20.110 ollama list / ollama pull <model> / ollama run <model> ## Important notes - Snapshots require VM shutdown (PCI passthrough limitation) - GPU blacklisted on host: /etc/modprobe.d/blacklist-gpu.conf - Proxmox apt repos: no-subscription (enterprise repos disabled) - Step 45
Next: continue building the stack
With this layer in place, the next guide in the series is Multi-agent orchestration with Multica, OpenClaw, and Hermes. Run multiple AI runtimes — OpenClaw, Hermes, and Claude Code — on one Ollama VM with serialised local inference controlled by OpenClaw's
agents.defaults.maxConcurrent: 1, an issue-board orchestrator (Multica), and a workflow for inviting collaborators into the same workspace.
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.