#openclaw on different vps servers. issue

1 messages · Page 1 of 1 (latest)

fossil fable
#

Hi, I am trying to get openclaw on vps 1 to talk to ollama/qwen3 on VPS 2. Not wihtout it's trials and tribulations.
firstly I had issues getting openclaw running. it would take so long to start up. both of these servers are remote. the 2nd VPS is a GPU server the first is a normal health vps with plenty of stout.
Getting openclaw up and running takes about 15 mins for the ui to open up. then it can be a little pedantic about its token. but got there . then getting it to talk to the Ollama VPS is the challenging part.
has anyone done this. both are linux machines. The 2nd VPS came with Ollama pre installed. I downloaded the qwen3 model I wanted. I can reach the ollama ui via the ip and port. yet the first VPS runnunig ubuntu 24.04 is just not connecting to it.

marsh solsticeBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

zinc sorrelBOT
#

Yep, this setup is supported. The two big gotchas are:

  1. Use Ollama’s native URL, not /v1
    {
      models: {
        providers: {
          ollama: {
            apiKey: "ollama-local",
            baseUrl: "http://VPS2_IP:11434",
            api: "ollama",
            timeoutSeconds: 300,
            models: [
              { id: "qwen3:YOUR_TAG", name: "qwen3:YOUR_TAG", input: ["text"] }
            ]
          }
    
#
       }
     },
     agents: {
       defaults: {
         model: { primary: "ollama/qwen3:YOUR_TAG" }
       }
     }
   }

Don’t use http://VPS2_IP:11434/v1 unless you’re intentionally forcing OpenAI-compatible mode; OpenClaw’s Ollama docs say native api: "ollama" is the safer path for tools.

  1. Test from VPS 1, not your laptop/browser
    On VPS 1:
    curl http://VPS2_IP:11434/api/tags
    
#
   openclaw models status
   openclaw logs --follow

If curl fails there, it’s networking/firewall/Ollama binding on VPS 2. If curl works but OpenClaw fails, it’s probably config/model ref/auth.

Also: please paste:

openclaw --version
openclaw gateway status --deep
openclaw models status

15 minutes for the UI/gateway to come up is not normal, so logs will matter there too.

Docs:
https://docs.openclaw.ai/providers/ollama

fossil fable
#

this is my current setup {
"gateway": {
"auth": {
"mode": "token",
"token": "594c2cc858182ccc672a426428fd31c4000a64f73ab99300"
},
"bind": "0.0.0.0",
"mode": "local",
"port": 18789,
"trustedProxies": [
"127.0.0.1",
"::1",
"localhost"
],
"controlUi": {
"allowedOrigins": [
"http://127.0.0.1:18789",
"localhost:18789",
"http://208.87.135.84:18789"
],
"dangerouslyAllowHostHeaderOriginFallback": true,
"dangerouslyDisableDeviceAuth": true,
"allowInsecureAuth": true
}
},
"agents": {
"defaults": {
"model": {
"primary": "ollama/auto"
},
"models": {
"ollama/auto": {}
}
}
},
"auth": {
"profiles": {
"ollama:default": {
"provider": "ollama",
"mode": "token"
}
}
},
"plugins": {
"entries": {
"ollama": {
"enabled": true,
"config": {}
},
"bonjour": {
"enabled": false
}
}
}
}

zinc sorrelBOT
#

First thing: you pasted your gateway token publicly — rotate it before doing anything else. 🫣

Main config issue: your OpenClaw config currently has no Ollama endpoint. ollama/auto will default toward local discovery, not your second VPS.

Add a real models.providers.ollama block, using VPS2’s reachable address:

{
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://VPS2_IP:11434",
        "api": "ollama",
        "apiKey": "ollama-local",
        "timeoutSeconds": 300,
        "models": [
#
          {
            "id": "qwen3:YOUR_EXACT_TAG",
            "name": "qwen3:YOUR_EXACT_TAG",
            "input": ["text"],
            "params": {
              "keep_alive": "15m"
            }
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
#
        "primary": "ollama/qwen3:YOUR_EXACT_TAG"
      },
      "models": {
        "ollama/qwen3:YOUR_EXACT_TAG": {}
      }
    }
  }
}

Replace qwen3:YOUR_EXACT_TAG with what VPS2 shows from:

ollama list
#

Then from VPS1, test:

curl http://VPS2_IP:11434/api/tags
openclaw models status
openclaw infer model run --local --model ollama/qwen3:YOUR_EXACT_TAG --prompt "Reply with exactly: pong" --json

One important security/networking note: if VPS2_IP is a public IP, don’t leave Ollama open to the internet. Ideally use Tailscale/WireGuard/private networking or firewall port 11434 so only VPS1 can reach it. If OpenClaw refuses ollama-local against a public IP, use a private/VPN IP or put an auth proxy in front.

Also, dangerouslyDisableDeviceAuth + public 0.0.0.0 gateway is risky. Fine for debugging briefly, but I’d lock that down once the Ollama connection works.

Docs: https://docs.openclaw.ai/providers/ollama

fossil fable
#

qwen3-vl:8b

zinc sorrelBOT
#

That :8080 may be a web UI, not Ollama’s native API. OpenClaw needs the Ollama API base URL where this works:

curl http://173.208.156.207:8080/api/tags

Run that from VPS1.

  • If it returns JSON with a models list → use:
    baseUrl: "http://173.208.156.207:8080"
    
  • If it returns HTML / 404 / login page → that’s not the Ollama API. You need the actual Ollama daemon URL, usually:
    http://173.208.156.207:11434
    
#

On VPS2, check:

curl http://127.0.0.1:11434/api/tags
ss -ltnp | grep -E '11434|8080|ollama'

Also: because this is a public IP, please firewall it so only VPS1 can hit the Ollama port. Don’t leave Ollama wide open on the internet.

And again: rotate that gateway token you pasted earlier. That one should be considered burned. 🦐

#

Perfect — then replace the placeholder with qwen3-vl:8b.

Use this on VPS1:

{
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://173.208.156.207:8080",
        "api": "ollama",
        "apiKey": "ollama-local",
        "timeoutSeconds": 300,
        "models": [
          {
            "id": "qwen3-vl:8b",
#
            "name": "qwen3-vl:8b",
            "input": ["text", "image"],
            "params": {
              "keep_alive": "15m"
            }
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "ollama/qwen3-vl:8b"
      },
#
      "models": {
        "ollama/qwen3-vl:8b": {}
      }
    }
  }
}

But only use port 8080 if this works from VPS1:

curl http://173.208.156.207:8080/api/tags

If that fails, 8080 is probably just the Ollama web UI and you need the real Ollama API port, usually:

#
"baseUrl": "http://173.208.156.207:11434"

Then test:

openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

Also small warning: qwen3-vl:8b is a vision model. It may work, but if tool use is flaky, try a regular text Qwen model as the main OpenClaw agent model and keep VL for image tasks.

fossil fable
#

can you privde the whole json file not just the model section

zinc sorrelBOT
#

Yep — here’s a full valid JSON version. Replace CHANGE_ME_ROTATE_THIS_TOKEN with a new token, and switch 8080 to 11434 if /api/tags does not work on 8080.

{
  "gateway": {
    "auth": {
      "mode": "token",
      "token": "CHANGE_ME_ROTATE_THIS_TOKEN"
    },
    "bind": "0.0.0.0",
    "mode": "local",
    "port": 18789,
    "trustedProxies": ["127.0.0.1", "::1", "localhost"],
    "controlUi": {
      "allowedOrigins": [
        "http://127.0.0.1:18789",
#
        "http://localhost:18789",
        "http://208.87.135.84:18789"
      ],
      "dangerouslyAllowHostHeaderOriginFallback": true,
      "dangerouslyDisableDeviceAuth": true,
      "allowInsecureAuth": true
    }
  },
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://173.208.156.207:8080",
        "api": "ollama",
        "apiKey": "ollama-local",
        "timeoutSeconds": 300,
#
        "models": [
          {
            "id": "qwen3-vl:8b",
            "name": "qwen3-vl:8b",
            "input": ["text", "image"],
            "params": {
              "keep_alive": "15m"
            }
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
#
      "model": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "imageModel": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "models": {
        "ollama/qwen3-vl:8b": {}
      }
    }
  },
  "plugins": {
    "entries": {
      "ollama": {
        "enabled": true,
#
        "config": {}
      },
      "bonjour": {
        "enabled": false
      }
    }
  }
}

Before restarting OpenClaw, test from VPS1:

curl http://173.208.156.207:8080/api/tags
#

If that does not return Ollama model JSON, change:

"baseUrl": "http://173.208.156.207:8080"

to:

"baseUrl": "http://173.208.156.207:11434"

Then restart:

openclaw gateway restart
fossil fable
#

Agent failed before reply: No API key found for provider "ollama". Auth store: /root/.openclaw/agents/main/agent/auth-profiles.json (agentDir: /root/.openclaw/agents/main/agent). Configure auth for this agent (openclaw agents add <id>) or copy auth-profiles.json from the main agentDir. | No API key found for provider "ollama". Auth store: /root/.openclaw/agents/main/agent/auth-profiles.json (agentDir: /root/.openclaw/agents/main/agent). Configure auth for this agent (openclaw agents add <id>) or copy auth-profiles.json from the main agentDir.
Logs: openclaw logs --follow

zinc sorrelBOT
#

That error is because apiKey: "ollama-local" is not accepted for a public-IP Ollama host. It’s only treated as a safe local marker for localhost/private LAN/.local/bare hostnames.

You have two good options:

Best option: put VPS1 + VPS2 on Tailscale/WireGuard/private networking, then use the private IP:

"baseUrl": "http://100.x.y.z:11434",
"apiKey": "ollama-local"

Quick test option: if the Ollama port is firewalled so only VPS1 can reach it, use a non-marker token string in the provider config:

"apiKey": "remote-ollama-firewalled"
#

So your Ollama block becomes:

"models": {
  "providers": {
    "ollama": {
      "baseUrl": "http://173.208.156.207:8080",
      "api": "ollama",
      "apiKey": "remote-ollama-firewalled",
      "timeoutSeconds": 300,
      "models": [
        {
          "id": "qwen3-vl:8b",
          "name": "qwen3-vl:8b",
          "input": ["text", "image"],
          "params": {
#
            "keep_alive": "15m"
          }
        }
      ]
    }
  }
}

Then restart:

openclaw gateway restart
openclaw models status
#

If it still says no API key, OpenClaw is probably not loading the file you edited. Check:

openclaw config get models.providers.ollama
openclaw gateway status --deep

Also remove/ignore that old:

"auth": {
  "profiles": {
    "ollama:default": {
      "provider": "ollama",
      "mode": "token"
    }
fossil fable
#

give me the entire file please

zinc sorrelBOT
#

Yep — use this as the full file. Do not reuse the token you pasted earlier; put a new random one in CHANGE_ME_ROTATE_THIS_TOKEN.

{
  "gateway": {
    "auth": {
      "mode": "token",
      "token": "CHANGE_ME_ROTATE_THIS_TOKEN"
    },
    "bind": "0.0.0.0",
    "mode": "local",
    "port": 18789,
    "trustedProxies": ["127.0.0.1", "::1", "localhost"],
    "controlUi": {
      "allowedOrigins": [
        "http://127.0.0.1:18789",
#
        "http://localhost:18789",
        "http://208.87.135.84:18789"
      ],
      "dangerouslyAllowHostHeaderOriginFallback": true,
      "dangerouslyDisableDeviceAuth": true,
      "allowInsecureAuth": true
    }
  },
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://173.208.156.207:8080",
        "api": "ollama",
        "apiKey": "remote-ollama-firewalled",
        "timeoutSeconds": 300,
#
        "models": [
          {
            "id": "qwen3-vl:8b",
            "name": "qwen3-vl:8b",
            "input": ["text", "image"],
            "params": {
              "keep_alive": "15m"
            }
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
#
      "model": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "imageModel": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "models": {
        "ollama/qwen3-vl:8b": {}
      }
    }
  },
  "plugins": {
    "entries": {
      "ollama": {
        "enabled": true,
#
        "config": {}
      },
      "bonjour": {
        "enabled": false
      }
    }
  }
}

Then run:

openclaw gateway restart
openclaw config get models.providers.ollama
fossil fable
#

no port 8080 is correct. it does return json correctly

zinc sorrelBOT
#

Good — then keep 8080. The remaining error was auth-resolution, not the port.

Use this exact line in the Ollama provider block:

"apiKey": "remote-ollama-firewalled"

Then verify OpenClaw is actually loading that file:

openclaw config get models.providers.ollama

You should see baseUrl, api, and apiKey in the output. If that command does not show the Ollama block, the gateway is reading a different config file than the one you edited.

Then:

#
openclaw gateway restart
openclaw models status
openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

If it still says “No API key found”, paste the output of:

openclaw config get models.providers.ollama
openclaw models status

And please make sure port 8080 is firewalled to VPS1 only — the fake API key is just satisfying OpenClaw’s remote-host auth requirement; it does not secure a public Ollama server.

fossil fable
#

Agent failed before reply: No API key found for provider "ollama". Auth store: /root/.openclaw/agents/main/agent/auth-profiles.json (agentDir: /root/.openclaw/agents/main/agent). Configure auth for this agent (openclaw agents add <id>) or copy auth-profiles.json from the main agentDir. | No API key found for provider "ollama". Auth store: /root/.openclaw/agents/main/agent/auth-profiles.json (agentDir: /root/.openclaw/agents/main/agent). Configure auth for this agent (openclaw agents add <id>) or copy auth-profiles.json from the main agentDir.

zinc sorrelBOT
#

Add this one line inside the Ollama provider:

"auth": "api-key",

That forces OpenClaw to use the inline models.providers.ollama.apiKey instead of looking only in /root/.openclaw/agents/main/agent/auth-profiles.json.

Your provider block should be:

"ollama": {
  "baseUrl": "http://173.208.156.207:8080",
  "api": "ollama",
  "auth": "api-key",
  "apiKey": "remote-ollama-firewalled",
#
  "timeoutSeconds": 300,
  "models": [
    {
      "id": "qwen3-vl:8b",
      "name": "qwen3-vl:8b",
      "input": ["text", "image"],
      "params": {
        "keep_alive": "15m"
      }
    }
  ]
}

Then run:

#
openclaw gateway restart
openclaw config get models.providers.ollama
openclaw models status

If config get does not show auth, apiKey, and baseUrl, then you’re editing the wrong config file / the gateway is loading a different one. Use:

openclaw gateway status --deep

to see which config path the service is actually using.

fossil fable
#

10:44:50 [ws] ⇄ res ✓ sessions.subscribe 1831ms conn=b68d3e9e…2b1f id=48134efb…7146
10:44:50 [ws] ⇄ res ✓ agent.identity.get 1846ms conn=b68d3e9e…2b1f id=37c2b4de…3dc0
10:44:50 [ws] ⇄ res ✓ agents.list 1856ms conn=b68d3e9e…2b1f id=af1f0085…64ae
10:44:50 [ws] ⇄ res ✓ health 1874ms cached=true conn=b68d3e9e…2b1f id=f805c7ec…01b0
10:44:52 [ws] ⇄ res ✗ chat.history 3605ms errorCode=UNAVAILABLE errorMessage=chat.history unavailable during gateway startup conn=b68d3e9e…2b1f id=7199231d…cbdf
10:44:52 [ws] ⇄ res ✓ sessions.list 3643ms conn=b68d3e9e…2b1f id=cdc2a71f…568a
10:44:52 [ws] ⇄ res ✗ models.list 3642ms errorCode=UNAVAILABLE errorMessage=models.list unavailable during gateway startup conn=b68d3e9e…2b1f id=df040ee6…fcae
10:44:54 [ws] ⇄ res ✓ commands.list 5822ms conn=b68d3e9e…2b1f id=c46731b7…763e
10:44:56 [ws] ⇄ res ✓ node.list 7098ms conn=b68d3e9e…2b1f id=0b4122df…b3c5
10:44:56 [ws] ⇄ res ✓ device.pair.list 7103ms conn=b68d3e9e…2b1f id=98b29755…b80c
10:44:56 [ws] ⇄ res ✗ chat.history 1ms errorCode=UNAVAILABLE errorMessage=chat.history unavailable during gateway startup conn=b68d3e9e…2b1f id=0dfad656…4d11
10:46:30 [ws] ⇄ res ✗ chat.history 7ms errorCode=UNAVAILABLE errorMessage=chat.history unavailable during gateway startup conn=b68d3e9e…2b1f id=bae85fb7…b091
10:46:30 [ws] ⇄ res ✓ chat.send 142ms runId=6109afff-d67d-4095-9cd3-596dcb5d7ddd conn=b68d3e9e…2b1f id=1f29513f…13b3
10:47:33 [ws] ⇄ res ✓ node.list 62918ms conn=b68d3e9e…2b1f id=c1c329b2…ce7a
10:49:27 [plugins] embedded acpx runtime backend registered (cwd: /root/.openclaw/workspace)
10:49:28 [browser/server] Browser control listening on http://127.0.0.1:18791/ (auth=token)
10:49:28 [gateway] ready
10:49:28 [heartbeat] started
10:50:16 [diagnostic] stuck session: sessionId=unknown sessionKey=agent:main:main state=processing age=166s queueDepth=1

zinc sorrelBOT
#

Those logs show two separate things:

  1. Gateway wasn’t ready until 10:49:28
    So the earlier models.list unavailable during gateway startup / chat.history unavailable messages are expected during startup.

  2. The current blocker is still auth/config loading
    Since it still says No API key found for provider "ollama", OpenClaw is either not seeing the apiKey, or it’s reading a different config file.

Please run these on VPS1:

openclaw --version
openclaw gateway status --deep
openclaw config get models.providers.ollama

The last command must show something like:

#
{
  "baseUrl": "http://173.208.156.207:8080",
  "api": "ollama",
  "auth": "api-key",
  "apiKey": "remote-ollama-firewalled"
}

If auth or apiKey is missing, add this inside the ollama provider block:

"auth": "api-key",
"apiKey": "remote-ollama-firewalled"

Then:

#
openclaw gateway restart

Also send /stop once in the UI/chat to clear that stuck run, then test:

openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

The slow startup may be a plugin runtime deps issue too, so if you’re not on 2026.4.27 or newer, update and run:

openclaw doctor --fix

Docs: https://docs.openclaw.ai/providers/ollama

fossil fable
#

OpenClaw 2026.4.26 (be8c246) {
"baseUrl": "http://173.208.156.207:8080",
"apiKey": "OPENCLAW_REDACTED",
"auth": "api-key",
"api": "ollama",
"timeoutSeconds": 300,
"models": [
{
"id": "qwen3-vl:8b",
"name": "qwen3-vl:8b",
"input": [
"text",
"image"
],
"params": {
"keep_alive": "15m"
},
"reasoning": false,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 200000,
"maxTokens": 8192,
"api": "ollama"
}
]
}

zinc sorrelBOT
#

Nice — that config output is now correct. So if the agent still says “No API key found”, it’s almost certainly one of these:

  1. Gateway hasn’t restarted after the config change
  2. Old stuck run/session is still using the previous config
  3. 2026.4.26 bug / startup weirdness

Do this on VPS1:

openclaw gateway restart

Then in the chat/UI send:

/stop
#
/new

Then test outside the agent loop:

openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

If that works, the Ollama/provider config is good and the issue was the old stuck session.

Also: you’re on 2026.4.26. I’d update to 2026.4.27+ — there are startup/plugin/runtime fixes there, and your logs showed very slow startup + stuck session behavior.

If it still fails after restart, paste:

#
openclaw gateway status --deep
openclaw models status
openclaw logs --follow
fossil fable
#

i got a reply in the browser with the pong message

zinc sorrelBOT
#

Great — that means the Ollama connection + model config are working 🎉

Now the remaining problem is just the old chat/session state. Do this once in the browser chat:

/stop
/new

Then send a normal test message like:

Say pong and nothing else

If that replies, you’re done.

#

If the normal agent chat is still slow/stuck but infer model run works, the model is probably struggling with OpenClaw’s full agent/tool prompt. For qwen3-vl:8b, I’d also consider lowering context from 200000 to something sane like 8192 or 16384:

"contextWindow": 16384,
"maxTokens": 4096,
"params": {
  "num_ctx": 16384,
  "keep_alive": "15m"
}

But first try /stop + /new. That’s the cleanest next step.

fossil fable
#

Assistant

[assistant turn failed before producing content]

#

11:06:41 [agent/embedded] embedded run agent end: runId=040c575c-e7c5-4de2-91ad-e5c7807d8d7a isError=true model=qwen3-vl:8b provider=ollama error=405 {"detail":"Method Not Allowed"} rawError=405 {"detail":"Method Not Allowed"}
11:08:58 [agent/embedded] embedded run agent end: runId=79fe140e-6b4c-4dde-97fb-e7c6323b1aea isError=true model=qwen3-vl:8b provider=ollama error=405 {"detail":"Method Not Allowed"} rawError=405 {"detail":"Method Not Allowed"}
11:10:39 [agent/embedded] session file repaired: rewrote 1 assistant message(s), dropped 1 blank user message(s) (f1b98f35-70f0-48ab-add9-054686fa660b.jsonl)
11:10:42 [agent/embedded] embedded run agent end: runId=623a2c6b-2e5f-40ba-a28a-4f2039edee8d isError=true model=qwen3-vl:8b provider=ollama error=405 {"detail":"Method Not Allowed"} rawError=405 {"detail":"Method Not Allowed"}

zinc sorrelBOT
#

Nice, so provider connectivity is solved. This new failure is probably the model choking on the full OpenClaw agent/tool prompt.

qwen3-vl:8b + contextWindow: 200000 is a risky combo. I’d make it much leaner:

"agents": {
  "defaults": {
    "experimental": {
      "localModelLean": true
    },
    "model": {
      "primary": "ollama/qwen3-vl:8b"
    },
    "imageModel": {
      "primary": "ollama/qwen3-vl:8b"
    },
#
    "models": {
      "ollama/qwen3-vl:8b": {}
    }
  }
}

And change the model entry to:

{
  "id": "qwen3-vl:8b",
  "name": "qwen3-vl:8b",
  "input": ["text", "image"],
  "reasoning": false,
#
  "contextWindow": 16384,
  "maxTokens": 4096,
  "params": {
    "num_ctx": 16384,
    "thinking": false,
    "keep_alive": "15m"
  },
  "compat": {
    "supportsTools": false
  }
}

Then:

#
openclaw gateway restart

In the browser chat:

/stop
/new

Then try a normal message again.

If it still fails, paste the few log lines immediately after the failure:

#
openclaw logs --follow

Also, since you’re on 2026.4.26, I’d update to 2026.4.27+ when you can — there were startup/runtime fixes that are relevant to the slow startup/stuck-session weirdness you’re seeing.

Docs: https://docs.openclaw.ai/providers/ollama

#

That 405 is actually useful: auth is fixed now. OpenClaw is reaching 173.208.156.207:8080, but that endpoint is rejecting the method OpenClaw needs.

With api: "ollama", OpenClaw calls Ollama’s native API, especially:

POST /api/chat

So test this from VPS1:

curl -i http://173.208.156.207:8080/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If that returns 405 Method Not Allowed, then port 8080 is not a full native Ollama API endpoint, even if /api/tags works. It may be a UI/proxy that only exposes some routes.

#

On VPS2, test the real Ollama daemon directly:

curl -i http://127.0.0.1:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If that works, point OpenClaw at the real Ollama API instead:

"baseUrl": "http://173.208.156.207:11434",
"api": "ollama"

Or reverse-proxy/firewall port 8080 so it forwards all methods/paths, including POST /api/chat, to Ollama on 11434.

fossil fable
#

[assistant turn failed before producing content]

zinc sorrelBOT
#

That UI message is just the wrapper — we need the log line right after it to know which failure path this is.

On VPS1, run:

openclaw logs --follow

Then send one test message in the browser chat and paste the new error lines.

Also please run these two checks:

curl -i http://173.208.156.207:8080/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'
#

openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

If /api/chat returns 405 Method Not Allowed, port 8080 is not a full Ollama API proxy — even if /api/tags works. OpenClaw needs POST /api/chat.

If both tests succeed but browser chat fails, then it’s likely the model struggling with the full agent prompt/tool surface, and we should use localModelLean, smaller num_ctx, and compat.supportsTools: false.

fossil fable
#

HTTP/1.1 405 Method Not Allowed
date: Tue, 28 Apr 2026 13:41:47 GMT
server: uvicorn
content-length: 31
content-type: application/json
x-process-time: 0

{"detail":"Method Not Allowed"}

zinc sorrelBOT
#

Yep, that confirms it: port 8080 is not a usable Ollama API endpoint for OpenClaw. It’s a Uvicorn app/proxy that answers some endpoints, but rejects POST /api/chat.

OpenClaw needs this to work:

POST /api/chat

So fix VPS2 one of these ways:

Option A — expose real Ollama port, firewalled to VPS1 only

"baseUrl": "http://173.208.156.207:11434"

Then on VPS1 test:

#
curl -i http://173.208.156.207:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

Option B — fix the 8080 reverse proxy
Make 8080 forward all methods and paths to Ollama’s native API on 127.0.0.1:11434, especially:

  • GET /api/tags
  • POST /api/chat
  • streaming responses

Until POST http://173.208.156.207:8080/api/chat works from VPS1, OpenClaw browser chat will keep failing.

Also keep it locked down — Ollama should not be public to the whole internet.

fossil fable
zinc sorrelBOT
#

It goes in your OpenClaw config at:

models.providers.ollama.baseUrl

Replace the old 8080 line inside the ollama provider block:

"models": {
  "providers": {
    "ollama": {
      "baseUrl": "http://173.208.156.207:11434",
      "apiKey": "remote-ollama-firewalled",
      "auth": "api-key",
      "api": "ollama",
#
      "timeoutSeconds": 300,
      "models": [
        {
          "id": "qwen3-vl:8b",
          "name": "qwen3-vl:8b",
          "input": ["text", "image"],
          "reasoning": false,
          "contextWindow": 16384,
          "maxTokens": 4096,
          "params": {
            "num_ctx": 16384,
            "thinking": false,
            "keep_alive": "15m"
          },
          "compat": {
#
            "supportsTools": false
          }
        }
      ]
    }
  }
}

So only this changes:

- "baseUrl": "http://173.208.156.207:8080"
+ "baseUrl": "http://173.208.156.207:11434"
#

Then restart:

openclaw gateway restart

But before relying on it, test from VPS1:

curl -i http://173.208.156.207:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If that doesn’t connect, VPS2 needs Ollama bound/exposed on 11434 and firewalled to VPS1.

fossil fable
#

im confused first you said to change base url option a expose real ollama port. hgow do i do that. as currently it is 8080

zinc sorrelBOT
#

Totally fair confusion — sorry, I should’ve separated the two parts more clearly.

Right now:

  • :8080 = some web UI / Uvicorn proxy. It answers /api/tags, but rejects POST /api/chat, so OpenClaw can’t use it.
  • Ollama’s real native API is usually :11434. You need to make that reachable from VPS1, then put :11434 in baseUrl.

Recommended safe way: use Tailscale/WireGuard between VPS1 and VPS2, then use the private/VPN IP in OpenClaw.

If you want to expose Ollama directly, on VPS2 you’d typically do:

sudo systemctl edit ollama

Add:

#
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
ss -ltnp | grep 11434

Then firewall it so only VPS1 can connect, e.g. with UFW:

#
sudo ufw allow from VPS1_PUBLIC_IP to any port 11434 proto tcp

Also check your VPS provider firewall/security group allows VPS1 → VPS2 port 11434.

Then from VPS1 test:

curl -i http://173.208.156.207:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

Only after that works, change OpenClaw:

fossil fable
#

vps1 cant reach vps2 via the curl command you gave me

zinc sorrelBOT
#

Yep — then don’t change OpenClaw yet. This is now a VPS2 networking/Ollama exposure issue.

Do this in order:

On VPS2, verify Ollama itself works locally:

curl -i http://127.0.0.1:11434/api/tags
curl -i http://127.0.0.1:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If that works, check what address Ollama is listening on:

#
ss -ltnp | grep 11434

If it shows 127.0.0.1:11434, VPS1 cannot reach it. On VPS2:

sudo systemctl edit ollama

Add:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
#

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
ss -ltnp | grep 11434

Now open the firewall only from VPS1:

sudo ufw allow from VPS1_PUBLIC_IP to any port 11434 proto tcp

Also check your VPS provider firewall/security group allows VPS1 → VPS2 port 11434.

Then from VPS1 retry:

#
curl -i http://173.208.156.207:11434/api/tags

If that works, then update OpenClaw’s baseUrl to:

"baseUrl": "http://173.208.156.207:11434"

Safest alternative: use Tailscale/WireGuard and avoid exposing Ollama publicly at all. That’s what I’d recommend long-term.

fossil fable
#

LISTEN 0 4096 *:11434 : users:(("ollama",pid=6296,fd=3))

zinc sorrelBOT
#

Good — Ollama is now listening on all interfaces (*:11434). So the remaining block is almost certainly firewall/provider networking.

On VPS2, allow VPS1 through the OS firewall:

sudo ufw status
sudo ufw allow from VPS1_PUBLIC_IP to any port 11434 proto tcp

If you don’t use UFW, check nftables/iptables:

sudo nft list ruleset | grep -n 11434
sudo iptables -S | grep 11434

Also check the VPS provider firewall/security group for VPS2 — many providers block ports before traffic reaches Ubuntu. Add an inbound rule:

#
TCP 11434 from VPS1_PUBLIC_IP only

Then from VPS1 test:

curl -i http://173.208.156.207:11434/api/tags

If it still fails, paste the exact curl error (connection refused, timeout, etc.). That tells us whether it’s firewall/drop vs routing/refused.

fossil fable
#

tcp command not found

zinc sorrelBOT
#

Ah, TCP wasn’t a command — I meant that as the provider firewall rule type in their web dashboard. Sorry, confusing wording.

On VPS2, run actual commands:

sudo ufw status

If UFW is active:

sudo ufw allow from VPS1_PUBLIC_IP to any port 11434 proto tcp
sudo ufw reload

Replace VPS1_PUBLIC_IP with the public IP of VPS1.

#

Then from VPS1:

curl -i http://173.208.156.207:11434/api/tags

If ufw says inactive, then check your VPS provider’s firewall/security group in their web control panel and add an inbound rule:

  • Protocol: TCP
  • Port: 11434
  • Source: VPS1 public IP only

Not a terminal command — provider dashboard setting.

fossil fable
#

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 28 Apr 2026 14:08:00 GMT
Content-Length: 340

{"models":[{"name":"qwen3-vl:8b","model":"qwen3-vl:8b","modified_at":"2026-04-24T02:44:25.131058107Z","size":6140415879,"digest":"901cae73216286ea8c5aba8b46d307ff7188f737285ec500c795a12f05225d28","details":{"parent_model":"","format":"gguf","family":"qwen3vl","families":["qwen3vl"],"parameter_size":"8.8B","quantization_level":"Q4_K_M"}}]}root@ssdnodes-658a1e047997a:~#

zinc sorrelBOT
#

Great — VPS1 can now reach the real Ollama API on 11434. 🎉

Now update OpenClaw’s config on VPS1:

"baseUrl": "http://173.208.156.207:11434"

So the Ollama block should include:

"ollama": {
  "baseUrl": "http://173.208.156.207:11434",
  "apiKey": "remote-ollama-firewalled",
  "auth": "api-key",
  "api": "ollama",
#
  "timeoutSeconds": 300,
  ...
}

Then restart and test:

openclaw gateway restart
openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

If that works, in the browser chat do:

#
/stop
/new

Then send a normal test message.

Keep the firewall rule restricted to VPS1 only — that part matters. 🦐

fossil fable
#

will zerotier work instead of tailscale?

zinc sorrelBOT
#

Yes — ZeroTier should work fine. OpenClaw doesn’t care whether it’s Tailscale, WireGuard, ZeroTier, private VPC, etc. It just needs VPS1 to reach Ollama’s native API.

Use the ZeroTier IP of VPS2 in OpenClaw:

"baseUrl": "http://ZEROTIER_VPS2_IP:11434"

Then because ZeroTier IPs are usually private-style overlay networking, you can usually go back to:

"apiKey": "ollama-local"

or keep:

#
"auth": "api-key",
"apiKey": "remote-ollama-firewalled"

Both are fine; keeping the explicit auth/apiKey is harmless.

Test from VPS1 first:

curl -i http://ZEROTIER_VPS2_IP:11434/api/tags
curl -i http://ZEROTIER_VPS2_IP:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If those work, update baseUrl, restart OpenClaw, and you’re set. ZeroTier is a much better idea than exposing Ollama publicly.

fossil fable
#

seems stuck although the port is active. 14:09:18 [gateway] loading configuration…
14:09:19 [gateway] resolving authentication…
14:09:19 [gateway] starting...
14:09:30 [gateway] starting HTTP server...
14:09:30 [canvas] host mounted at http://0.0.0.0:18789/__openclaw__/canvas/ (root /root/.openclaw/canvas)
14:09:30 [gateway] ⚠️ Gateway is binding to a non-loopback address. Ensure authentication is configured before exposing to public networks.
14:09:30 [gateway] ⚠️ gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true is enabled. Host-header origin fallback weakens origin checks and should only be used as break-glass.
14:09:32 [health-monitor] started (interval: 300s, startup-grace: 60s, channel-connect-grace: 120s)
14:09:33 [gateway] agent model: ollama/qwen3-vl:8b
14:09:33 [gateway] http server listening (6 plugins: acpx, browser, device-pair, memory-core, phone-control, talk-voice; 13.9s)
14:09:33 [gateway] log file: /tmp/openclaw/openclaw-2026-04-28.log
14:09:33 [gateway] security warning: dangerous config flags enabled: gateway.controlUi.allowInsecureAuth=true, gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true, gateway.controlUi.dangerouslyDisableDeviceAuth=true. Run openclaw security audit.
14:09:33 [gateway] starting channels and sidecars...
14:12:16 [plugins] embedded acpx runtime backend registered (cwd: /root/.openclaw/workspace)
14:12:17 [browser/server] Browser control listening on http://127.0.0.1:18791/ (auth=token)
14:12:17 [gateway] ready
14:12:17 [heartbeat] started

zinc sorrelBOT
#

That log actually shows it did finish startup:

14:12:17 [gateway] ready

The port being active at 14:09:33 just means the HTTP server was listening; OpenClaw was still doing channels/sidecars until 14:12:17.

So two things:

  1. Don’t test chat until you see [gateway] ready
  2. Since you’re on 2026.4.26, I’d update to 2026.4.27+ — there are startup/runtime fixes that look relevant here.

After it says ready, run:

#
openclaw status
openclaw models status
openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

If that works, the model path is fine. Then in the browser chat:

/stop
/new

and try a simple message.

If it still hangs after [gateway] ready, paste the log lines after the chat message — that will tell us whether it’s Ollama latency, the model choking on the agent prompt, or a session issue.

fossil fable
#

and ui isnt loading

zinc sorrelBOT
#

Got it — now we’re talking about the OpenClaw UI on VPS1, not Ollama.

Port “active” only means the gateway is listening. If the UI doesn’t load from your browser, check these:

1. Use the VPS1 URL, not the Ollama VPS

Open in your browser:

http://VPS1_PUBLIC_IP:18789/

Not 173.208.156.207 unless that is VPS1.

2. Make sure VPS1 firewall allows UI port 18789

On VPS1:

#
sudo ufw status
sudo ufw allow from YOUR_HOME_IP to any port 18789 proto tcp

Or add provider firewall rule:

TCP 18789 from your home IP

3. Add the exact browser origin

If you access the UI via a different IP/domain, add that exact origin to:

"gateway": {
#
  "controlUi": {
    "allowedOrigins": [
      "http://127.0.0.1:18789",
      "http://localhost:18789",
      "http://VPS1_PUBLIC_IP:18789"
    ]
  }
}

Then:

openclaw gateway restart
#

4. If it loads but won’t connect, use the gateway token

Run on VPS1:

openclaw dashboard

It should print/open the correct dashboard URL. If it prompts for auth, paste your new rotated gateway token into the token field.

Also: since the log says [gateway] ready, the backend finished startup. If the page is blank/spinning, it’s usually firewall, wrong URL/IP, origin mismatch, or token/auth.

fossil fable
#

ui is up. he types but disappears

zinc sorrelBOT
#

That “type → disappears” usually means the UI is sending an optimistic message, then chat.history refreshes and the gateway did not persist a real turn — usually because the run failed immediately.

Do this on VPS1 while you send one browser message:

openclaw logs --follow

Also verify OpenClaw is now using 11434, not old 8080:

openclaw config get models.providers.ollama.baseUrl

It should print:

#
http://173.208.156.207:11434

Then test the actual chat endpoint:

curl -i http://173.208.156.207:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

If that works:

openclaw gateway restart
#

Then in the UI:

/stop
/new

and try again.

If it still disappears, paste the new openclaw logs --follow lines from the moment you send the message. The old 405 would mean OpenClaw is still pointed at 8080 or hasn’t restarted with the updated config.

fossil fable
#

this is just hanging curl -i http://173.208.156.207:11434/api/chat
-H 'content-type: application/json'
-d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false}'

zinc sorrelBOT
#

That means OpenClaw isn’t the problem at this moment — Ollama is accepting the request but not returning. Usually one of:

  • model is cold-loading and taking ages
  • GPU/VRAM is stuck or overloaded
  • qwen3-vl:8b is slow/hung on that server
  • Ollama is trying a huge default context

On VPS2, watch Ollama while that curl is hanging:

sudo journalctl -u ollama -f

In another VPS2 shell:

#
nvidia-smi

Also try a much simpler/generic generate endpoint from VPS1:

curl --max-time 120 -i http://173.208.156.207:11434/api/generate \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","prompt":"Reply with exactly: pong","stream":false,"options":{"num_ctx":2048}}'

And try chat with a small context:

curl --max-time 120 -i http://173.208.156.207:11434/api/chat \
#
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":2048}}'

If those still hang, test locally on VPS2:

ollama run qwen3-vl:8b "Reply with exactly: pong"

If local ollama run also hangs, it’s model/Ollama/GPU-side. Try restarting Ollama:

sudo systemctl restart ollama
#

Then retest locally first. Once direct curl returns reliably, OpenClaw will have a fighting chance.

fossil fable
#

Apr 28 14:34:36 gpu-zjrd ollama[6296]: time=2026-04-28T14:34:36.116Z level=WARN source=runner.go:187 msg="truncating input prompt" limit=4096 prompt=14441 keep=4 new=4096
Apr 28 14:36:57 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:36:57 | 200 | 1.267285ms | 127.0.0.1 | GET "/api/tags"
Apr 28 14:36:57 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:36:57 | 200 | 536.948135ms | 127.0.0.1 | POST "/api/show"
Apr 28 14:39:17 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:39:17 | 200 | 1.299113ms | 127.0.0.1 | GET "/api/tags"
Apr 28 14:39:18 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:39:18 | 200 | 1.031492154s | 127.0.0.1 | POST "/api/show"
Apr 28 14:39:32 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:39:32 | 500 | 4m59s | 208.87.135.84 | POST "/api/chat"
Apr 28 14:41:22 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:41:22 | 500 | 2m2s | 208.87.135.84 | POST "/api/chat"
Apr 28 14:41:22 gpu-zjrd ollama[6296]: time=2026-04-28T14:41:22.336Z level=INFO source=runner.go:922 msg="aborting completion request due to client closing the connection"
Apr 28 14:41:54 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:41:54 | 200 | 1.628659ms | 127.0.0.1 | GET "/api/tags"
Apr 28 14:41:54 gpu-zjrd ollama[6296]: [GIN] 2026/04/28 - 14:41:54 | 200 | 790.500274ms | 127.0.0.1 | POST "/api/show"

zinc sorrelBOT
#

Yep, this is now clearly model/Ollama-side, not OpenClaw networking.

Key line:

truncating input prompt limit=4096 prompt=14441

OpenClaw is sending a normal-ish agent prompt, but Ollama is only running this model with a 4096 context, then the chat request eventually 500s after minutes.

Update the OpenClaw model entry to be much smaller/leaner:

{
  "id": "qwen3-vl:8b",
  "name": "qwen3-vl:8b",
#
  "input": ["text", "image"],
  "reasoning": false,
  "contextWindow": 4096,
  "maxTokens": 512,
  "params": {
    "num_ctx": 4096,
    "num_predict": 512,
    "thinking": false,
    "keep_alive": "15m"
  },
  "compat": {
    "supportsTools": false
  }
}
#

And keep:

"agents": {
  "defaults": {
    "experimental": {
      "localModelLean": true
    }
  }
}

Then:

openclaw gateway restart
#

But honestly: qwen3-vl:8b is a vision model and may be a poor main agent model. If possible, pull a normal text model on VPS2 and use that as the main agent model, for example a Qwen text/instruct model. Keep qwen3-vl:8b only as imageModel.

Quick sanity test from VPS1:

curl --max-time 120 -i http://173.208.156.207:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If even that fails/500s, restart Ollama and/or switch models:

sudo systemctl restart ollama

Progress though: the path is working; now it’s just the model/backend not handling the full turn.

fossil fable
#

can yu send the whole file. i got an error

zinc sorrelBOT
#

Yep — here’s a full clean JSON file with the lean Ollama settings and 11434.

Replace:

  • CHANGE_ME_ROTATE_THIS_TOKEN
  • 208.87.135.84 if that is not your VPS1 public IP
{
  "gateway": {
    "auth": {
      "mode": "token",
      "token": "CHANGE_ME_ROTATE_THIS_TOKEN"
    },
    "bind": "0.0.0.0",
    "mode": "local",
    "port": 18789,
#
    "trustedProxies": ["127.0.0.1", "::1", "localhost"],
    "controlUi": {
      "allowedOrigins": [
        "http://127.0.0.1:18789",
        "http://localhost:18789",
        "http://208.87.135.84:18789"
      ],
      "dangerouslyAllowHostHeaderOriginFallback": true,
      "dangerouslyDisableDeviceAuth": true,
      "allowInsecureAuth": true
    }
  },
  "models": {
    "providers": {
      "ollama": {
#
        "baseUrl": "http://173.208.156.207:11434",
        "apiKey": "remote-ollama-firewalled",
        "auth": "api-key",
        "api": "ollama",
        "timeoutSeconds": 300,
        "models": [
          {
            "id": "qwen3-vl:8b",
            "name": "qwen3-vl:8b",
            "input": ["text", "image"],
            "reasoning": false,
            "contextWindow": 4096,
            "maxTokens": 512,
            "params": {
              "num_ctx": 4096,
#
              "num_predict": 512,
              "thinking": false,
              "keep_alive": "15m"
            },
            "compat": {
              "supportsTools": false
            },
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            }
          }
        ]
#
      }
    }
  },
  "agents": {
    "defaults": {
      "experimental": {
        "localModelLean": true
      },
      "model": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "imageModel": {
        "primary": "ollama/qwen3-vl:8b"
      },
      "models": {
#
        "ollama/qwen3-vl:8b": {}
      }
    }
  },
  "plugins": {
    "entries": {
      "ollama": {
        "enabled": true,
        "config": {}
      },
      "bonjour": {
        "enabled": false
      }
    }
  }
#
}

Then run:

openclaw gateway restart
openclaw config get models.providers.ollama.baseUrl
openclaw config get agents.defaults.experimental

After the gateway says ready, send in the UI:

/stop
#
/new

Then try a tiny message.

fossil fable
#

ok i have zerotier setup on both units with 10.121.15.177 ollama
10.121.15.22 openclaw what do i need to change to make it work and close the firewall. i have pinged both machines using the new IPs

zinc sorrelBOT
#

Perfect — use the ZeroTier Ollama IP now and close the public port.

1. On VPS1/OpenClaw, change only the Ollama baseUrl

"baseUrl": "http://10.121.15.177:11434"

Your Ollama provider should look like:

"ollama": {
  "baseUrl": "http://10.121.15.177:11434",
  "apiKey": "ollama-local",
  "api": "ollama",
  "timeoutSeconds": 300,
#
  "models": [
    {
      "id": "qwen3-vl:8b",
      "name": "qwen3-vl:8b",
      "input": ["text", "image"],
      "reasoning": false,
      "contextWindow": 4096,
      "maxTokens": 512,
      "params": {
        "num_ctx": 4096,
        "num_predict": 512,
        "thinking": false,
        "keep_alive": "15m"
      },
      "compat": {
#
        "supportsTools": false
      }
    }
  ]
}

You can remove "auth": "api-key" now if you want, because 10.x.x.x is private-network. Keeping it is also okay, but then keep a non-empty apiKey.

2. On VPS1, test ZeroTier path

curl -i http://10.121.15.177:11434/api/tags
curl --max-time 120 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
#
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

3. Restart OpenClaw

openclaw gateway restart

4. Close public Ollama access on VPS2

If using UFW:

sudo ufw delete allow from 208.87.135.84 to any port 11434 proto tcp
#
sudo ufw deny 11434/tcp
sudo ufw allow in on zt+ to any port 11434 proto tcp
sudo ufw status

If zt+ doesn’t work, get the interface name:

ip -br addr | grep 10.121.15.177

Then allow that interface explicitly, e.g.:

sudo ufw allow in on ztXXXXXXXX to any port 11434 proto tcp
#

Also remove the public 11434 inbound rule from your VPS provider firewall/security group if you added one.

After that, use:

"baseUrl": "http://10.121.15.177:11434"

and you’re off the public internet. 🦐

fossil fable
#

does ollama know to listen on the new ip?

zinc sorrelBOT
#

If Ollama is still showing:

LISTEN *:11434

then yes — it’s listening on all interfaces, including the ZeroTier IP 10.121.15.177.

Check on the Ollama VPS:

ss -ltnp | grep 11434

Good:

#
*:11434

or:

0.0.0.0:11434

Not enough:

127.0.0.1:11434

Then from the OpenClaw VPS test:

#
curl -i http://10.121.15.177:11434/api/tags

If that works, OpenClaw can use:

"baseUrl": "http://10.121.15.177:11434"

If you want Ollama to listen only on ZeroTier and not public interfaces, bind it specifically:

sudo systemctl edit ollama
#
[Service]
Environment="OLLAMA_HOST=10.121.15.177:11434"

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
ss -ltnp | grep 11434

But binding to *:11434 plus firewalling public access is also fine.

fossil fable
zinc sorrelBOT
#

That means the first curl is hanging, so the second command never runs. Hit Ctrl+C, then test with timeouts:

On VPS1:

curl --connect-timeout 5 --max-time 10 -v http://10.121.15.177:11434/api/tags

If that hangs/times out, ZeroTier ping works but TCP 11434 is blocked or Ollama isn’t listening on the ZeroTier interface.

On VPS2 / Ollama box, run:

ip -br addr | grep 10.121.15.177
ss -ltnp | grep 11434
curl -i http://127.0.0.1:11434/api/tags
#
curl -i http://10.121.15.177:11434/api/tags
sudo ufw status verbose

If UFW is active, allow the ZeroTier interface. First get the interface name:

ip -br addr | grep 10.121.15.177

It’ll look like ztxxxxxxx. Then:

sudo ufw allow in on ztxxxxxxx to any port 11434 proto tcp
sudo ufw reload
#

If you previously added a broad deny like sudo ufw deny 11434/tcp, remove it if it’s blocking the ZeroTier allow:

sudo ufw status numbered
sudo ufw delete NUMBER

Then retry from VPS1:

curl --connect-timeout 5 --max-time 10 -i http://10.121.15.177:11434/api/tags

Only change OpenClaw to the ZeroTier URL once that curl returns JSON.

fossil fable
#

ok it finally came back with curl: (28) Failed to connect to 10.121.15.177 port 11434 after 136304 ms: Couldn't connect to server

zinc sorrelBOT
#

That’s a TCP connect timeout: ZeroTier ping works, but port 11434 over ZeroTier is blocked/not listening on that path.

On the Ollama VPS, run these and paste the output:

ip -br addr | grep 10.121.15.177
ss -ltnp | grep 11434
curl --connect-timeout 5 --max-time 10 -i http://10.121.15.177:11434/api/tags
sudo ufw status numbered

Most likely fixes:

If ss shows only 127.0.0.1:11434

Ollama is local-only. Bind it to ZeroTier:

#
sudo systemctl edit ollama

Put:

[Service]
Environment="OLLAMA_HOST=10.121.15.177:11434"

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
#

If ss shows *:11434 but ZeroTier curl still fails

Firewall is blocking it. Find the ZeroTier interface name:

ip -br addr | grep 10.121.15.177

Then allow it, replacing ztxxxxxx:

sudo ufw allow in on ztxxxxxx to any port 11434 proto tcp
sudo ufw reload

If you have a deny rule for 11434, remove it first:

#
sudo ufw status numbered
sudo ufw delete NUMBER

Then from VPS1 retry:

curl --connect-timeout 5 --max-time 10 -i http://10.121.15.177:11434/api/tags
fossil fable
#

ztbs54awa2 UNKNOWN 10.121.15.177/24 fe80::4cad:95ff:fec8:b81b/64
LISTEN 0 4096 *:11434 :
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 28 Apr 2026 20:57:04 GMT
Content-Length: 340

{"models":[{"name":"qwen3-vl:8b","model":"qwen3-vl:8b","modified_at":"2026-04-24T02:44:25.131058107Z","size":6140415879,"digest":"901cae73216286ea8c5aba8b46d307ff7188f737285ec500c795a12f05225d28","details":{"parent_model":"","format":"gguf","family":"qwen3vl","families":["qwen3vl"],"parameter_size":"8.8B","quantization_level":"Q4_K_M"}}]}[sudo] password for administrator:

zinc sorrelBOT
#

Good data. On the Ollama VPS itself, 10.121.15.177:11434 works and Ollama is listening on *:11434. So the block is between VPS1 → VPS2 over ZeroTier, almost certainly firewall.

You’re currently stopped at the sudo password prompt for ufw status. Enter the password, then check the rules.

Since your ZeroTier interface is:

ztbs54awa2

On the Ollama VPS, run:

sudo ufw status numbered
sudo ufw allow in on ztbs54awa2 to any port 11434 proto tcp
sudo ufw reload
#
sudo ufw status numbered

If you see any broad deny for 11434/tcp, delete it by number:

sudo ufw delete NUMBER

Then from the OpenClaw VPS retry:

curl --connect-timeout 5 --max-time 10 -i http://10.121.15.177:11434/api/tags

If it still times out after UFW allows ztbs54awa2, check ZeroTier Central too: make sure both members are authorized and there are no flow rules blocking TCP/11434.

fossil fable
#

To Action From
-- ------ ----
[ 1] OpenSSH ALLOW IN Anywhere
[ 2] 8080 ALLOW IN Anywhere
[ 3] 11434/tcp ALLOW IN 208.87.135.84
[ 4] OpenSSH (v6) ALLOW IN Anywhere (v6)
[ 5] 8080 (v6) ALLOW IN Anywhere (v6)

zinc sorrelBOT
#

There it is: UFW only allows 11434 from the public VPS1 IP (208.87.135.84), not from the ZeroTier IP (10.121.15.22).

On the Ollama VPS, add the ZeroTier allow:

sudo ufw allow from 10.121.15.22 to any port 11434 proto tcp
sudo ufw reload
sudo ufw status numbered

Then from OpenClaw VPS test:

curl --connect-timeout 5 --max-time 10 -i http://10.121.15.177:11434/api/tags

Once that works, remove the public 11434 rule:

#
sudo ufw delete 3

Careful: after adding the new rule, numbering may change, so run sudo ufw status numbered first and delete the rule that says:

11434/tcp ALLOW IN 208.87.135.84

Also consider closing public 8080 later if that UI/proxy doesn’t need to be internet-facing.

fossil fable
#

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 28 Apr 2026 21:00:00 GMT
Content-Length: 340

{"models":[{"name":"qwen3-vl:8b","model":"qwen3-vl:8b","modified_at":"2026-04-24T02:44:25.131058107Z","size":6140415879,"digest":"901cae73216286ea8c5aba8b46d307ff7188f737285ec500c795a12f05225d28","details":{"parent_model":"","format":"gguf","family":"qwen3vl","families":["qwen3vl"],"parameter_size":"8.8B","quantization_level":"Q4_K_M"}}]}root@ssdnodes-658a1e047997a:~#

zinc sorrelBOT
#

Excellent — ZeroTier path is working now. 🎉

Now update OpenClaw on VPS1 to use:

"baseUrl": "http://10.121.15.177:11434"

Then restart:

openclaw gateway restart

After that, test:

#
openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

And in the UI:

/stop
/new

Then try a tiny message.

Now close the old public exposure on the Ollama VPS:

#
sudo ufw status numbered

Delete the rule that looks like:

11434/tcp ALLOW IN 208.87.135.84

For example, if it’s still rule 3:

sudo ufw delete 3

Then confirm:

#
sudo ufw status numbered

You want 11434 allowed from 10.121.15.22, not the public IP.

fossil fable
#

how do I get the openclaw gateway to start without holding the cli open with text after it loads

zinc sorrelBOT
#

Install/run it as the managed systemd user service instead of foreground mode:

openclaw gateway install --force
openclaw gateway start
openclaw gateway status

After that you can close the terminal. Manage it with:

openclaw gateway restart
openclaw gateway stop
openclaw gateway status

Logs without keeping the gateway attached:

#
openclaw logs --follow

or on Linux systemd:

journalctl --user -u openclaw-gateway.service -f

If you started it manually with openclaw gateway, stop that foreground one first with Ctrl+C, then install/start the service.

Docs: https://docs.openclaw.ai/cli/gateway

fossil fable
#

do i need to remove 8080 from ollama as swell?

zinc sorrelBOT
#

Yes, if you don’t need that 8080 web UI/proxy exposed publicly, close it too.

On the Ollama VPS, your UFW had:

8080 ALLOW IN Anywhere
8080 (v6) ALLOW IN Anywhere (v6)

Remove those:

sudo ufw status numbered

Then delete the rule numbers for 8080. Example:

#
sudo ufw delete 2
sudo ufw delete 4

But check the numbers first — they shift after each delete.

Safer flow:

sudo ufw status numbered
sudo ufw delete <number-for-8080>
sudo ufw status numbered
sudo ufw delete <number-for-8080-v6>
sudo ufw status numbered
#

Keep only what you need:

  • SSH
  • 11434 from 10.121.15.22 only

If you still want to reach the web UI over ZeroTier, add:

sudo ufw allow from 10.121.15.22 to any port 8080 proto tcp

But don’t leave 8080 as Anywhere unless you intentionally want it public.

fossil fable
#

message just gets queued on the ui

zinc sorrelBOT
#

Queued usually means there’s already an active/stuck run for that session, so new messages are waiting behind it.

In the UI, send:

/stop

Wait a few seconds, then:

/new

If it still says queued, restart the gateway to clear the active run:

#
openclaw gateway restart

Then after [gateway] ready, test the backend outside UI:

openclaw infer model run --local --model ollama/qwen3-vl:8b --prompt "Reply with exactly: pong" --json

And tail logs while sending one UI message:

openclaw logs --follow

If it queues again, paste the log lines after the chat.send/agent run. My suspicion is still that qwen3-vl:8b is struggling as the main agent model; if the direct infer test is slow or fails, use a smaller text/instruct model as agents.defaults.model.primary and keep qwen3-vl:8b only for imageModel.

fossil fable
#

ahh here we go. Agent failed before reply: Model context window too small (4096 tokens; source=modelsConfig). Minimum is 16000.
Logs: openclaw logs --follow

zinc sorrelBOT
#

Good catch — set OpenClaw’s contextWindow back to 16000 minimum, but keep Ollama’s runtime context smaller if needed.

Change the model entry to:

{
  "id": "qwen3-vl:8b",
  "name": "qwen3-vl:8b",
  "input": ["text", "image"],
  "reasoning": false,
  "contextWindow": 16000,
  "maxTokens": 512,
  "params": {
    "num_ctx": 4096,
    "num_predict": 512,
    "thinking": false,
#
    "keep_alive": "15m"
  },
  "compat": {
    "supportsTools": false
  }
}

So:

  • contextWindow: 16000 = OpenClaw’s minimum planning budget
  • params.num_ctx: 4096 = what Ollama actually tries to run

Then:

#
openclaw gateway restart

If Ollama still logs truncating input prompt, raise params.num_ctx to 8192 or 16000 if your GPU can handle it. But first get past OpenClaw’s minimum check.

fossil fable
#

im running openclaw gateway in cli mode at moment, not with systemd so i cant run the openclaw logs --follow

zinc sorrelBOT
#

You can still view logs — the gateway printed the file path earlier:

/tmp/openclaw/openclaw-2026-04-28.log

Open a second SSH terminal to VPS1 and run:

tail -f /tmp/openclaw/openclaw-2026-04-28.log

Or generally:

tail -f "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"
#

Then keep your first terminal running openclaw gateway, and use the second one for logs/tests.

If you want to stop holding the CLI open later, install the service:

openclaw gateway install --force
openclaw gateway start
openclaw gateway status

But for debugging right now, two SSH terminals is perfect.

fossil fable
#

logs 0:00","hostname":"ssdnodes-658a1e047997a","message":"model fallback decision"}
{"0":"FailoverError: Model context window too small (4096 tokens; source=modelsConfig). Minimum is 16000.","_meta":{"runtime":"node","runtimeVersion":"22.22.2","hostname":"unknown","name":"openclaw","date":"2026-04-28T21:19:27.335Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/console-D6VW2Y3e.js:149:68","fileName":"console-D6VW2Y3e.js","fileNameWithLine":"console-D6VW2Y3e.js:149","fileColumn":"68","fileLine":"149","filePath":"/usr/lib/node_modules/openclaw/dist/console-D6VW2Y3e.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/console-D6VW2Y3e.js:149","method":"console.error"}},"time":"2026-04-28T21:19:27.337+00:00","hostname":"ssdnodes-658a1e047997a","message":"FailoverError: Model context window too small (4096 tokens; source=modelsConfig). Minimum is 16000."}

zinc sorrelBOT
#

Yep — that log means the config still has contextWindow: 4096 in the Ollama model entry. OpenClaw refuses anything below 16000.

On VPS1, run this:

openclaw config set models.providers.ollama.models[0].contextWindow 16000 --strict-json
openclaw config set models.providers.ollama.models[0].maxTokens 512 --strict-json
openclaw config set models.providers.ollama.models[0].params.num_ctx 4096 --strict-json
openclaw config set models.providers.ollama.models[0].params.num_predict 512 --strict-json

Then verify:

openclaw config get models.providers.ollama.models
#

You want to see:

"contextWindow": 16000

Then restart the gateway. If running foreground, Ctrl+C, then:

openclaw gateway

Keep params.num_ctx: 4096 for now — that’s Ollama’s actual runtime context. The important fix is contextWindow: 16000 for OpenClaw’s minimum check.

fossil fable
#

but the ollama server just gave me this before I change anything. [
{
"id": "qwen3-vl:8b",
"name": "qwen3-vl:8b",
"reasoning": false,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 16000,
"maxTokens": 512,
"params": {
"num_ctx": 4096,
"num_predict": 512,
"thinking": false,
"keep_alive": "15m"
},
"compat": {
"supportsTools": false
},
"api": "ollama"
}
]

zinc sorrelBOT
#

That config looks correct now. The error log was likely from the previous run/config before restart, or there’s an old active session still failing.

Do this:

  1. Stop the foreground gateway with Ctrl+C
  2. Start it again:
openclaw gateway
  1. After it says [gateway] ready, in the UI send:
/stop
/new
#
  1. Then send a tiny message.

If it still says context window 4096, run these on VPS1:

openclaw config get models.providers.ollama.models[0].contextWindow
openclaw config get agents.defaults.contextTokens
openclaw gateway status --deep

Important: if agents.defaults.contextTokens is set to 4096, that would cap the model and trigger the same error. If it prints 4096, remove/raise it:

openclaw config set agents.defaults.contextTokens 16000 --strict-json

But from the model snippet you pasted, the model entry itself is fixed.

fossil fable
#

the ui window just has wavy dots for split second and nothing even after stop new commands logs seem to be stopped {"0":"{"subsystem":"agent/embedded"}","1":"[llm-idle-timeout] ollama/qwen3-vl:8b produced no reply before the idle watchdog; retrying same model","_meta":{"runtime":"node","runtimeVersion":"22.22.2","hostname":"unknown","name":"{"subsystem":"agent/embedded"}","parentNames":["openclaw"],"date":"2026-04-28T21:54:27.936Z","logLevelId":4,"logLevelName":"WARN","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147:14","fileName":"subsystem-rHhUC6qs.js","fileNameWithLine":"subsystem-rHhUC6qs.js:147","fileColumn":"14","fileLine":"147","filePath":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147","method":"logToFile"}},"time":"2026-04-28T21:54:27.937+00:00","hostname":"ssdnodes-658a1e047997a","message":"[llm-idle-timeout] ollama/qwen3-vl:8b produced no reply before the idle watchdog; retrying same model"}

zinc sorrelBOT
#

That log means OpenClaw reached Ollama, but qwen3-vl:8b produced no tokens before the idle watchdog. So the UI “wavy dots then nothing” is the model run dying/silently retrying, not a UI problem.

At this point I’d stop using the VL/vision model as the main agent model. Use a normal text/instruct Ollama model as:

"agents": {
  "defaults": {
    "model": {
      "primary": "ollama/YOUR_TEXT_MODEL_TAG"
    },
    "imageModel": {
      "primary": "ollama/qwen3-vl:8b"
    }
  }
}
#

Keep qwen3-vl:8b for images only.

Before changing OpenClaw, prove Ollama can respond from VPS1:

curl --max-time 120 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If that hangs or 500s, OpenClaw can’t fix it — the model/backend isn’t returning.

On the Ollama VPS, also test locally:

ollama run qwen3-vl:8b "Reply with exactly: pong"
#

If that’s slow/hung too, restart Ollama:

sudo systemctl restart ollama

Then either pull/use a text model for the main agent, or ask in #models for a current Ollama model people are having success with. The networking is solved now; this is model suitability/runtime behavior.

fossil fable
#

the ui is not connecting

zinc sorrelBOT
#

Okay — separate this from the Ollama/model issue. For UI not connecting, check the gateway itself on VPS1:

openclaw gateway status --deep
curl -i http://127.0.0.1:18789/readyz
curl -i http://127.0.0.1:18789/healthz

Then check from your browser machine / outside VPS1:

http://VPS1_PUBLIC_IP:18789/

If the page loads but says disconnected/pairing/auth, run on VPS1:

#
openclaw devices list

If it shows a pending request, approve it:

openclaw devices approve <requestId>

If the page does not load at all, open firewall on VPS1 for your home IP:

sudo ufw allow from YOUR_HOME_PUBLIC_IP to any port 18789 proto tcp
sudo ufw status numbered
#

Also verify your allowedOrigins contains the exact URL you’re using:

"http://VPS1_PUBLIC_IP:18789"

Then restart:

openclaw gateway restart

If you’re running foreground instead of service, Ctrl+C and:

openclaw gateway
#

If it still won’t connect, paste the exact UI text: pairing required, auth token mismatch, connection refused, blank page, etc.

fossil fable
#

21:51:16 [diagnostic] stuck session: sessionId=8d47922c-ba7e-4c9f-a61f-fc40dd30f629 sessionKey=agent:main:main state=processing age=143s queueDepth=0
21:52:22 [ws] ⇄ res ✓ chat.history 118926ms conn=5a8ace67…0d96 id=1026da4b…cf9a
21:52:22 [ws] ⇄ res ✓ models.list 118940ms conn=5a8ace67…0d96 id=3d5fa423…7c36
21:52:22 [diagnostic] stuck session: sessionId=8d47922c-ba7e-4c9f-a61f-fc40dd30f629 sessionKey=agent:main:main state=processing age=209s queueDepth=0
21:52:24 [ws] ⇄ res ✓ node.list 66066ms conn=5a8ace67…0d96 id=f1918bfb…5815
21:52:52 [diagnostic] stuck session: sessionId=8d47922c-ba7e-4c9f-a61f-fc40dd30f629 sessionKey=agent:main:main state=processing age=239s queueDepth=0
21:53:22 [diagnostic] stuck session: sessionId=8d47922c-ba7e-4c9f-a61f-fc40dd30f629 sessionKey=agent:main:main state=processing age=269s queueDepth=0
21:54:27 [agent/embedded] [llm-idle-timeout] ollama/qwen3-vl:8b produced no reply before the idle watchdog; retrying same model

zinc sorrelBOT
#

The UI is connecting, but the gateway is getting wedged behind the stuck model run. That’s why chat.history took 118 seconds and the UI feels disconnected.

Stop the stuck session first.

If foreground gateway: press Ctrl+C, then start clean:

openclaw gateway

If managed service:

openclaw gateway restart

Then do not send a normal chat message yet. First change the main model away from qwen3-vl:8b, because it’s producing no reply.

#

For now, either pull a text model on the Ollama VPS, e.g.:

ollama pull qwen3:8b

Then on VPS1 set the primary to that text model and keep VL as image-only:

"model": {
  "primary": "ollama/qwen3:8b"
},
"imageModel": {
  "primary": "ollama/qwen3-vl:8b"
}
#

And add qwen3:8b under models.providers.ollama.models.

Or temporarily switch to any cloud/provider model you already have configured, just to confirm UI health.

Right now qwen3-vl:8b is the thing hanging the agent loop. The gateway/UI path is alive; it’s just blocked by the model run.

fossil fable
#

ui isnt connecting

zinc sorrelBOT
#

At this point the fastest clean reset is:

  1. Stop the current foreground gateway
    Press Ctrl+C in the terminal running openclaw gateway.

  2. Start it again

    openclaw gateway
    
  3. Wait until you see:

    [gateway] ready
    
  4. Open the UI fresh in a private/incognito tab:

#
   http://VPS1_PUBLIC_IP:18789/

If it still doesn’t connect, run these on VPS1 and paste the output:

openclaw gateway status --deep
curl -i http://127.0.0.1:18789/healthz
curl -i http://127.0.0.1:18789/readyz
sudo ufw status numbered

Also: don’t send another normal chat message with qwen3-vl:8b as primary yet — it’s been wedging the gateway. Once the UI connects, switch the main model to a text model and keep qwen3-vl:8b for images only.

fossil fable
#

err connection refused

zinc sorrelBOT
#

ERR_CONNECTION_REFUSED means nothing is listening on that UI address/port, or the gateway bound somewhere else.

On VPS1, run:

ss -ltnp | grep 18789
openclaw gateway status --deep

If ss shows nothing, start it:

openclaw gateway

Wait for:

#
[gateway] ready

If ss shows 127.0.0.1:18789, it’s only bound locally, so your browser can’t reach it remotely. Your config needs:

"gateway": {
  "bind": "0.0.0.0",
  "port": 18789
}

Then restart the gateway.

If ss shows 0.0.0.0:18789 or *:18789 but browser still gets refused, check VPS1 firewall/provider firewall:

#
sudo ufw status numbered

Allow your home IP:

sudo ufw allow from YOUR_HOME_PUBLIC_IP to any port 18789 proto tcp

Paste the output of:

ss -ltnp | grep 18789

and we’ll know which branch it is.

fossil fable
#

the only thing we changed since last working ui was the qwen3 model

zinc sorrelBOT
#

The qwen config can make the UI hang, but it should not cause connection refused. Refused means the gateway process is not listening on 18789 right now, or it crashed during startup.

Check this first on VPS1:

ss -ltnp | grep 18789

If nothing prints, start the gateway and watch for a config/startup error:

openclaw gateway

If it exits immediately, paste the error. My guess: one of the JSON edits broke validation and the gateway never started.

To confirm config validity without starting blindly:

#
openclaw doctor
openclaw config get models.providers.ollama

If you want to quickly rule out the qwen model config, temporarily switch primary away from Ollama before starting:

openclaw config set agents.defaults.model.primary "ollama/qwen3-vl:8b"

…but honestly, first run openclaw gateway and see if it stays up. ERR_CONNECTION_REFUSED is a gateway/listener problem, not the browser chat model run.

fossil fable
#

err connection refused. and the cli window on the vps1 wasnt reponding

#

wqe have gone backwards

zinc sorrelBOT
#

That sounds like the foreground gateway process wedged hard. Kill it and restart cleanly.

On VPS1, in the stuck CLI window try:

Ctrl+C

If it doesn’t respond, open a second SSH session to VPS1 and run:

pkill -f "openclaw gateway"
pkill -f "node.*openclaw"

Then verify port is clear:

#
ss -ltnp | grep 18789 || echo "18789 is clear"

Now start it again:

openclaw gateway

If it still hangs/crashes, temporarily disable the Ollama primary so the gateway/UI can recover. Edit config or run:

openclaw config set agents.defaults.model.primary "ollama/qwen3-vl:8b"

Actually if that’s already the failing model, better option: set a known working non-Ollama/cloud model if you have one configured, or remove the current session state by starting a fresh session after restart:

#
/new

But first priority: kill the wedged process and get ss -ltnp | grep 18789 showing a listener again.

Once UI is reachable, don’t send a normal message to qwen3-vl:8b as the primary — it’s the model run that wedged the loop.

#

Yeah, agreed — let’s stop chasing new changes and get back to a known-good baseline.

We now know:

  • ZeroTier networking works.
  • Ollama API is reachable on 10.121.15.177:11434.
  • The problem is qwen3-vl:8b hanging as the main agent model.
  • UI “connection refused” means the foreground gateway process is wedged/not listening.

Do this recovery path only:

# VPS1, second SSH session
pkill -f "openclaw gateway"
ss -ltnp | grep 18789 || echo "gateway stopped"
#

Then start clean:

openclaw gateway

Wait for:

[gateway] ready

Do not send a normal chat message yet.

For now, use a non-VL text model as the main model. On the Ollama VPS:

#
ollama pull qwen3:8b

Then we’ll set:

"model": { "primary": "ollama/qwen3:8b" },
"imageModel": { "primary": "ollama/qwen3-vl:8b" }

The VL model can stay for images, but it’s not behaving as a main OpenClaw agent model.

Also — you’re right to be frustrated. We solved networking, then got dragged into model/runtime instability. Let’s get the UI stable first, then swap the main model.

fossil fable
#

ok we are back on qwen3b-vl:8b and the webui is up but prompots just disappear again

zinc sorrelBOT
#

Good, UI is back. The disappearing prompts are the same model-run failure pattern. Don’t debug the UI further — switch the main model off the VL model.

On the Ollama VPS, pull a text model:

ollama pull qwen3:8b

Then on VPS1/OpenClaw, add it and set it as primary. Use this Ollama provider models array:

"models": [
  {
    "id": "qwen3:8b",
    "name": "qwen3:8b",
    "input": ["text"],
#
    "reasoning": false,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": {
      "num_ctx": 8192,
      "num_predict": 512,
      "thinking": false,
      "keep_alive": "15m"
    },
    "compat": {
      "supportsTools": false
    }
  },
  {
    "id": "qwen3-vl:8b",
#
    "name": "qwen3-vl:8b",
    "input": ["text", "image"],
    "reasoning": false,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": {
      "num_ctx": 4096,
      "num_predict": 512,
      "thinking": false,
      "keep_alive": "15m"
    },
    "compat": {
      "supportsTools": false
    }
  }
#
]

And set:

"model": {
  "primary": "ollama/qwen3:8b"
},
"imageModel": {
  "primary": "ollama/qwen3-vl:8b"
}

Then restart:

#
openclaw gateway restart

or if foreground, Ctrl+C then:

openclaw gateway

The VL model is fine to keep for image tasks, but it’s not returning reliably as the main chat agent.

fossil fable
#

we already did that and thats when the vps1 decided it wanted to hang.

zinc sorrelBOT
#

Fair. Let’s not repeat that blindly.

The safe rule now: don’t put any model into OpenClaw primary until it passes direct Ollama chat from VPS1. Otherwise the UI can wedge again.

From VPS1, test whatever text model you want to use:

curl --max-time 60 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"TEXT_MODEL_TAG_FROM_OLLAMA_LIST","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

Only if that returns pong, set OpenClaw primary to it.

For now, to stop the UI disappearing/hanging, either:

  1. Use a known working cloud model temporarily, if you have one configured, just to confirm OpenClaw/UI stability, or
#
  1. Leave Ollama configured but don’t send UI prompts until a direct /api/chat test succeeds.

Also reduce the Ollama timeout so bad local runs fail faster instead of wedging the UI:

"timeoutSeconds": 60

The networking is solved. The current issue is: the selected Ollama model isn’t reliably producing a normal chat completion for OpenClaw. For model choice, #models is the best place to ask what people are currently having success with on Ollama.

fossil fable
#

would we be better off installing openclaw on the same server as ollama?

zinc sorrelBOT
#

Honestly: it would simplify networking, but it won’t fix the model hanging.

Putting OpenClaw on the Ollama/GPU server would remove:

  • ZeroTier/firewall/baseUrl complexity
  • public/private IP confusion
  • cross-VPS latency

But your current blocker is now:

qwen3-vl:8b produced no reply before the idle watchdog

That will likely still happen on the same server if qwen3-vl:8b can’t reliably answer /api/chat.

My recommendation:

#
  1. Keep the two-server setup now that ZeroTier works.
  2. First prove the model works directly:
    curl --max-time 60 -i http://10.121.15.177:11434/api/chat \
      -H 'content-type: application/json' \
      -d '{"model":"qwen3-vl:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'
    
  3. If that hangs, switch to a better text model for primary.
  4. Keep qwen3-vl:8b only for image understanding.

If you do move OpenClaw onto the GPU box, use:

"baseUrl": "http://127.0.0.1:11434",
"apiKey": "ollama-local"
#

But I wouldn’t migrate until you’ve confirmed a text model responds cleanly. Otherwise we’ll just have the same problem in a new location.

fossil fable
zinc sorrelBOT
#

Yep, use that channel if that’s the visible models/model-discussion one. I may have used the old name from memory — sorry for the extra confusion.

Ask something like:

I have OpenClaw talking to remote Ollama over ZeroTier now. qwen3-vl:8b responds to /api/tags but hangs/no tokens on /api/chat as the main OpenClaw model. What Ollama text model are people currently using successfully as agents.defaults.model.primary?

Key thing: ask for a text/instruct main agent model, not VL/vision. Keep qwen3-vl:8b for imageModel once the primary is stable.

fossil fable
#

i dont have permission to ask in that channel

zinc sorrelBOT
#

No worries — then ask in #users-helping-users instead, since this is partly “what are people successfully running on Ollama?” experience.

For this thread, the practical next step is still:

  1. On the Ollama VPS, pick/pull a text/instruct model, not VL.
  2. Test it directly from VPS1 with /api/chat.
  3. Only then set it as OpenClaw primary.

Use this test shape:

curl --max-time 60 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"MODEL_TAG_HERE","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If it returns pong, it’s safe to try in OpenClaw. If it hangs, don’t set it as primary.

fossil fable
#

ok that was no help. no one seems to answer requests much in there. Chatgpt said to add these ollama pull qwen3:14b
ollama pull qwen2.5-coder:14b
ollama pull deepseek-r1:14b
ollama pull llama3.1:8b

zinc sorrelBOT
#

That list isn’t crazy, but don’t pull all of them yet. Pick one plain text/instruct model first and prove it answers /api/chat from VPS1.

I’d avoid the reasoning/coder/VL models as the first OpenClaw primary. We need boring + reliable.

On the Ollama VPS, pull one text model first, then from VPS1 test:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"MODEL_TAG_HERE","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

Only if that returns pong, add it to OpenClaw as primary.

Use this model entry shape:

#
{
  "id": "MODEL_TAG_HERE",
  "name": "MODEL_TAG_HERE",
  "input": ["text"],
  "reasoning": false,
  "contextWindow": 16000,
  "maxTokens": 512,
  "params": {
    "num_ctx": 4096,
    "num_predict": 512,
    "thinking": false,
    "keep_alive": "15m"
  },
  "compat": {
    "supportsTools": false
#
  }
}

Then set:

"model": {
  "primary": "ollama/MODEL_TAG_HERE"
},
"imageModel": {
  "primary": "ollama/qwen3-vl:8b"
}

So: text model for chat, qwen3-vl:8b only for images.

#

If the direct curl hangs, don’t put that model into OpenClaw — it’ll just wedge the UI again.

fossil fable
#

change this file to use the above models. use qwen3.14b as primary . remove the qwen3-vl:8b from the file {
"gateway": {
"auth": {
"mode": "token",
"token": "CHANGE_ME_ROTATE_THIS_TOKEN"
},
"bind": "0.0.0.0",
"mode": "local",
"port": 18789,
"trustedProxies": ["127.0.0.1", "::1", "localhost"],
"controlUi": {
"allowedOrigins": [
"http://127.0.0.1:18789",
"http://localhost:18789",
"http://208.87.135.84:18789"
],
"dangerouslyAllowHostHeaderOriginFallback": true,
"dangerouslyDisableDeviceAuth": true,
"allowInsecureAuth": true
}
},

#

"models": {
"providers": {
"ollama": {
"baseUrl": "http://10.121.15.177:11434",
"apiKey": "remote-ollama-firewalled",
"auth": "api-key",
"api": "ollama",
"timeoutSeconds": 300,
"models": [
{
"id": "qwen3:8b",
"name": "qwen3:8b",
"input": ["text", "image"],
"reasoning": false,
"contextWindow": 16000,
"maxTokens": 512,
"params": {
"num_ctx": 4096,
"num_predict": 512,
"thinking": false,
"keep_alive": "15m"
},
"compat": {
"supportsTools": false
},
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
}
}
]
}
}
},

#

"agents": {
"defaults": {
"experimental": {
"localModelLean": true
},
"model": {
"primary": "ollama/qwen3:8b"
},
"imageModel": {
"primary": "ollama/qwen3-vl:8b"
},
"models": {
"ollama/qwen3-vl:8b": {}
}
}
},
"plugins": {
"entries": {
"ollama": {
"enabled": true,
"config": {}
},
"bonjour": {
"enabled": false
}
}
}
}

zinc sorrelBOT
#

Yep — here’s the full JSON with those four models, qwen3:14b as primary, and no qwen3-vl:8b.

Important: the Ollama tag is usually qwen3:14b, not qwen3.14b.

{
  "gateway": {
    "auth": {
      "mode": "token",
      "token": "CHANGE_ME_ROTATE_THIS_TOKEN"
    },
    "bind": "0.0.0.0",
    "mode": "local",
    "port": 18789,
    "trustedProxies": ["127.0.0.1", "::1", "localhost"],
    "controlUi": {
#
      "allowedOrigins": [
        "http://127.0.0.1:18789",
        "http://localhost:18789",
        "http://208.87.135.84:18789"
      ],
      "dangerouslyAllowHostHeaderOriginFallback": true,
      "dangerouslyDisableDeviceAuth": true,
      "allowInsecureAuth": true
    }
  },
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://10.121.15.177:11434",
        "apiKey": "ollama-local",
#
        "api": "ollama",
        "timeoutSeconds": 60,
        "models": [
          {
            "id": "qwen3:14b",
            "name": "qwen3:14b",
            "input": ["text"],
            "reasoning": false,
            "contextWindow": 16000,
            "maxTokens": 512,
            "params": {
              "num_ctx": 4096,
              "num_predict": 512,
              "thinking": false,
              "keep_alive": "15m"
#
            },
            "compat": {
              "supportsTools": false
            }
          },
          {
            "id": "qwen2.5-coder:14b",
            "name": "qwen2.5-coder:14b",
            "input": ["text"],
            "reasoning": false,
            "contextWindow": 16000,
            "maxTokens": 512,
            "params": {
              "num_ctx": 4096,
              "num_predict": 512,
#
              "thinking": false,
              "keep_alive": "15m"
            },
            "compat": {
              "supportsTools": false
            }
          },
          {
            "id": "deepseek-r1:14b",
            "name": "deepseek-r1:14b",
            "input": ["text"],
            "reasoning": true,
            "contextWindow": 16000,
            "maxTokens": 512,
            "params": {
#
              "num_ctx": 4096,
              "num_predict": 512,
              "thinking": false,
              "keep_alive": "15m"
            },
            "compat": {
              "supportsTools": false
            }
          },
          {
            "id": "llama3.1:8b",
            "name": "llama3.1:8b",
            "input": ["text"],
            "reasoning": false,
            "contextWindow": 16000,
#
            "maxTokens": 512,
            "params": {
              "num_ctx": 4096,
              "num_predict": 512,
              "thinking": false,
              "keep_alive": "15m"
            },
            "compat": {
              "supportsTools": false
            }
          }
        ]
      }
    }
  },
#
  "agents": {
    "defaults": {
      "experimental": {
        "localModelLean": true
      },
      "model": {
        "primary": "ollama/qwen3:14b",
        "fallbacks": [
          "ollama/llama3.1:8b",
          "ollama/qwen2.5-coder:14b",
          "ollama/deepseek-r1:14b"
        ]
      },
      "models": {
        "ollama/qwen3:14b": {},
#
        "ollama/llama3.1:8b": {},
        "ollama/qwen2.5-coder:14b": {},
        "ollama/deepseek-r1:14b": {}
      }
    }
  },
  "plugins": {
    "entries": {
      "ollama": {
        "enabled": true,
        "config": {}
      },
      "bonjour": {
        "enabled": false
      }
#
    }
  }
}

Before using it, make sure the models are actually pulled on the Ollama VPS:

ollama pull qwen3:14b
ollama pull qwen2.5-coder:14b
ollama pull deepseek-r1:14b
ollama pull llama3.1:8b

Then restart OpenClaw.

#

That block is for qwen3:8b, not qwen3:14b. If you want the four-model config with qwen3:14b primary, replace the whole "models" block with the one I sent above.

Also update the agents.defaults.model.primary section — otherwise OpenClaw may still point at the old model.

Minimum changes from your pasted block:

- "id": "qwen3:8b",
- "name": "qwen3:8b",
- "input": ["text", "image"],
+ "id": "qwen3:14b",
+ "name": "qwen3:14b",
+ "input": ["text"],

And:

#
"agents": {
  "defaults": {
    "experimental": {
      "localModelLean": true
    },
    "model": {
      "primary": "ollama/qwen3:14b"
    },
    "models": {
      "ollama/qwen3:14b": {}
    }
  }
}

But again: only set qwen3:14b as primary after it exists on Ollama:

#
ollama list

and ideally after this works from VPS1:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'
#

Yep — that agents block is inconsistent:

  • primary is ollama/qwen3:8b
  • allowlist only contains ollama/qwen3-vl:8b
  • imageModel points to a model you said to remove

Replace your whole "agents" block with this:

"agents": {
  "defaults": {
    "experimental": {
      "localModelLean": true
    },
    "model": {
      "primary": "ollama/qwen3:14b",
#
      "fallbacks": [
        "ollama/llama3.1:8b",
        "ollama/qwen2.5-coder:14b",
        "ollama/deepseek-r1:14b"
      ]
    },
    "models": {
      "ollama/qwen3:14b": {},
      "ollama/llama3.1:8b": {},
      "ollama/qwen2.5-coder:14b": {},
      "ollama/deepseek-r1:14b": {}
    }
  }
}
#

No imageModel, no qwen3-vl:8b.

And make sure your models.providers.ollama.models array also contains those same four model IDs. Then restart OpenClaw.

fossil fable
#

ok after all those changes and removing qwen3-vl:8b. the webui is still sowing up as qwen3-vl:8b

zinc sorrelBOT
#

That’s probably a session-level model override stuck in the current UI session, not the global config.

Do these in order:

  1. In the UI, start a fresh session:
/new
  1. Check current model status from CLI:
openclaw models status
openclaw config get agents.defaults.model
openclaw config get agents.defaults.models
#
  1. If the UI still shows qwen3-vl:8b, explicitly switch the current session in the UI using the model picker or type:
/model ollama/qwen3:14b

If that says model not allowed, your allowlist still doesn’t include it. Verify:

openclaw config get agents.defaults.models

It should include:

"ollama/qwen3:14b": {}
#

Also hard-check that qwen3-vl:8b isn’t still somewhere in config:

openclaw config get | grep -n "qwen3-vl"

If it prints anything, remove that leftover entry.

fossil fable
#

im running the gateway in cli mode not systemd so cant run any openclaw commands

zinc sorrelBOT
#

You can run OpenClaw commands from a second SSH terminal while the first terminal keeps openclaw gateway running.

So:

  • Terminal 1: keep running:

    openclaw gateway
    
  • Terminal 2: run:

    openclaw models status
    openclaw config get agents.defaults.model
    openclaw config get agents.defaults.models
    openclaw config get | grep -n "qwen3-vl"
    
#

If you only have one SSH window, press Ctrl+C to stop the gateway, run the config checks/edits, then start it again:

openclaw gateway

CLI mode just means the gateway itself is foreground; it doesn’t prevent other shells from running openclaw commands.

plain fableBOT
fossil fable
#

Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : ollama/qwen3-vl:8b
Fallbacks (0) : -
Image model : ollama/qwen3-vl:8b
Image fallbacks (0): -
Aliases (0) : -
Configured models (1): ollama/qwen3-vl:8b

Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -

  • ollama effective=models.json:remote-o...rewalled | models.json=remote-o...rewalled | source=models.json: ~/.openclaw/agents/main/agent/models.json | synthetic=plugin-owned | source=models.providers.ollama (synthetic local key)

OAuth/token status

  • none

🦞 OpenClaw 2026.4.26 (be8c246) — I'm not magic—I'm just extremely persistent with retries and coping strategies.

{
"primary": "ollama/qwen3-vl:8b"
}

🦞 OpenClaw 2026.4.26 (be8c246) — Less clicking, more shipping, fewer "where did that file go" moments.

{
"ollama/qwen3-vl:8b": {}
}
error: missing required argument 'path'

zinc sorrelBOT
#

Yep — your status proves OpenClaw is still configured for qwen3-vl:8b:

Default: ollama/qwen3-vl:8b
Configured models (1): ollama/qwen3-vl:8b

Run these on VPS1 in a second SSH terminal, or stop the foreground gateway first:

openclaw config set agents.defaults.model.primary "ollama/qwen3:14b"

openclaw config set agents.defaults.model.fallbacks '[
  "ollama/llama3.1:8b",
  "ollama/qwen2.5-coder:14b",
  "ollama/deepseek-r1:14b"
#
]' --strict-json

openclaw config unset agents.defaults.imageModel

openclaw config set agents.defaults.models '{
  "ollama/qwen3:14b": {},
  "ollama/llama3.1:8b": {},
  "ollama/qwen2.5-coder:14b": {},
  "ollama/deepseek-r1:14b": {}
}' --strict-json --replace

Then verify:

#
openclaw models status

You want:

Default: ollama/qwen3:14b
Configured models: ollama/qwen3:14b ...

If qwen3-vl:8b still appears, find where it remains:

grep -R "qwen3-vl" ~/.openclaw/openclaw.json ~/.openclaw/agents/main/agent/models.json
#

Then restart the gateway. Also: the correct tag is qwen3:14b, not qwen3.14b.

fossil fable
#

it re wrote the json file

zinc sorrelBOT
#

Yep — that’s expected if you edited:

~/.openclaw/agents/main/agent/models.json

That file is generated/managed and OpenClaw can rewrite it. Don’t edit that one.

Edit this instead:

~/.openclaw/openclaw.json

or use openclaw config set.

Your status showed:

#
Config: ~/.openclaw/openclaw.json
source=models.json: ~/.openclaw/agents/main/agent/models.json
Default: ollama/qwen3-vl:8b

So fix the real config:

openclaw config set agents.defaults.model.primary "ollama/qwen3:14b"

openclaw config unset agents.defaults.imageModel

openclaw config set agents.defaults.models '{
  "ollama/qwen3:14b": {},
  "ollama/llama3.1:8b": {},
#
  "ollama/qwen2.5-coder:14b": {},
  "ollama/deepseek-r1:14b": {}
}' --strict-json --replace

Then check:

openclaw models status

If it still shows qwen3-vl:8b, search the real config:

grep -n "qwen3-vl" ~/.openclaw/openclaw.json
fossil fable
#

no i editedd the openclaw.json file only

zinc sorrelBOT
#

Got it. Then something is applying/saving config back over your manual edit — usually the Control UI config editor, openclaw config set, doctor --fix, or a stale running gateway/UI snapshot.

Do this cleanly:

  1. Stop foreground gateway with Ctrl+C.

  2. Backup the real config:

cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak
  1. Edit only this file:
nano ~/.openclaw/openclaw.json
  1. Validate before starting:
#
jq . ~/.openclaw/openclaw.json >/dev/null
openclaw config validate
  1. Confirm qwen-vl is gone:
grep -n "qwen3-vl" ~/.openclaw/openclaw.json || echo "qwen3-vl gone"
openclaw config get agents.defaults.model
openclaw config get agents.defaults.models
  1. Start gateway:
openclaw gateway
#

If qwen3-vl comes back after startup, paste the lines around it from:

grep -n "qwen3-vl\|qwen3:14b\|agents\|models" ~/.openclaw/openclaw.json

Important: don’t use the UI config editor during this — it may save an old snapshot back over your manual changes.

fossil fable
#

saaVED IT, VERIFIED IT WAS there and ran openclaw gateway. and it somehow re wrote it

zinc sorrelBOT
#

Yeah — that means OpenClaw likely auto-restored last-known-good config because the edited file failed validation/startup. It saves the bad one as openclaw.json.clobbered.*.

Do this, with gateway stopped:

# stop foreground gateway first: Ctrl+C

ls -lt ~/.openclaw/openclaw.json*
grep -n "qwen3-vl\|qwen3:14b" ~/.openclaw/openclaw.json
tail -n 80 /tmp/openclaw/openclaw-*.log | grep -i "clobbered\|restored\|rejected\|config"

Then use openclaw config set instead of manual editing:

openclaw config set agents.defaults.model.primary "ollama/qwen3:14b"
#

openclaw config set agents.defaults.model.fallbacks '[
  "ollama/llama3.1:8b",
  "ollama/qwen2.5-coder:14b",
  "ollama/deepseek-r1:14b"
]' --strict-json

openclaw config unset agents.defaults.imageModel

openclaw config set agents.defaults.models '{
  "ollama/qwen3:14b": {},
  "ollama/llama3.1:8b": {},
  "ollama/qwen2.5-coder:14b": {},
  "ollama/deepseek-r1:14b": {}
}' --strict-json --replace
#

Validate:

openclaw config validate
openclaw models status
grep -n "qwen3-vl" ~/.openclaw/openclaw.json || echo "qwen3-vl gone"

Only then start:

openclaw gateway

If it rewrites again, paste the clobbered/restored/rejected log line — that will tell us exactly what validation rejected.

fossil fable
#

ok ran the check. validation. i got a json error at line 119:2

zinc sorrelBOT
#

That explains the rewrite — OpenClaw restored the last good config because the edited JSON is invalid.

Show the area around line 119:

nl -ba ~/.openclaw/openclaw.json | sed -n '105,130p'

Common cause is an extra/missing comma or brace near the end of the file.

You can also run:

jq . ~/.openclaw/openclaw.json

It’ll usually point at the exact syntax problem.

#

If you paste lines 105–130, I can tell you exactly what to remove/add.

fossil fable
#

}
}
},
"plugins": {
"entries": {
"ollama": {
"enabled": true,
"config": {}
},
"bonjour": {
"enabled": false
}
}
}
}

zinc sorrelBOT
#

That ending looks valid by itself. The JSON error is probably just before that — likely a missing comma between the "agents" block and "plugins" block, or one extra }.

Please paste with line numbers:

nl -ba ~/.openclaw/openclaw.json | sed -n '90,125p'

But based on that tail, the transition should look exactly like this:

  "agents": {
    "defaults": {
      "experimental": {
        "localModelLean": true
      },
#
      "model": {
        "primary": "ollama/qwen3:14b",
        "fallbacks": [
          "ollama/llama3.1:8b",
          "ollama/qwen2.5-coder:14b",
          "ollama/deepseek-r1:14b"
        ]
      },
      "models": {
        "ollama/qwen3:14b": {},
        "ollama/llama3.1:8b": {},
        "ollama/qwen2.5-coder:14b": {},
        "ollama/deepseek-r1:14b": {}
      }
    }
#
  },
  "plugins": {
    "entries": {
      "ollama": {
        "enabled": true,
        "config": {}
      },
      "bonjour": {
        "enabled": false
      }
    }
  }
}

Notice the comma here:

#
  },
  "plugins": {

If yours says:

  }
  "plugins": {

add the comma.

fossil fable
#

90 "localModelLean": true
91 },
92 "model": {
93 "primary": "ollama/qwen3:14b",
94 "fallbacks": [
95 "ollama/llama3.1:8b",
96 "ollama/qwen2.5-coder:14b",
97 "ollama/deepseek-r1:14b"
98 ]
99 },
100 "models": {
101 "ollama/qwen3:14b": {},
102 "ollama/llama3.1:8b": {},
103 "ollama/qwen2.5-coder:14b": {},
104 "ollama/deepseek-r1:14b": {}
105 }
106 }
107 },
108 "plugins": {
109 "entries": {
110 "ollama": {
111 "enabled": true,
112 "config": {}
113 },
114 "bonjour": {
115 "enabled": false
116 }
117 }
118 }
119 }

zinc sorrelBOT
#

Lines 90–119 look valid. The JSON error is earlier than line 90, likely in the models.providers.ollama.models array before the agents block.

Run this for the earlier section:

nl -ba ~/.openclaw/openclaw.json | sed -n '45,90p'

Also run:

jq . ~/.openclaw/openclaw.json

jq usually says something like “expected comma at line X column Y”. Paste that exact message too.

Most likely there’s a missing comma after the final model object in the Ollama models array, or an extra trailing comma before line 89.

fossil fable
#

45 }
46 },
47 {
48 "id": "qwen2.5-coder:14b",
49 "name": "qwen2.5-coder:14b",
50 "input": ["text"],
51 "reasoning": false,
52 "contextWindow": 16000,
53 "maxTokens": 512,
54 "params": {
55 "num_ctx": 4096,
56 "num_predict": 512,
57 "thinking": false,
58 "keep_alive": "15m"
59 },
60 "compat": {
61 "supportsTools": false
62 }
63 },
64 {
65 "id": "deepseek-r1:14b",
66 "name": "deepseek-r1:14b",
67 "input": ["text"],
68 "reasoning": true,
69 "contextWindow": 16000,
70 "maxTokens": 512,
71 "params": {
72 "num_ctx": 4096,
73 "num_predict": 512,
74 "thinking": false,
75 "keep_alive": "15m"
76 },
77 "compat": {
78 "supportsTools": false
79 }
80 },
81 {
82 "id": "llama3.1:8b",
83 "name": "llama3.1:8b",
84 "input": ["text"],
85 "reasoning": false,
86 "contextWindow": 16000,
87 "agents": {
88 "defaults": {
89 "experimental": {
90 "localModelLean": true

zinc sorrelBOT
#

Found it. You accidentally inserted the "agents" block inside the llama3.1:8b model object.

At line 87, this is wrong:

"contextWindow": 16000,
"agents": {

The llama3.1:8b model object needs to finish first, then the models.providers... block closes, then "agents" starts at the top level.

Replace from line 81 onward with this ending:

            {
              "id": "llama3.1:8b",
#
              "name": "llama3.1:8b",
              "input": ["text"],
              "reasoning": false,
              "contextWindow": 16000,
              "maxTokens": 512,
              "params": {
                "num_ctx": 4096,
                "num_predict": 512,
                "thinking": false,
                "keep_alive": "15m"
              },
              "compat": {
                "supportsTools": false
              }
            }
#
          ]
        }
      }
    },
    "agents": {
      "defaults": {
        "experimental": {
          "localModelLean": true
        },
        "model": {
          "primary": "ollama/qwen3:14b",
          "fallbacks": [
            "ollama/llama3.1:8b",
            "ollama/qwen2.5-coder:14b",
            "ollama/deepseek-r1:14b"
#
          ]
        },
        "models": {
          "ollama/qwen3:14b": {},
          "ollama/llama3.1:8b": {},
          "ollama/qwen2.5-coder:14b": {},
          "ollama/deepseek-r1:14b": {}
        }
      }
    },
    "plugins": {
      "entries": {
        "ollama": {
          "enabled": true,
          "config": {}
#
        },
        "bonjour": {
          "enabled": false
        }
      }
    }
  }

Then run:

jq . ~/.openclaw/openclaw.json >/dev/null
openclaw config validate
#

If both pass, start the gateway.

fossil fable
#

jq command not found

zinc sorrelBOT
#

No problem — use Node instead, since OpenClaw already has Node:

node -e "JSON.parse(require('fs').readFileSync(process.env.HOME + '/.openclaw/openclaw.json','utf8')); console.log('JSON OK')"

Then run OpenClaw’s validator:

openclaw config validate

If both pass:

openclaw gateway
#

Optional install jq later:

sudo apt update
sudo apt install jq
fossil fable
#

openclaw config validate
-bash: jq: command not found
Config auto-restored from backup: /root/.openclaw/openclaw.json (missing-meta-vs-last-good)
Config observe anomaly: /root/.openclaw/openclaw.json (missing-meta-vs-last-good)

zinc sorrelBOT
#

Ah — that explains it. missing-meta-vs-last-good means OpenClaw saw your hand-edited file as a possible clobber because the file lost OpenClaw’s meta.lastTouchedVersion / last-known-good metadata. So it restored the backup.

Don’t hand-edit the whole JSON right now. Use openclaw config set so OpenClaw writes the metadata correctly.

With gateway stopped or from a second SSH terminal, run:

openclaw config set models.providers.ollama.models '[
  {
    "id": "qwen3:14b",
    "name": "qwen3:14b",
    "input": ["text"],
    "reasoning": false,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": { "num_ctx": 4096, "num_predict": 512, "thinking": false, "keep_alive": "15m" },
#
    "compat": { "supportsTools": false }
  },
  {
    "id": "llama3.1:8b",
    "name": "llama3.1:8b",
    "input": ["text"],
    "reasoning": false,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": { "num_ctx": 4096, "num_predict": 512, "thinking": false, "keep_alive": "15m" },
    "compat": { "supportsTools": false }
  },
  {
    "id": "qwen2.5-coder:14b",
    "name": "qwen2.5-coder:14b",
#
    "input": ["text"],
    "reasoning": false,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": { "num_ctx": 4096, "num_predict": 512, "thinking": false, "keep_alive": "15m" },
    "compat": { "supportsTools": false }
  },
  {
    "id": "deepseek-r1:14b",
    "name": "deepseek-r1:14b",
    "input": ["text"],
    "reasoning": true,
    "contextWindow": 16000,
    "maxTokens": 512,
    "params": { "num_ctx": 4096, "num_predict": 512, "thinking": false, "keep_alive": "15m" },
#
    "compat": { "supportsTools": false }
  }
]' --strict-json --replace

Then:

openclaw config set agents.defaults.model.primary "ollama/qwen3:14b"

openclaw config set agents.defaults.model.fallbacks '[
  "ollama/llama3.1:8b",
  "ollama/qwen2.5-coder:14b",
  "ollama/deepseek-r1:14b"
]' --strict-json
#

openclaw config unset agents.defaults.imageModel

openclaw config set agents.defaults.models '{
  "ollama/qwen3:14b": {},
  "ollama/llama3.1:8b": {},
  "ollama/qwen2.5-coder:14b": {},
  "ollama/deepseek-r1:14b": {}
}' --strict-json --replace

Verify:

openclaw config validate
#
openclaw models status
grep -n "qwen3-vl" ~/.openclaw/openclaw.json || echo "qwen3-vl gone"

Then start gateway again. This avoids the auto-restore trap.

fossil fable
#

config is now valid

zinc sorrelBOT
#

Nice — that’s real progress. 🎉

Before starting the gateway, do two quick checks:

openclaw models status
grep -n "qwen3-vl" ~/.openclaw/openclaw.json || echo "qwen3-vl gone"

You want Default: ollama/qwen3:14b and no qwen3-vl.

Then start:

openclaw gateway
#

Wait for [gateway] ready, open UI, and try a tiny prompt.

If it hangs again, don’t change config first — test the model directly from VPS1:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'
fossil fable
#

🦞 OpenClaw 2026.4.26 (be8c246)
I don't just autocomplete—I auto-commit (emotionally), then ask you to review (logically).

Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : ollama/qwen3:14b
Fallbacks (3) : ollama/llama3.1:8b, ollama/qwen2.5-coder:14b, ollama/deepseek-r1:14b
Image model : -
Image fallbacks (0): -
Aliases (0) : -
Configured models (4): ollama/qwen3:14b, ollama/llama3.1:8b, ollama/qwen2.5-coder:14b, ollama/deepseek-r1:14b

Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -

  • ollama effective=models.json:remote-o...rewalled | models.json=remote-o...rewalled | source=models.json: ~/.openclaw/agents/main/agent/models.json | synthetic=plugin-owned | source=models.providers.ollama (synthetic local key)

OAuth/token status

  • none
    qwen3-vl gone
    r
zinc sorrelBOT
#

Perfect — config is finally clean. ✅

Now start the gateway:

openclaw gateway

Wait for:

[gateway] ready

Then open the UI and test with a tiny prompt.

If it hangs/disappears, test the actual primary model directly from VPS1:

#
curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

But the OpenClaw side now looks right: primary is qwen3:14b, fallbacks are set, and qwen3-vl is gone.

fossil fable
#

the ui is still showing the qwen3-vl:8b model and I cant drop it down to change it. I did /new and it just did same thing. where on earth is it getting this model from. The json file is showing the correct file we just set

zinc sorrelBOT
#

It’s almost certainly coming from the current session override, not openclaw.json.

The Control UI model picker writes a persistent per-session model via sessions.patch, so the old session can keep saying qwen3-vl:8b even after the global default is fixed.

Run this from a second SSH terminal while gateway is running:

openclaw gateway call sessions.patch \
  --params '{"key":"agent:main:main","model":null}' \
  --json

That clears the session model override back to the configured default.

Then hard-refresh the browser UI. If it still shows the old model, explicitly set the session:

#
openclaw gateway call sessions.patch \
  --params '{"key":"agent:main:main","model":"ollama/qwen3:14b"}' \
  --json

Then verify:

openclaw sessions --verbose | grep -A6 -B3 "qwen3-vl"

If that prints another session key, patch that key the same way.

fossil fable
#

openclaw gateway call sessions.patch
--params '{"key":"agent:main:main","model":null}'
--json
Gateway call failed: Error: gateway timeout after 10000ms
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /root/.openclaw/openclaw.json
Bind: lan

zinc sorrelBOT
#

The gateway is wedged again, so RPC can’t answer. Stop it and patch the session file offline.

  1. Stop foreground gateway: Ctrl+C

  2. Back up sessions:

cp ~/.openclaw/agents/main/sessions/sessions.json ~/.openclaw/agents/main/sessions/sessions.json.bak
  1. Clear the stale model override directly:
node - <<'NODE'
const fs = require('fs');
const p = process.env.HOME + '/.openclaw/agents/main/sessions/sessions.json';
#
const s = JSON.parse(fs.readFileSync(p, 'utf8'));
for (const [k, v] of Object.entries(s)) {
  if (v && typeof v === 'object') {
    for (const key of ['providerOverride','modelOverride','modelOverrideSource','model','modelProvider','contextTokens','liveModelSwitchPending']) {
      delete v[key];
    }
  }
}
fs.writeFileSync(p, JSON.stringify(s, null, 2));
console.log('cleared model overrides in', Object.keys(s).length, 'sessions');
NODE
  1. Start gateway again:
#
openclaw gateway

That should force the UI/session to fall back to the configured default ollama/qwen3:14b.

If it still shows qwen3-vl, grep session/config files:

grep -R "qwen3-vl" ~/.openclaw/agents/main ~/.openclaw/openclaw.json
fossil fable
#

ok now it is showing correct model in ui

zinc sorrelBOT
#

Finally 😅

Before sending a real UI prompt, do one direct test from VPS1 so we don’t wedge it again:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If that returns pong, then try a tiny prompt in the UI.

If the UI hangs again, it’s the model runtime, not config/session anymore. But the OpenClaw side is now finally pointing at the right model.

fossil fable
#

how do i kill gateway

zinc sorrelBOT
#

If it’s running in the foreground terminal:

Ctrl+C

If that doesn’t work, from a second SSH terminal on VPS1:

pkill -f "openclaw gateway"

Then verify it’s stopped:

ss -ltnp | grep 18789 || echo "gateway stopped"
#

If you later install it as a service, use:

openclaw gateway stop
fossil fable
#

didnt stop it

zinc sorrelBOT
#

Use the port to find and kill the exact process:

sudo lsof -iTCP:18789 -sTCP:LISTEN -n -P

Look at the PID, then:

sudo kill PID

If it still stays up:

sudo kill -9 PID
#

One-liner version:

sudo kill -9 $(sudo lsof -t -iTCP:18789 -sTCP:LISTEN)

Then verify:

ss -ltnp | grep 18789 || echo "gateway stopped"

If it immediately comes back, it’s running as a service too. Then run:

openclaw gateway stop
#
systemctl --user stop openclaw-gateway.service
fossil fable
#

sudo lsof -iTCP:18789 -sTCP:LISTEN -n -P didnt return anything

zinc sorrelBOT
#

If lsof returned nothing, then nothing is listening on 18789 — the gateway is already stopped.

Verify:

ss -ltnp | grep 18789 || echo "gateway stopped"
curl --connect-timeout 3 -i http://127.0.0.1:18789/healthz

The curl should fail if it’s stopped.

If your browser still shows something, it’s likely cached/stale. Hard refresh or close the tab.

To start again cleanly:

#
openclaw gateway
fossil fable
#

oh it finally died

zinc sorrelBOT
#

Good — clean slate.

Before starting it again, do the direct model test so we don’t wedge the gateway immediately:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If that returns pong, start OpenClaw:

openclaw gateway

If it hangs or errors, don’t start the gateway with that model yet — the Ollama model itself isn’t behaving.

fossil fable
#

curl --max-time 90 -i http://10.121.15.177:11434/api/chat -H 'content-type: application/json' -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

curl: (28) Operation timed out after 90002 milliseconds with 0 bytes received

zinc sorrelBOT
#

That confirms it: don’t start OpenClaw with qwen3:14b as primary. The model itself is not returning even for a tiny direct /api/chat, so OpenClaw will wedge again.

Try the smaller/fallback models directly, one at a time from VPS1:

curl --max-time 60 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

If that works, set primary to llama3.1:8b:

openclaw config set agents.defaults.model.primary "ollama/llama3.1:8b"

If it fails, try:

#
curl --max-time 60 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"qwen2.5-coder:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

Also check the Ollama box while the curl is running:

journalctl -u ollama -f
nvidia-smi

At this point the networking and OpenClaw config are fine. The selected Ollama model just isn’t producing responses.

fossil fable
#

curl --max-time 60 -i http://10.121.15.177:11434/api/chat
-H 'content-type: application/json'
-d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 29 Apr 2026 01:22:45 GMT
Content-Length: 305

{"model":"llama3.1:8b","created_at":"2026-04-29T01:22:45.44103659Z","message":{"role":"assistant","content":"Pong"},"done":true,"done_reason":"stop","total_duration":22526575520,"load_duration":13972351551,"prompt_eval_count":15,"prompt_eval_duration":3233306347,"eval_count":3,"eval_duration":5305254835}

zinc sorrelBOT
#

Excellent — llama3.1:8b is the first model we’ve proven actually returns. Use that as primary.

On VPS1:

openclaw config set agents.defaults.model.primary "ollama/llama3.1:8b"

Optional: remove the bad qwen3:14b from fallbacks for now so it doesn’t wedge later:

openclaw config set agents.defaults.model.fallbacks '[
  "ollama/qwen2.5-coder:14b",
  "ollama/deepseek-r1:14b"
]' --strict-json
#

Then verify:

openclaw models status

You want:

Default: ollama/llama3.1:8b

Then start the gateway:

openclaw gateway
#

Wait for ready, open UI, try a tiny prompt.

If this works, you can later test other models one-by-one, but don’t put a model into primary/fallback unless direct /api/chat returns.

fossil fable
#

the .json file is still showing Qwen3.1:8b as primary?

zinc sorrelBOT
#

If it says qwen3.1:8b, that’s wrong — the model that worked was:

llama3.1:8b

Set it explicitly:

openclaw config set agents.defaults.model.primary "ollama/llama3.1:8b"

Then verify:

openclaw config get agents.defaults.model
#
openclaw models status

You want:

{
  "primary": "ollama/llama3.1:8b"
}

or status:

Default: ollama/llama3.1:8b
#

It’s llama, not qwen. easy typo after this many model names 😅

fossil fable
#

{
"primary": "ollama/llama3.1:8b",
"fallbacks": [
"ollama/qwen2.5-coder:14b",
"ollama/deepseek-r1:14b"
]

zinc sorrelBOT
#

That’s correct, but your pasted snippet is missing the final closing brace:

{
  "primary": "ollama/llama3.1:8b",
  "fallbacks": [
    "ollama/qwen2.5-coder:14b",
    "ollama/deepseek-r1:14b"
  ]
}

If openclaw config get agents.defaults.model printed that, you’re good.

One more check before starting:

#
openclaw models status

Make sure it says:

Default: ollama/llama3.1:8b

Then start gateway:

openclaw gateway
fossil fable
#

json file still says qwen. is that an issue

zinc sorrelBOT
#

Not necessarily. It’s only an issue if qwen is still the primary or a model the UI/session is using.

Your current primary is correct:

"primary": "ollama/llama3.1:8b"

It’s fine for the file to still mention qwen in:

"fallbacks": [
  "ollama/qwen2.5-coder:14b",
  "ollama/deepseek-r1:14b"
]
#

or in models.providers.ollama.models.

But if you want to be extra safe and avoid any chance of falling back into a bad qwen model, temporarily remove fallbacks:

openclaw config set agents.defaults.model.fallbacks '[]' --strict-json

Then verify:

openclaw models status

You want:

#
Default: ollama/llama3.1:8b
Fallbacks (0): -

That’s the safest next test.

fossil fable
#

but primary in json is llama yay

zinc sorrelBOT
#

Yesss, finally. 🎉

For the safest first run, I’d still clear fallbacks temporarily:

openclaw config set agents.defaults.model.fallbacks '[]' --strict-json

Then:

openclaw models status
openclaw gateway

Wait for [gateway] ready, then try one tiny UI prompt.

#

If that works, we can add fallbacks back one at a time only after each direct curl test passes.

fossil fable
#

even though it says gateay ready, the ui wont come up. connection refused and a netstat shows no open port

zinc sorrelBOT
#

If netstat/ss shows no listener on 18789, the UI can’t connect — regardless of the old [gateway] ready line. Let’s verify the live process.

In a second SSH terminal on VPS1, run:

ps -ef | grep -E '[o]penclaw|[n]ode.*openclaw'
ss -ltnp | grep -E '18789|18791|openclaw|node'
curl --connect-timeout 3 -i http://127.0.0.1:18789/healthz
openclaw gateway status --deep

If curl fails and ss shows no 18789, the gateway is not actually listening. Stop any stuck process:

pkill -f "openclaw gateway"
pkill -f "node.*openclaw"
#

Then start clean:

openclaw gateway --force

Watch for this line specifically:

[gateway] http server listening

If it says [gateway] ready but not http server listening, or exits after ready, paste the last ~80 log lines:

tail -n 80 "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"
#

Also sanity check the port config:

openclaw config get gateway.port
openclaw config get gateway.bind
fossil fable
#

curl --connect-timeout 3 -i http://127.0.0.1:18789/healthz
openclaw gateway status --deep
root 39538 38714 0 02:30 pts/2 00:00:00 grep --color=auto -E [o]penclaw|[n]ode.*openclaw
curl: (7) Failed to connect to 127.0.0.1 port 18789 after 0 ms: Couldn't connect to server

🦞 OpenClaw 2026.4.26 (be8c246) — Open source means you can see exactly how I judge your config.



Service: systemd (disabled)
File logs: /tmp/openclaw/openclaw-2026-04-29.log

Config (cli): ~/.openclaw/openclaw.json
Config (service): ~/.openclaw/openclaw.json

Gateway: bind=lan (0.0.0.0), port=18789 (env/config)
Probe target: ws://127.0.0.1:18789
Dashboard: http://208.87.135.84:18789/
Probe note: bind=lan listens on 0.0.0.0 (all interfaces); probing via 127.0.0.1.

Runtime: stopped (state inactive, sub dead, last exit 0, reason 0)
Connectivity probe: failed
Probe target: ws://127.0.0.1:18789
connect ECONNREFUSED 127.0.0.1:18789
Capability: unknown

Troubles: run openclaw status
Troubleshooting: https://docs.openclaw.ai/troubleshooting

zinc sorrelBOT
#

That output is clear: gateway is stopped.

Runtime: stopped
Connectivity probe: failed
ECONNREFUSED

So start it one of these two ways:

Foreground/debug mode

openclaw gateway --force

Keep that terminal open. Wait for:

#
[gateway] http server listening
[gateway] ready

Background/service mode

Since systemd is installed but disabled:

openclaw gateway install --force
openclaw gateway start
openclaw gateway status --deep

Then it won’t need the terminal open.

If openclaw gateway --force prints “ready” and then drops back to the shell, paste the last lines from:

#
tail -n 120 /tmp/openclaw/openclaw-2026-04-29.log

Right now there’s simply no running gateway process/listener.

fossil fable
#

ok ui is up. just typed a quick hello. the claw is spinning his waavy lines still

zinc sorrelBOT
#

Okay, UI/gateway are alive now. The wavy lines mean the model run is in progress. Since llama3.1:8b took ~22s on direct curl cold-load, give it up to ~60–90s on the first UI turn.

In a second SSH terminal, watch logs:

tail -f /tmp/openclaw/openclaw-2026-04-29.log

Look for either:

  • model=llama3.1:8b and then a reply — good
  • llm-idle-timeout
  • fallback to qwen/deepseek
  • context/tool/schema errors

If it goes past ~90s, stop it and remove fallbacks so it can’t wander into bad models:

#
openclaw config set agents.defaults.model.fallbacks '[]' --strict-json

Then restart gateway and try again.

Also verify the session didn’t keep an old model override:

grep -R "qwen3-vl\|qwen3:14b" ~/.openclaw/agents/main/sessions ~/.openclaw/openclaw.json

But for the first run, wait a bit — local model first token can be painfully slow.

fossil fable
#

","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147:14","fileName":"subsystem-rHhUC6qs.js","fileNameWithLine":"subsystem-rHhUC6qs.js:147","fileColumn":"14","fileLine":"147","filePath":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147","method":"logToFile"}},"time":"2026-04-29T03:28:38.864+00:00","hostname":"ssdnodes-658a1e047997a","message":"main-session restart recovery complete: recovered=0 failed=1 skipped=0"}

zinc sorrelBOT
#

That line is from startup recovery, not necessarily the current “hello” run. Need the fresh lines after you sent hello.

Run:

tail -n 80 /tmp/openclaw/openclaw-2026-04-29.log

or live:

tail -f /tmp/openclaw/openclaw-2026-04-29.log

Then send one tiny prompt and watch for lines containing:

#
agent/embedded
model=
llm-idle-timeout
ollama
error

Also, since restart recovery says failed=1, clear the old active session if it’s still wedged:

/stop
/new

If /stop doesn’t take, restart once more and clear fallbacks before testing:

#
openclaw config set agents.defaults.model.fallbacks '[]' --strict-json

Then start gateway and test only llama3.1:8b.

fossil fable
#

{"0":"{"subsystem":"agent/embedded"}","1":"[llm-idle-timeout] ollama/llama3.1:8b produced no reply before the idle watchdog; retrying same model","_meta":{"runtime":"node","runtimeVersion":"22.22.2","hostname":"unknown","name":"{"subsystem":"agent/embedded"}","parentNames":["openclaw"],"date":"2026-04-29T03:42:02.240Z","logLevelId":4,"logLevelName":"WARN","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147:14","fileName":"subsystem-rHhUC6qs.js","fileNameWithLine":"subsystem-rHhUC6qs.js:147","fileColumn":"14","fileLine":"147","filePath":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147","method":"logToFile"}},"time":"2026-04-29T03:42:02.242+00:00","hostname":"ssdnodes-658a1e047997a","message":"[llm-idle-timeout] ollama/llama3.1:8b produced no reply before the idle watchdog

zinc sorrelBOT
#

Good, now we have the actual issue:

llama3.1:8b produced no reply before the idle watchdog

Direct curl worked, but it took 22s for a tiny prompt. OpenClaw’s full agent prompt is much bigger, so first token may be too slow.

Set Ollama provider timeout higher:

openclaw config set models.providers.ollama.timeoutSeconds 300 --strict-json
openclaw config set agents.defaults.model.fallbacks '[]' --strict-json

Then stop/restart gateway:

#
pkill -f "openclaw gateway"
openclaw gateway

Before testing UI, warm the model:

curl --max-time 90 -i http://10.121.15.177:11434/api/chat \
  -H 'content-type: application/json' \
  -d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'

Then try UI again.

If it still hits idle timeout after timeoutSeconds: 300, then llama3.1:8b is too slow for OpenClaw’s full agent prompt on that Ollama setup. But this is the right next knob.

fossil fable
#

-H 'content-type: application/json'
-d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096,"num_predict":64}}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 29 Apr 2026 03:48:41 GMT
Content-Length: 303

{"model":"llama3.1:8b","created_at":"2026-04-29T03:48:41.510941888Z","message":{"role":"assistant","content":"Pong"},"done":true,"done_reason":"stop","total_duration":8146856748,"load_duration":254440500,"prompt_eval_count":15,"prompt_eval_duration":2758202499,"eval_count":3,"eval_duration":5119797724}

zinc sorrelBOT
#

Good — warmed up, it’s down to ~8s for tiny curl. Now restart OpenClaw after the timeout change and test UI:

pkill -f "openclaw gateway"
openclaw gateway

Make sure config has no fallbacks and timeout is 300:

openclaw config get models.providers.ollama.timeoutSeconds
openclaw config get agents.defaults.model

Expected:

#
300

and fallback array should be empty or absent.

Then in UI try:

hello

If it still hits llm-idle-timeout, paste that new log line — specifically the timestamp after the timeoutSeconds 300 change. That will tell us whether the new timeout is actually being picked up.

fossil fable
#

openclaw config get agents.defaults.model

🦞 OpenClaw 2026.4.26 (be8c246) — If you're lost, run doctor; if you're brave, run prod; if you're wise, run tests.

300

🦞 OpenClaw 2026.4.26 (be8c246) — I don't have opinions about tabs vs spaces. I have opinions about everything else.

{
"primary": "ollama/llama3.1:8b",
"fallbacks": []
}

zinc sorrelBOT
#

Perfect — config is exactly where we want it:

  • Ollama timeout: 300
  • Primary: ollama/llama3.1:8b
  • Fallbacks: []

Now restart the gateway so it definitely picks that up:

pkill -f "openclaw gateway"
openclaw gateway

Wait for [gateway] ready, then test one tiny UI prompt.

If it still spins, tail logs:

#
tail -f /tmp/openclaw/openclaw-2026-04-29.log

and paste the new llm-idle-timeout or error line after the restart.

fossil fable
#

{"0":"{"subsystem":"agent/embedded"}","1":"low context window: ollama/llama3.1:8b ctx=16000 (warn<32000) source=modelsConfig","_meta":{"runtime":"node","runtimeVersion":"22.22.2","hostname":"unknown","name":"{"subsystem":"agent/embedded"}","parentNames":["openclaw"],"date":"2026-04-29T03:59:26.257Z","logLevelId":4,"logLevelName":"WARN","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147:14","fileName":"subsystem-rHhUC6qs.js","fileNameWithLine":"subsystem-rHhUC6qs.js:147","fileColumn":"14","fileLine":"147","filePath":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147","method":"logToFile"}},"time":"2026-04-29T03:59:26.259+00:00","hostname":"ssdnodes-658a1e047997a","message":"low context window: ollama/llama3.1:8b ctx=16000 (warn<32000) source=modelsConfig","traceId":"28274df74791346203caa43fc9839729","spanId":"08470886a275bf35","traceFlags":"01"}

#

{"0":"{"subsystem":"gateway/ws"}","1":"\u001b[93m⇄\u001b[39m \u001b[1mres\u001b[22m \u001b[92m✓\u001b[39m \u001b[1mnode.list\u001b[22m \u001b[2m35309ms\u001b[22m \u001b[2mconn\u001b[22m=\u001b[90m735bc7b1…06d1\u001b[39m \u001b[2mid\u001b[22m=\u001b[90mb4849920…2386\u001b[39m","_meta":{"runtime":"node","runtimeVersion":"22.22.2","hostname":"unknown","name":"{"subsystem":"gateway/ws"}","parentNames":["openclaw"],"date":"2026-04-29T03:59:26.370Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"file:///usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147:14","fileName":"subsystem-rHhUC6qs.js","fileNameWithLine":"subsystem-rHhUC6qs.js:147","fileColumn":"14","fileLine":"147","filePath":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js","filePathWithLine":"/usr/lib/node_modules/openclaw/dist/subsystem-rHhUC6qs.js:147","method":"logToFile"}},"time":"2026-04-29T03:59:26.370+00:00","hostname":"ssdnodes-658a1e047997a","message":"\u001b[93m⇄\u001b[39m \u001b[1mres\u001b[22m \u001b[92m✓\u001b[39m \u001b[1mnode.list\u001b[22m \u001b[2m35309ms\u001b[22m \u001b[2mconn\u001b[22m=\u001b[90m735bc7b1…06d1\u001b[39m \u001b[2mid\u001b[22m=\u001b[90mb4849920…2386\u001b[39m","traceId":"fc7551c53967ebd912aef726f1c38569","spanId":"e0d126c33080f662","traceFlags":"01"}

zinc sorrelBOT
#

That log is only a warning, not the connection failure:

  • OpenClaw is currently using ollama/llama3.1:8b
  • context is only 16000, so it warns because that’s below 32k
  • it also suggests Qwen isn’t actually the selected model yet

First, please paste:

openclaw --version

Then on VPS 1 — the OpenClaw box — test Ollama reachability:

curl http://<VPS2-IP-or-host>:11434/api/tags
#

If that fails, fix networking/Ollama binding/firewall first. On VPS 2, Ollama usually needs to listen beyond localhost, e.g. bind to 0.0.0.0 or preferably a private/Tailscale IP.

For OpenClaw config, important bit: do not use /v1 for Ollama. Use native Ollama:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://<VPS2-private-or-tailnet-ip>:11434",
        apiKey: "ollama-local",
        api: "ollama",
        timeoutSeconds: 300,
        models: [
          {
            id: "qwen3:<exact-tag>",
#
            name: "qwen3:<exact-tag>",
            contextWindow: 32768,
            maxTokens: 8192,
            params: {
              num_ctx: 32768,
              keep_alive: "15m",
              thinking: false
            }
          }
        ]
      }
    }
  },
  agents: {
    defaults: {
#

That node.list … 35309ms line is a different symptom: the Control UI asked the gateway for paired OpenClaw nodes and it took 35s. That’s not the Ollama model call itself.

For this setup, don’t route Ollama through an OpenClaw “node” unless you specifically need remote shell/browser tools. The simple path is:

OpenClaw VPS → HTTP → Ollama VPS native API

From VPS 1, test the real Ollama API, not just the UI:

curl --max-time 10 http://<VPS2-IP>:11434/api/tags

If that doesn’t return model JSON, OpenClaw won’t connect either. If it does, try:

curl --max-time 60 http://<VPS2-IP>:11434/api/chat \
#
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen3:<exact-tag>","messages":[{"role":"user","content":"say pong"}],"stream":false}'

Also: if you’re using a public VPS IP, please don’t expose Ollama raw to the internet. Prefer Tailscale/private networking/SSH tunnel. With OpenClaw, use baseUrl: "http://host:11434"no /v1.

Please paste these outputs next, with tokens/IPs redacted if needed:

openclaw --version
openclaw status --all
openclaw models status
openclaw nodes status

Docs: https://docs.openclaw.ai/providers/ollama

fossil fable
#

OpenClaw 2026.4.26 (be8c246)

zinc sorrelBOT
#

Nice, thanks — 2026.4.26 is new enough that I’d focus on network/config, not an old-version issue.

Next best checks from VPS 1:

curl --max-time 10 http://<VPS2-IP>:11434/api/tags

If that works, test Qwen directly:

curl --max-time 60 http://<VPS2-IP>:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen3:<exact-tag>","messages":[{"role":"user","content":"say pong"}],"stream":false}'

Important config detail: for OpenClaw, use Ollama’s native API, not OpenAI-compatible mode:

#
baseUrl: "http://<host>:11434" // no /v1
api: "ollama"

If <VPS2-IP> is a public IP, I’d strongly switch to Tailscale/private networking or an SSH tunnel. apiKey: "ollama-local" is meant for loopback/private/LAN-style hosts, and exposing Ollama publicly is risky.

If you want other people’s “I’ve done this” experience too, ask in #users-helping-users — but paste the two curl results here and we can narrow this down fast. 🦐

fossil fable
#

{"models":[{"name":"llama3.1:8b","model":"llama3.1:8b","modified_at":"2026-04-29T00:01:20.572654206Z","size":4920753328,"digest":"46e0c10c039e019119339687c3c1757cc81b9da49709a3b3924863ba87ca666e","details":{"parent_model":"","format":"gguf","family":"llama","families":["llama"],"parameter_size":"8.0B","quantization_level":"Q4_K_M"}},{"name":"deepseek-r1:14b","model":"deepseek-r1:14b","modified_at":"2026-04-28T23:58:18.876807976Z","size":8988112209,"digest":"c333b7232bdb521236694ffbb5f5a6b11cc45d98e9142c73123b670fca400b09","details":{"parent_model":"","

zinc sorrelBOT
#

Good — that /api/tags response means VPS 1 can reach Ollama on VPS 2. So the network path is working. 🎯

Now it’s likely one of these:

  1. OpenClaw is still pointed at local/default Ollama
  2. the selected model name doesn’t exactly match Ollama
  3. Qwen isn’t actually in the visible /api/tags list — I only see llama3.1:8b and deepseek-r1:14b in the pasted part

Try a direct chat using one model we know exists:

curl --max-time 60 http://<VPS2-IP>:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"say pong"}],"stream":false}'

If that works, configure OpenClaw with the same known-good model first:

#
openclaw config set models.providers.ollama.baseUrl "http://<VPS2-IP>:11434"
openclaw config set models.providers.ollama.apiKey "ollama-local"
openclaw config set models.providers.ollama.api "ollama"
openclaw config set models.providers.ollama.timeoutSeconds 300 --strict-json
openclaw config set models.providers.ollama.models '[{"id":"llama3.1:8b","name":"llama3.1:8b"}]' --strict-json --merge
openclaw config set agents.defaults.model '{"primary":"ollama/llama3.1:8b"}' --strict-json

openclaw config validate
openclaw gateway restart
openclaw models status

Once that works, swap llama3.1:8b for the exact Qwen tag shown by ollama list / /api/tags.

Also: if <VPS2-IP> is public internet, I’d use Tailscale/private IP instead. Direct public Ollama is a bit spicy security-wise. 🦐

fossil fable
#

we have been over those commands so many times, you know the IP's of the VPS1 and VPS2. can you please enlighten me to get this working. surely no one else has issues like this

zinc sorrelBOT
#

Yep — and I get why you’re annoyed. Remote Ollama across two VPSes is exactly the kind of thing that looks “simple” and then wastes hours.

Use the ZeroTier/private path, not the public/IP/UI path:

  • OpenClaw VPS1: 10.121.15.22
  • Ollama VPS2: 10.121.15.177
  • Final Ollama base URL should be:
http://10.121.15.177:11434

On VPS2, allow VPS1 over ZeroTier:

sudo ufw allow from 10.121.15.22 to any port 11434 proto tcp
#

Then on VPS1, verify:

curl http://10.121.15.177:11434/api/tags

For OpenClaw, configure native Ollama, not /v1 and not the :8080 UI/proxy thing:

openclaw config set models.providers.ollama '{
  "baseUrl": "http://10.121.15.177:11434",
  "api": "ollama",
  "apiKey": "ollama-local",
  "timeoutSeconds": 300,
  "contextWindow": 16000,
  "maxTokens": 8192,
#
  "models": [
    {
      "id": "qwen3:14b",
      "name": "qwen3:14b",
      "contextWindow": 16000,
      "maxTokens": 8192,
      "params": {
        "num_ctx": 8192,
        "keep_alive": "15m",
        "thinking": false
      }
    },
    { "id": "llama3.1:8b", "name": "llama3.1:8b" },
    { "id": "deepseek-r1:14b", "name": "deepseek-r1:14b" }
  ]
#
}' --strict-json --replace

openclaw config set agents.defaults.model '{"primary":"ollama/qwen3:14b"}' --strict-json
openclaw config validate
openclaw gateway restart
openclaw models status

Important: it’s qwen3:14b with a colon, not qwen3.14b.

Also I’d avoid qwen3-vl:8b as the primary chat model — we saw it hang/500/truncate. Use it only for image/vision later once text is stable.

fossil fable
#

again you have alreayd been though those commands. zerotier is already running. VPS 1 can talk to VPS 2. we have isolated the firewalls and are not using 8080. and the json is already qwen3:14b . so get your act together. hours. so far we have spent days doing this and I am only a little bit away from it working. I do not understand why this is happpening. both clean builds. both correct software and yet 1 has issues talking to the other via openclaw. Maybe openclaw is not as good as people make out. maybe there is something better to use

zinc sorrelBOT
#

You’re right — we’re past firewall/ZeroTier/8080. I shouldn’t have looped you back there.

Where we actually are:

  • VPS1 → VPS2 works over ZeroTier: 10.121.15.22 → 10.121.15.177:11434
  • model is qwen3:14b
  • native Ollama URL is the right one
  • so this is now OpenClaw runtime/model resolution, not basic networking

The single most useful split now is this:

openclaw infer model run \
  --local \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
#
  --json

If that fails, OpenClaw is still not resolving the Ollama provider/config correctly.

If that succeeds, but chat/UI fails, then the problem is the full agent turn: session override, old model still selected, tool prompt too large, context/idle timeout, or Qwen not behaving under OpenClaw’s agent prompt.

Given what we saw earlier, my strongest suspicion is stale model/session config or agent defaults, not VPS connectivity. Specifically: something may still be pulling qwen3-vl:8b, llama3.1:8b, or a too-small 4096 context from another config layer/session.

So don’t redo firewall stuff. Paste only the output/error from that openclaw infer model run command. That tells us which branch we’re in.

And honestly: if your goal is just “chat with Ollama on a GPU box,” OpenWebUI is simpler. If your goal is OpenClaw as a personal assistant with tools/channels/memory, then yes, this path is more brittle — especially with local models. Not impossible, just annoyingly exacting.

fossil fable
#

no I need agents, security and others to handle tasks. webui on ollama wont do thaat

zinc sorrelBOT
#

Yep, that makes sense. Then OpenClaw is the right class of tool — OpenWebUI won’t replace agents/tools/security.

So let’s stop debating the stack and isolate the exact OpenClaw layer.

The next move is not networking. It’s this one split:

openclaw infer model run --local --model ollama/qwen3:14b --prompt "Reply with exactly: pong" --json

That command uses OpenClaw’s model/provider path but avoids the whole agent/tool/session prompt.

  • If it fails: provider config/auth/model registration is still wrong.
  • If it returns pong: provider is fine, and the bug is in the agent layer — likely stale session model override, old qwen3-vl, context limit, or tool prompt causing Qwen to stall.

Given your setup, I’d bet on agent/session/model override, not Ollama connectivity.

#

After that test, also try in the chat UI/thread:

/model status

If it shows anything other than ollama/qwen3:14b, switch it explicitly:

/model ollama/qwen3:14b
/new

I know this is maddening. You’re not miles away — you’re at the “OpenClaw can reach Ollama, but the active agent turn isn’t using the model/config we think it is” stage.

fossil fable
#

im running the openclaw infer command now but it seems to be just sitting there

zinc sorrelBOT
#

That’s actually useful: infer hanging means we’re below the agent layer now. So it’s not Web UI/session/tools yet — it’s OpenClaw → Ollama/model request.

Let it run maybe 2–3 minutes if Qwen is cold-loading. While it’s hanging, open another SSH tab.

On VPS2:

curl -s http://127.0.0.1:11434/api/ps
sudo journalctl -u ollama -n 80 --no-pager
watch -n1 nvidia-smi

What we need to know:

  • model appears in /api/ps + GPU activity → Qwen is loading/generating slowly
  • no model / no GPU activity → request probably isn’t reaching Ollama correctly
  • Ollama logs show context/truncation/500/OOM → model/runtime config problem
#

If it’s still sitting after ~5 minutes, Ctrl+C it and run the same prompt directly against Ollama from VPS1:

time curl --max-time 180 http://10.121.15.177:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'

If direct curl also hangs, it’s Ollama/Qwen load/runtime. If curl returns but openclaw infer hangs, then we’ve got a real OpenClaw provider issue to pin down.

fossil fable
#

Every 1.0s: nvidia-smi gpu-zjrd: Wed Apr 29 04:17:32 2026

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

zinc sorrelBOT
#

There it is. That’s probably the root cause.

If nvidia-smi can’t talk to the NVIDIA driver on the GPU VPS, Ollama is either:

  • falling back to CPU and taking forever, or
  • failing while trying to load/generate with the model

That would explain openclaw infer just sitting there.

On VPS2, check:

ollama ps
curl -s http://127.0.0.1:11434/api/ps
sudo journalctl -u ollama -n 120 --no-pager
lsmod | grep nvidia
#

But the fix is likely at the VPS/GPU-driver layer, not OpenClaw. Usually one of:

sudo systemctl restart ollama
sudo modprobe nvidia
sudo reboot

If after reboot nvidia-smi still fails, the provider image/driver install is broken — reinstall the NVIDIA driver / CUDA stack from the VPS provider’s docs or rebuild from their GPU image.

For now, prove the diagnosis by testing a tiny model:

openclaw infer model run \
  --local \
  --model ollama/llama3.1:8b \
#
  --prompt "Reply with exactly: pong" \
  --json

If tiny model works but qwen3:14b hangs, it’s almost certainly GPU/VRAM/runtime, not OpenClaw config.

fossil fable
#

Apr 29 04:17:11 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:17:11 | 200 | 269.569124ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:17:11 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:17:11 | 200 | 292.665834ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:17:11 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:17:11 | 200 | 317.486854ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:18:13 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:18:13 | 200 | 88.62µs | 127.0.0.1 | HEAD "/"
Apr 29 04:18:13 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:18:13 | 200 | 57.029µs | 127.0.0.1 | GET "/api/ps"
Apr 29 04:18:13 gpu-zjrd ollama[6296]: [GIN] 2026/04/29 - 04:18:13 | 200 | 76.728µs | 127.0.0.1 | GET "/api/ps"

zinc sorrelBOT
#

Those Ollama logs are telling: I see /api/show and /api/ps, but no /api/chat from the hanging openclaw infer run.

Two problems may be stacked:

  1. GPU driver is brokennvidia-smi failing is not okay for a GPU VPS.
  2. The hanging OpenClaw request may not even be reaching Ollama as a generation call.

Let’s do one sharp test.

On VPS2, run:

sudo journalctl -u ollama -f

Then on VPS1, in another terminal, run:

#
time curl --max-time 180 http://10.121.15.177:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'

If the journal shows /api/chat and then hangs/fails, that’s Ollama/GPU/model runtime.

If curl works but openclaw infer hangs, run:

openclaw logs --follow

while retrying infer — then we need the OpenClaw-side error.

But don’t ignore the driver: if this is meant to be a GPU host, nvidia-smi must work. A reboot is worth trying; if it still fails, the VPS GPU image/driver install is broken and Qwen may be crawling on CPU or not loading properly.

fossil fable
#

le, set OLLAMA_VULKAN=1"
Apr 29 04:19:07 gpu-zjrd ollama[1208]: time=2026-04-29T04:19:07.538Z level=INFO source=types.go:60 msg="inference compute" id=cpu library=cpu compute="" name=cpu description=cpu libdirs=ollama driver="" pci_id="" type="" total="27.4 GiB" available="26.4 GiB"
Apr 29 04:19:07 gpu-zjrd ollama[1208]: time=2026-04-29T04:19:07.538Z level=INFO source=routes.go:1860 msg="vram-based default context" total_vram="0 B" default_num_ctx=4096
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 8.802937ms | 127.0.0.1 | GET "/api/tags"
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 263.082277ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 274.084069ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 290.134058ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 304.814807ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:19:39 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:39 | 200 | 315.129267ms | 127.0.0.1 | POST "/api/show"
Apr 29 04:19:40 gpu-zjrd ollama[1208]: [GIN] 2026/04/29 - 04:19:40 | 200 | 353.595232ms | 127.0.0.1 | POST "/api/show"

zinc sorrelBOT
#

Yep — that confirms the big issue:

inference compute id=cpu library=cpu
total_vram="0 B"
default_num_ctx=4096

Ollama is not using the GPU at all. It sees zero VRAM and is running CPU-only. That’s why Qwen is hanging/crawling, and why OpenClaw startup/model probing feels awful.

This is no longer primarily an OpenClaw connection problem. OpenClaw is reaching Ollama enough to do /api/tags and /api/show; Ollama itself has no working GPU backend.

Immediate path:

  1. Fix GPU on VPS2 until this works:
#
nvidia-smi
  1. Restart Ollama after the driver works:
sudo systemctl restart ollama
sudo journalctl -u ollama -n 80 --no-pager

You want logs to show CUDA/GPU compute, not id=cpu, and nonzero VRAM.

  1. Until GPU is fixed, use a tiny CPU-friendly model only for testing:
#
openclaw infer model run \
  --local \
  --model ollama/llama3.1:8b \
  --prompt "Reply with exactly: pong" \
  --json

But for qwen3:14b as an agent model: CPU-only + 4096 ctx is going to be miserable or unusable.

If nvidia-smi keeps failing after reboot, I’d stop debugging OpenClaw and fix/rebuild the GPU VPS image first. The smoking gun is total_vram="0 B".

fossil fable
#

time curl --max-time 180 http://10.121.15.177:11434/api/chat
-H 'Content-Type: application/json'
-d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'
curl: (7) Failed to connect to 10.121.15.177 port 11434 after 14330 ms: Couldn't connect to server

real 0m14.374s
user 0m0.038s
sys 0m0.049s

zinc sorrelBOT
#

Now we have a very concrete failure:

VPS1 cannot connect to 10.121.15.177:11434

So right now OpenClaw is irrelevant — the ZeroTier Ollama port is not reachable.

On VPS2, run:

sudo ss -ltnp | grep 11434
sudo systemctl status ollama --no-pager
sudo ufw status verbose

If ss shows only this:

#
127.0.0.1:11434

then Ollama is only listening locally. Fix it with a systemd override:

sudo systemctl edit ollama

Add:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
#

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ufw allow from 10.121.15.22 to any port 11434 proto tcp
sudo ss -ltnp | grep 11434

You want to see 0.0.0.0:11434 or *:11434, not just 127.0.0.1:11434.

Then from VPS1:

curl http://10.121.15.177:11434/api/tags
#

Separate issue: your GPU is also broken (nvidia-smi fails / Ollama says CPU + total_vram=0 B), but first we need the port reachable again.

fossil fable
#

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

zinc sorrelBOT
#

Yep. That’s the hard blocker for Qwen performance.

But keep the two issues separate:

1) Connectivity is currently broken

Your last VPS1 curl to 10.121.15.177:11434 failed. Fix/listen/firewall first:

sudo ss -ltnp | grep 11434
sudo ufw status verbose

If Ollama is only on 127.0.0.1:11434, set OLLAMA_HOST=0.0.0.0:11434 in the Ollama systemd service and restart it.

2) GPU is also broken

nvidia-smi failing + Ollama saying inference compute id=cpu means the GPU VPS is not actually GPU-capable right now.

#

Try the quick recovery:

sudo reboot

After reconnect:

nvidia-smi
sudo systemctl restart ollama
sudo journalctl -u ollama -n 80 --no-pager

If nvidia-smi still fails after reboot, this is a VPS/provider image/driver problem. Rebuild from the provider’s GPU image or reinstall their recommended NVIDIA driver stack. OpenClaw cannot make qwen3:14b usable while Ollama sees total_vram=0 B.

So the honest priority order is:

#
  1. restore 10.121.15.177:11434 reachability from VPS1
  2. fix NVIDIA driver until nvidia-smi works
  3. then retest openclaw infer / chat agent
fossil fable
#

GGML_VK_VISIBLE_DEVICES: GPU_DEVICE_ORDINAL: HIP_VISIBLE_DEVICES: HSA_OVERRIDE_GFX_VERSION: HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_CONTEXT_LENGTH:0 OLLAMA_DEBUG:INFO OLLAMA_DEBUG_LOG_REQUESTS:false OLLAMA_EDITOR: OLLAMA_FLASH_ATTENTION:false OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://0.0.0.0:11434 OLLAMA_KEEP_ALIVE:5m0s OLLAMA_KV_CACHE_TYPE: OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:0 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:/usr/share/ollama/.ollama/models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NEW_ENGINE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NO_CLOUD:false OLLAMA_NUM_PARALLEL:1 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://* vscode-file://*] OLLAMA_REMOTES:[ollama.com] OLLAMA_SCHED_SPREAD:false OLLAMA_VULKAN:false ROCR_VISIBLE_DEVICES: http_proxy: https_proxy: no_proxy:]"
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.696Z level=INFO source=routes.go:1754 msg="Ollama cloud disabled: false"
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.699Z level=INFO source=images.go:517 msg="total blobs: 26"
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.700Z level=INFO source=images.go:524 msg="total unused blobs removed: 0"
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.701Z level=INFO source=routes.go:1810 msg="Listening on [::]:11434 (version 0.21.2)"
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.703Z level=INFO source=runner.go:67 msg="discovering available GPUs..."
Apr 29 04:23:15 gpu-zjrd ollama[2472]: time=2026-04-29T04:23:15.704Z level=INFO source=server.go:444 m

zinc sorrelBOT
#

Good — this part is now fixed:

Listening on [::]:11434

So Ollama is listening externally again. Now verify from VPS1:

curl --max-time 10 http://10.121.15.177:11434/api/tags

If that works, the remaining blocker is the GPU. Your log stops right at:

discovering available GPUs...
#

We need the next few lines after that. Run on VPS2:

sudo journalctl -u ollama -n 120 --no-pager | grep -Ei 'gpu|cuda|nvidia|cpu|vram|inference|error'

Right now nvidia-smi still failing means Ollama probably lands on CPU again. If the log says inference compute id=cpu / total_vram="0 B", Qwen will keep crawling/hanging.

After VPS1 can curl /api/tags, test a known tiny generation before OpenClaw:

curl --max-time 180 http://10.121.15.177:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"llama3.1:8b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":2048}}'

If even that is slow/fails, fix NVIDIA first. If it returns, then try qwen3:14b.

fossil fable
#

i have submitted a ticket to the Databasamart support regarding the GPU. I am not sure when they will get back. their dumbass ai support gave me some stupid answers

zinc sorrelBOT
#

Yeah, that’s frustrating as hell — but opening a provider ticket is the right move now.

For Databasemart, give them the concrete evidence, not the OpenClaw story:

nvidia-smi fails:
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.

Ollama detects CPU only:
inference compute id=cpu library=cpu
total_vram="0 B"
default_num_ctx=4096

Expected: NVIDIA GPU visible to the VM/container and usable by Ollama/CUDA.

Ask them specifically:

#

Please verify the GPU is attached to this VPS, the NVIDIA kernel driver is loaded, and CUDA/NVML works. nvidia-smi currently cannot communicate with the driver.

Until they fix that, don’t burn more time trying to make qwen3:14b behave — OpenClaw is reaching the Ollama API, but Ollama has no working GPU backend.

Practical fallback meanwhile:

  • use llama3.1:8b only as a temporary CPU test model, or
  • point OpenClaw at a cloud model for actual agent work until the GPU host is fixed

You weren’t crazy. The setup had multiple issues, but the current blocker is clearly the GPU VPS.

fossil fable
#

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 560.31.02 Driver Version: 560.31.02 CUDA Version: 12.6 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA RTX A4000 Off | 00000000:01:00.0 Off | Off |
| 30% 43C P0 35W / 140W | 1MiB / 16376MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+

zinc sorrelBOT
#

Excellent — that’s the first genuinely good sign. GPU is visible now: RTX A4000, 16GB VRAM. 🎯

Now restart Ollama so it re-detects CUDA:

sudo systemctl restart ollama
sudo journalctl -u ollama -n 100 --no-pager | grep -Ei 'gpu|cuda|nvidia|cpu|vram|inference'

You want to see GPU/CUDA, not id=cpu / total_vram="0 B".

Then from VPS1 test generation directly:

curl --max-time 180 http://10.121.15.177:11434/api/chat \
  -H 'Content-Type: application/json' \
#
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'

While that runs, nvidia-smi should show an Ollama/runner process using VRAM.

If direct curl works, then retry OpenClaw:

openclaw infer model run \
  --local \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
  --json

We’re finally back to the actual OpenClaw test path.

fossil fable
#

127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://* vscode-file://*] OLLAMA_REMOTES:[ollama.com] OLLAMA_SCHED_SPREAD:false OLLAMA_VULKAN:false ROCR_VISIBLE_DEVICES: http_proxy: https_proxy: no_proxy:]"
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.644Z level=INFO source=routes.go:1754 msg="Ollama cloud disabled: false"
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.649Z level=INFO source=images.go:517 msg="total blobs: 26"
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.650Z level=INFO source=images.go:524 msg="total unused blobs removed: 0"
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.651Z level=INFO source=routes.go:1810 msg="Listening on [::]:11434 (version 0.21.2)"
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.652Z level=INFO source=runner.go:67 msg="discovering available GPUs..."
Apr 29 11:14:19 gpu-zjrd ollama[53659]: time=2026-04-29T11:14:19.653Z level=INFO source=server.go:444 msg="starting runner" cmd="/usr/local/bin/ollama runner --ollama-engine --port 40165"

zinc sorrelBOT
#

That looks much healthier. The important difference is:

starting runner

Now check whether that runner is actually using the GPU.

On VPS2:

nvidia-smi

If you see an ollama / ollama runner process using VRAM, good.

Then from VPS1 run the direct chat again:

#
curl --max-time 180 http://10.121.15.177:11434/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'

If it still hangs, tail the next Ollama lines:

sudo journalctl -u ollama -n 120 --no-pager | grep -Ei 'cuda|gpu|vram|runner|loaded|memory|offload|error|cpu'

We need to see whether it says GPU/CUDA/offload, or falls back to CPU.

fossil fable
#

-H 'Content-Type: application/json'
-d '{"model":"qwen3:14b","messages":[{"role":"user","content":"Reply with exactly: pong"}],"stream":false,"options":{"num_ctx":4096}}'
{"model":"qwen3:14b","created_at":"2026-04-29T11:16:02.997693364Z","message":{"role":"assistant","content":"pong","thinking":"Okay, the user wants me to reply with exactly "pong". Let me check the instructions again. They said to reply with exactly that word. No extra text, no explanations. Just "pong". I need to make sure there's no typo. Let me type it out. P-O-N-G. Yep, that's correct. Alright, that's all I need to do here.\n"},"done":true,"done_reason":"stop","total_duration":17198741860,"load_duration":14756536919,"prompt_eval_count":15,"prompt_eval_duration":162381276,"eval_count":84,"eval_duration":2145711168}

zinc sorrelBOT
#

YES. That means the hard bits are now working:

  • VPS1 can reach VPS2 over ZeroTier ✅
  • Ollama native /api/chat works ✅
  • qwen3:14b loads and generates ✅
  • first load took ~14.7s, total ~17.2s — normal after cold start ✅

Now run the OpenClaw-side test again:

openclaw infer model run \
  --local \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
  --json
#

If that works, switch/restart the agent side:

openclaw config set agents.defaults.model '{"primary":"ollama/qwen3:14b"}' --strict-json
openclaw gateway restart
openclaw models status

Then in the chat/UI:

/model ollama/qwen3:14b
/new

One config tweak I’d make now: since Qwen returns a thinking field, keep this in the model params if it isn’t already:

#
params: {
  num_ctx: 4096,
  keep_alive: "15m",
  thinking: false
}

That’ll reduce weird verbose thinking behavior and keep the model warm between turns.

fossil fable
#

still waiting for this to run - openclaw infer model run
--local
--model ollama/qwen3:14b
--prompt "Reply with exactly: pong"
--json

zinc sorrelBOT
#

Don’t wait forever — since direct curl returned in ~17s, this should not sit for minutes.

Hit Ctrl+C on that --local run. Then run the more relevant test for your actual setup, the Gateway path:

timeout 180s openclaw infer model run \
  --gateway \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
  --json

While that runs, tail Ollama on VPS2:

sudo journalctl -u ollama -f
#

Key thing:

  • if VPS2 shows POST /api/chat → OpenClaw reached Ollama; wait/check GPU/load
  • if VPS2 shows only /api/tags or /api/show, or nothing → OpenClaw is stuck before generation, likely config/model discovery/auth
  • if --gateway works but --local hangs → ignore --local for now; your real assistant uses gateway routing anyway

If --gateway also hangs, run this with debug and paste the last ~40 lines:

OPENCLAW_LOG_LEVEL=debug OPENCLAW_DEBUG_TIMING=1 timeout 180s openclaw infer model run \
  --gateway \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
  --json

We finally have Ollama itself working, so now we’re narrowing the OpenClaw side.

fossil fable
#

--gateway
--model ollama/qwen3:14b
--prompt "Reply with exactly: pong"
--json
Error: gateway closed (1006 abnormal closure (no close frame)): no close reason
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /root/.openclaw/openclaw.json
Bind: lan

Possible causes:

  • Gateway not yet ready to accept connections (retry after a moment)
  • TLS mismatch (connecting with ws:// to a wss:// gateway, or vice versa)
  • Gateway crashed or was terminated unexpectedly
    Run openclaw doctor for diagnostics.
zinc sorrelBOT
#

Good, new failure and it’s specific:

gateway closed (1006 abnormal closure)
Gateway target: ws://127.0.0.1:18789
Config: /root/.openclaw/openclaw.json

That means the request is not reaching Ollama yet. The local OpenClaw Gateway is closing/crashing/refusing the websocket.

On VPS1, run these now:

openclaw gateway status
openclaw health --verbose
openclaw status --all
#

Then immediately grab the crash/log tail:

openclaw logs --tail 200

If that command doesn’t work:

tail -n 200 "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"

The key thing I want to see is the gateway log at the exact time of the 1006.

Also note the config path is /root/.openclaw/openclaw.json. If the gateway service is running as a different Linux user than the shell you’re testing from, it may be using a different config. openclaw gateway status should expose that.

fossil fable
#

the gateway wasnt running when I ran that test though

zinc sorrelBOT
#

Ah — perfect, then that 1006 is explained. Not a model failure, just no running gateway.

Start the gateway, then rerun the gateway probe:

openclaw gateway start
openclaw gateway status

Once it says reachable/healthy:

timeout 180s openclaw infer model run \
  --gateway \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
#
  --json

Keep the direct curl result in mind: Ollama/Qwen itself is working now. We’re just validating OpenClaw’s gateway route.

If you’re running the gateway in foreground with openclaw gateway, leave that terminal open and use a second SSH tab for openclaw infer.

fossil fable
#

--gateway
--model ollama/qwen3:14b
--prompt "Reply with exactly: pong"
--json
Error: gateway timeout after 120000ms
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /root/.openclaw/openclaw.json
Bind: lan

#

but on the main gateway window a pong appeared

zinc sorrelBOT
#

Okay — now the Gateway is up, but the Gateway model probe is hanging for the full 120s.

Since direct Ollama curl returns in ~17s, this is now OpenClaw Gateway path, not GPU/Ollama/network.

First: make sure the previous hanging --local infer is stopped. Ctrl+C it if it’s still alive.

Then run this with both logs visible:

Terminal A on VPS2:

sudo journalctl -u ollama -f

Terminal B on VPS1:

#
openclaw logs --follow

Terminal C on VPS1:

openclaw infer model run \
  --gateway \
  --model ollama/qwen3:14b \
  --prompt "Reply with exactly: pong" \
  --timeout-ms 300000 \
  --json

What matters:

#
  • If Ollama shows POST /api/chat, Gateway reached Ollama and we’re waiting on model/provider response.
  • If Ollama shows only /api/tags / /api/show, Gateway is stuck in discovery/config before generation.
  • If Ollama shows nothing, Gateway is not using the provider/baseUrl we think it is.

Also paste this:

openclaw config get models.providers.ollama --json
openclaw config get agents.defaults.model --json

We’re close now. Direct Ollama works; the remaining bug is Gateway routing/config/runtime.

fossil fable
#

Apr 29 11:36:59 gpu-zjrd ollama[53659]: time=2026-04-29T11:36:59.015Z level=INFO source=sched.go:561 msg="loaded runners" count=1
Apr 29 11:36:59 gpu-zjrd ollama[53659]: time=2026-04-29T11:36:59.016Z level=INFO source=server.go:1364 msg="waiting for llama runner to start responding"
Apr 29 11:36:59 gpu-zjrd ollama[53659]: time=2026-04-29T11:36:59.016Z level=INFO source=server.go:1398 msg="waiting for server to become available" status="llm server loading model"
Apr 29 11:37:08 gpu-zjrd ollama[53659]: time=2026-04-29T11:37:08.072Z level=INFO source=server.go:1402 msg="llama runner started in 11.83 seconds"
Apr 29 11:37:08 gpu-zjrd ollama[53659]: time=2026-04-29T11:37:08.212Z level=WARN source=runner.go:187 msg="truncating input prompt" limit=4096 prompt=6006 keep=4 new=4096
Apr 29 11:37:11 gpu-zjrd ollama[53659]: [GIN] 2026/04/29 - 11:37:11 | 200 | 17.463571028s | 10.121.15.22 | POST "/api/chat"
Apr 29 11:37:13 gpu-zjrd ollama[53659]: [GIN] 2026/04/29 - 11:37:13 | 200 | 2.008243102s | 10.121.15.22 | POST "/api/chat"

zinc sorrelBOT
#

Ah! That changes it: the Gateway did complete the model call, but the CLI client timed out waiting for the response/route back.

So model/provider path is working now. ✅

That means the “pong” in the gateway window is the success signal we needed. The remaining issue is likely just the CLI websocket request timing/response plumbing, not Ollama.

Next step: try the real agent/chat path, but keep it tiny:

/model ollama/qwen3:14b
/new
Say exactly pong.

If the UI/chat replies, you’re basically through.

For config, I’d still set/keep:

#
params: {
  num_ctx: 4096,
  keep_alive: "15m",
  thinking: false
}

And for heavier agent use, consider enabling lean mode:

openclaw config set agents.defaults.experimental.localModelLean true --strict-json
openclaw gateway restart

That reduces the tool/prompt burden for local models. Qwen can work, but local models are much more sensitive to huge tool schemas than cloud models.

#

This is the cleanest evidence yet:

10.121.15.22 | POST "/api/chat" | 200
truncating input prompt limit=4096 prompt=6006

So:

  • OpenClaw Gateway is reaching Ollama
  • Ollama is generating successfully
  • The issue is now context size / prompt size, not connectivity

Your configured runtime num_ctx is 4096, but even the lean probe sent ~6006 tokens, so Ollama truncated. For the full agent, it’ll be worse.

Set Ollama runtime context higher, but keep OpenClaw’s contextWindow at least 16000:

#
openclaw config set models.providers.ollama.models '[{
  "id": "qwen3:14b",
  "name": "qwen3:14b",
  "contextWindow": 16000,
  "maxTokens": 4096,
  "params": {
    "num_ctx": 16000,
    "keep_alive": "15m",
    "thinking": false
  }
}]' --strict-json --replace

openclaw config set agents.defaults.experimental.localModelLean true --strict-json
openclaw config validate
openclaw gateway restart
#

Then retry the chat with:

/model ollama/qwen3:14b
/new
Say exactly pong.

If 16k is too much for the RTX A4000, drop params.num_ctx to 8192, but expect some truncation on real agent turns. The big breakthrough is: the pipes work now. We’re tuning context/tool load.

fossil fable
#

the gateway crashed with that pong that came ethrough and I didnt realise it. i was waiting for ages lol. just restarted gateway

zinc sorrelBOT
#

Ahhh, okay — that explains the “CLI waited forever but pong appeared” weirdness. The model call worked, then the Gateway died before the client got a clean response.

Don’t change more config yet. First grab the crash evidence right after restart:

openclaw gateway status
openclaw logs --tail 300

If logs are empty/not enough:

tail -n 300 "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"

If you installed it as a service, also try:

#
journalctl --user -u openclaw-gateway -n 200 --no-pager

What we’re looking for is the exception/OOM/stack trace right after the pong. The Ollama side is finally proven working; now we need the Gateway crash reason. Also keep localModelLean on — the prompt=6006 limit=4096 truncation means we need to keep the agent prompt lighter or raise num_ctx.

fossil fable
#

i gpot a pong reply in the ui

zinc sorrelBOT
#

YES. That’s the milestone. 🎉

That means:

  • ZeroTier path works
  • Ollama native API works
  • GPU is fixed enough for Qwen
  • OpenClaw Gateway can route to ollama/qwen3:14b
  • UI chat can get a reply

Now I’d stop making big changes and just stabilize:

openclaw config validate
openclaw gateway status
#

If those are clean, test one slightly more realistic prompt:

In one sentence, tell me what tools you can use.

If it behaves, you’re functionally working.

Keep an eye on two things:

  1. Context truncation — earlier Ollama logged limit=4096 prompt=6006, so use num_ctx: 8192 or 16000 if the A4000 handles it.
  2. Gateway crash — if it happens again, grab openclaw logs --tail 300 immediately.

But seriously: pong in the UI means the core setup is finally alive. 🦐

fossil fable
#

Failed to set model: GatewayRequestError: model not allowed: ollama/qwen3:14b
/new
pong

zinc sorrelBOT
#

That error is actually straightforward now:

model not allowed: ollama/qwen3:14b

It means agents.defaults.models is acting as a model allowlist, and ollama/qwen3:14b is not in that allowlist yet. The provider works; the picker/session override is blocked.

Run this on VPS1:

openclaw config set agents.defaults.models '{
  "ollama/qwen3:14b": {
    "alias": "Qwen3 14B"
  }
}' --strict-json --merge
#

openclaw config set agents.defaults.model '{"primary":"ollama/qwen3:14b"}' --strict-json

openclaw config validate
openclaw gateway restart

Then in UI/chat:

/model ollama/qwen3:14b
/new
Say exactly pong.

The /new pong you saw means something is answering, but the failed /model means the explicit session switch was rejected. Adding it to agents.defaults.models should fix that.

fossil fable
#

the /new request just has wavy dots

zinc sorrelBOT
#

That means the UI has an active run in-flight. Don’t stack more messages yet.

In the UI/chat, send:

/stop

Then:

/status

If it clears, do:

#
/think off
/model ollama/qwen3:14b
/new
Say exactly pong.

If /stop also just spins, check VPS1 logs immediately:

openclaw logs --tail 300
openclaw gateway status

And on VPS2, see whether Ollama is actually receiving the request:

#
sudo journalctl -u ollama -n 80 --no-pager | grep '/api/chat'

My read: we’re no longer blocked on connectivity. This is either a stuck previous run/session state, or Qwen taking a big agent prompt. /stop first — clear the lane before testing anything else.

fossil fable
#

the /stop isnt doing anthing

zinc sorrelBOT
#

If /stop doesn’t respond, the run/gateway lane is wedged. Use the CLI side now.

On VPS1:

openclaw gateway restart

Then check for stuck task records:

openclaw tasks list --status running

If it lists a task id/run id, cancel it:

#
openclaw tasks cancel <id>

Then keep the first post-restart test very small:

/status

If /status responds, then:

/model status

Don’t send /new yet until /status proves the gateway is responsive.

#

If restart hangs or /status still gives wavy dots, grab:

openclaw gateway status
openclaw logs --tail 300
fossil fable
#

ok hang five. it just stopped and said Agent failed before reply: This operation was aborted | This operation was aborted.
Logs: openclaw logs --follow

zinc sorrelBOT
#

Good — /stop finally landed. That message is expected after aborting a wedged run:

Agent failed before reply: This operation was aborted

Now don’t restart again yet. Check the session is responsive:

/status

If /status responds, do:

/model status
#

Then, before another /new, make sure the allowlist/default are clean:

openclaw config get agents.defaults.model --json
openclaw config get agents.defaults.models --json
openclaw config get models.providers.ollama --json

For the next real test, use a plain message, not /new first:

Say exactly pong.

If it hangs again, tail logs during the run:

#
openclaw logs --follow

At this point abort worked, Ollama works, and the UI can receive replies. We’re down to tuning/stuck-run behavior rather than the original connection mess.

fossil fable
#

🦞 OpenClaw 2026.4.26 (be8c246)
🧠 Model: ollama/qwen3:14b · 🔑 api-key (models.json)
📚 Context: 0/16k (0%) · 🧹 Compactions: 0
🧵 Session: agent:main:main • updated just now
📌 Tasks: 1 active · 1 total · cli · [System] Your previous turn was interrupted by a gateway restart while OpenClaw…
⚙️ Execution: direct · Runtime: OpenClaw Pi Default · Think: off
🪢 Queue: collect (depth 0)

zinc sorrelBOT
#

That status is mostly good:

  • model is correctly ollama/qwen3:14b
  • context is 16k
  • thinking is off
  • session is alive

The one red flag is:

Tasks: 1 active · cli · previous turn was interrupted by a gateway restart

Clear that stale CLI task:

#
openclaw tasks list --status running
openclaw tasks cancel <id-from-list>

If it won’t cancel or looks stale:

openclaw tasks maintenance --apply

Then check:

/status
#

You want Tasks: 0 active.

After that, send only:

Say exactly pong.

No /new until the stale task is gone. That active interrupted CLI task may be what’s making the UI feel stuck.

fossil fable
#

Background tasks: 1
Task pressure: 0 queued · 1 running · 0 issues
Status filter: running
Task Kind Status Delivery Run Child Session Summary
2ce3c097-… cli running not_applicable ce589250-… agent:main:main [Tue 2026-04-28 14:29 UTC] [System] Your previous turn was interrupted by a gat…

zinc sorrelBOT
#

Yep, that’s stale — it’s from Tuesday 2026-04-28 14:29 UTC, not current work.

Cancel it by task id prefix:

openclaw tasks cancel 2ce3c097

Then verify:

openclaw tasks list --status running

If it still shows as running, apply maintenance:

#
openclaw tasks maintenance --apply
openclaw tasks list --status running

Once that’s gone, /status should show Tasks: 0 active, then test:

Say exactly pong.
fossil fable
#

Task not found: 2ce3c097

zinc sorrelBOT
#

Use the run id instead — the task-id prefix may be too short/ambiguous in that CLI path.

From your table:

Run ce589250-…

Try:

openclaw tasks cancel ce589250

If that also says not found, get JSON so we can copy the exact full id:

#
openclaw tasks list --status running --json

Then cancel using the full "taskId" or "runId" value from the JSON.

If it’s a stale ledger entry and cancel won’t find it, run:

openclaw tasks maintenance --apply
openclaw tasks list --status running
fossil fable
#

table?

zinc sorrelBOT
#

The “table” is the output you pasted from:

openclaw tasks list --status running

This line:

2ce3c097-… cli running ... ce589250-… agent:main:main ...

Because Discord shortened it with , we don’t have the full ID. Get the unshortened version with JSON:

openclaw tasks list --status running --json
#

Then paste that output, or cancel using the full value shown for taskId or runId.

fossil fable
#

{
"count": 0,
"runtime": null,
"status": "running",
"tasks": []
}

zinc sorrelBOT
#

Great — the stale running task is gone now.

Run /status once more in the UI. If it shows Tasks: 0 active, test with a normal message:

Say exactly pong.

If that works, you’re stable enough to move on to real tasks.

If it still spins, grab logs during that exact message:

openclaw logs --follow

But the task ledger is clean now, model is selected, and Ollama/GPU path is proven.

fossil fable
#

{
"count": 0,
"runtime": null,
"status": "running",
"tasks": []
}

zinc sorrelBOT
#

Yep, that confirms it: no running tasks.

Now do the simplest UI test:

/status

Then:

Say exactly pong.

If it hangs again despite tasks: [], the next thing to inspect is live logs while sending that message:

#
openclaw logs --follow

But from the task side, it’s clean.

fossil fable
#

sorry wrong paste

#

OpenClaw 2026.4.26 (be8c246)
🧠 Model: ollama/qwen3:14b · 🔑 api-key (models.json)
🧮 Tokens: 4.1k in / 6 out · 💵 Cost: $0.0000
📚 Context: 4.1k/16k (26%) · 🧹 Compactions: 1
🧵 Session: agent:main:main • updated just now
📌 Tasks: 1 active · 1 total · cli · [System] Your previous turn was interrupted by a gateway restart while OpenClaw…
⚙️ Execution: direct · Runtime: OpenClaw Pi Default · Think: off
🪢 Queue: collect (depth 0)

zinc sorrelBOT
#

No worries. Paste the /status output when you have it — or if the UI is responsive, just try:

Say exactly pong.

We’ve cleared the stale task, so this is the clean test now.

#

Interesting — CLI says no running tasks, but /status still reports 1 active. That smells like a stale in-memory/session status, not the task ledger.

Try a gateway restart once, now that the task ledger is clean:

openclaw gateway restart

Then wait ~10 seconds and run:

/status

If it still shows the same old interrupted CLI task after restart, run:

#
openclaw tasks audit
openclaw tasks maintenance --apply
openclaw tasks list --json

But the actual model stats are good: it did 4.1k in / 6 out, model is correct, and thinking is off. The stale “active task” is the remaining cleanup weirdness.

fossil fable
#

isnt there still a task active previously interrupted?

zinc sorrelBOT
#

Yes — /status is still reporting one active interrupted CLI task:

Tasks: 1 active · cli · previous turn was interrupted by a gateway restart

But openclaw tasks list --status running --json showed:

"count": 0,
"tasks": []

So there’s a mismatch: the durable task ledger says no running tasks, while the session/status view still has stale “active task” metadata.

Do this cleanup sequence:

#
openclaw tasks audit
openclaw tasks maintenance --apply
openclaw gateway restart

Then run /status again.

If it still says 1 active, it’s likely stale session metadata rather than an actually running task. In that case, start a truly fresh session after restart:

/new
/status

But don’t worry about Ollama connectivity anymore — the model is working. This is cleanup/session state now.

fossil fable
#

12:59:49 [agent/embedded] low context window: ollama/qwen3:14b ctx=16000 (warn<32000) source=modelsConfig

zinc sorrelBOT
#

That one is only a warning, not a failure.

low context window: ctx=16000 (warn<32000)

OpenClaw warns below 32k, but it only blocks below 16k. So 16000 is acceptable — especially for an RTX A4000 where 32k may be too heavy.

For now I’d leave it at 16k until the setup is stable. The active interrupted task/session metadata is the thing to clean up, not this warning.

Run:

openclaw tasks audit
openclaw tasks maintenance --apply
openclaw gateway restart
#

Then check:

/status

If /status still says Tasks: 1 active while openclaw tasks list --status running --json says 0, then it’s stale session status, not a real running task.

fossil fable
#

ok it finally responded to the say exactly pong statement by a NO

zinc sorrelBOT
#

Weird answer, but weirdly good news: it did respond. So the path is alive.

The NO likely came from stale/interrupted context or Qwen being Qwen under agent instructions — not a connection failure.

Do one clean reset now:

/new

Then after it completes:

Ignore previous conversation. Reply with exactly the single word: pong

If it still says anything other than pong, check whether Qwen’s thinking/tool behavior is leaking. Keep:

#
"params": {
  "num_ctx": 16000,
  "keep_alive": "15m",
  "thinking": false
}

But honestly, responding “NO” means we’re past the infrastructure battle. Now it’s model behavior / prompt tuning.

fossil fable
#

i got this at the top which is a first. - I need to read and follow the BOOTSTRAP.md file to complete the setup for this workspace. Please provide me with the contents of the BOOTSTRAP.md file so I can proceed with the necessary steps.

zinc sorrelBOT
#

That explains the “NO” and weird behavior. The agent thinks it is in first-run bootstrap mode.

Normally OpenClaw seeds BOOTSTRAP.md, runs the setup ritual, then removes BOOTSTRAP.md. If that file is still present/stale, the agent can keep trying to bootstrap instead of answering normally.

On VPS1, check the workspace:

openclaw config get agents.defaults.workspace
find ~/.openclaw -name BOOTSTRAP.md -print

If you see one under the active workspace, move it aside:

mv ~/.openclaw/workspace/BOOTSTRAP.md ~/.openclaw/workspace/BOOTSTRAP.md.done
#

If your workspace path is different, use that path instead.

Then:

openclaw config set agents.defaults.skipBootstrap true --strict-json
openclaw gateway restart

After restart, in UI:

/new
/status
Say exactly pong.
#

This is a known pattern: stale BOOTSTRAP.md can keep an agent in bootstrapping mode. Once it’s moved aside, the model should stop asking you to provide bootstrap contents.

fossil fable
#

Config path not found: agents.defaults.workspace
/root/.openclaw/workspace/BOOTSTRAP.md

zinc sorrelBOT
#

Yep, there’s the culprit:

/root/.openclaw/workspace/BOOTSTRAP.md

Move it aside:

mv /root/.openclaw/workspace/BOOTSTRAP.md /root/.openclaw/workspace/BOOTSTRAP.md.done

Then prevent it being recreated:

openclaw config set agents.defaults.skipBootstrap true --strict-json
#
openclaw config validate
openclaw gateway restart

Then in UI:

/new
/status
Say exactly pong.

The missing agents.defaults.workspace just means you’re using the default workspace path, which is /root/.openclaw/workspace in your current root-run setup.

fossil fable
#

75% of my time is spent waiting for these prompts to return. I hope it gets better than this

#

ps it still popped up with the bootstrap message even after the /new

zinc sorrelBOT
#

Yeah, that’s a completely fair complaint. This should not feel like watching paint dry.

Some of today’s wait was because we had stacked blockers — GPU driver broken, Ollama CPU fallback, stale task, stale BOOTSTRAP.md, context truncation — but even after fixing those, local 14B agent turns can still be slow.

To make it less painful:

openclaw config set agents.defaults.experimental.localModelLean true --strict-json
openclaw config set agents.defaults.contextInjection "continuation-skip"
openclaw config validate
openclaw gateway restart

And keep Ollama warm:

#
params: {
  num_ctx: 8192,      // or 16000 if stable
  keep_alive: "15m",
  thinking: false
}

Also for sanity: use cloud models for setup/debugging, and local Qwen for lower-risk/private work once the system is stable. Local models are workable, but they’re much less forgiving with full agent prompts/tools.

You’re not wrong to expect better. We did uncover real setup issues, not user error.

fossil fable
#

and now it has queued the status message

zinc sorrelBOT
#

Then either BOOTSTRAP.md still exists, or the gateway restarted before seeing the moved file/config.

Run this exact check on VPS1:

find /root/.openclaw -name BOOTSTRAP.md -print
openclaw config get agents.defaults.skipBootstrap --json

If it prints any BOOTSTRAP.md, move/delete it:

find /root/.openclaw -name BOOTSTRAP.md -exec mv {} {}.done \;

Then force the config again:

#
openclaw config set agents.defaults.skipBootstrap true --strict-json
openclaw config set agents.defaults.contextInjection "continuation-skip"
openclaw config validate
openclaw gateway restart

After restart, verify:

find /root/.openclaw -name BOOTSTRAP.md -print

It should print nothing.

Then in UI, avoid /new once and just send:

#
Say exactly pong.

If it still mentions bootstrap with no BOOTSTRAP.md on disk, that’s stale session/context and we’ll need to clear that session specifically.

#

Yeah, if even /status is queued, the current lane/session is wedged again. Stop trying UI commands for a minute and reset from CLI.

On VPS1:

openclaw gateway restart
openclaw gateway status
openclaw tasks list --status running --json
find /root/.openclaw -name BOOTSTRAP.md -print

If any BOOTSTRAP.md appears:

find /root/.openclaw -name BOOTSTRAP.md -exec mv {} {}.done \;
#

Then:

openclaw config set agents.defaults.skipBootstrap true --strict-json
openclaw config set agents.defaults.contextInjection "continuation-skip"
openclaw config validate
openclaw gateway restart

After that, open a fresh UI tab/window if you can. The old Control UI tab may still have queued websocket state.

Then first message should be only:

/status
#

If /status queues immediately after a fresh gateway + fresh UI, paste:

openclaw gateway status
openclaw logs --tail 300
fossil fable
#

it said true

zinc sorrelBOT
#

Good — I’m assuming that was:

openclaw config get agents.defaults.skipBootstrap --json

returning:

true

So config is correct. Now the key check is whether any bootstrap file still exists:

find /root/.openclaw -name BOOTSTRAP.md -print
#

If it prints nothing, restart and use a fresh UI tab:

openclaw gateway restart

Then try only:

/status

If /status queues again, this is no longer bootstrap config — it’s gateway/session wedging. Then paste:

openclaw gateway status
#
openclaw logs --tail 300
fossil fable
#

find: ‘/root/.openclaw/plugin-runtime-deps/openclaw-2026.4.26-4eca5026e977/.openclaw-runtime-mirror.lock’: No such file or directory

zinc sorrelBOT
#

That find error is just a race while scanning plugin-runtime-deps — OpenClaw is changing that directory while find walks it. Not the bootstrap file.

Use a narrower find that avoids runtime deps:

find /root/.openclaw/workspace /root/.openclaw/agents -name BOOTSTRAP.md -print 2>/dev/null

If it prints a path, move it:

find /root/.openclaw/workspace /root/.openclaw/agents -name BOOTSTRAP.md -exec mv {} {}.done \; 2>/dev/null

Then:

#
openclaw gateway restart

Also, that plugin-runtime-deps path reminds me: if you keep seeing weird plugin/runtime churn on 2026.4.26, run:

openclaw doctor

But first confirm BOOTSTRAP.md is gone from workspace/agents.

fossil fable
#

printed nothing

zinc sorrelBOT
#

Great — then BOOTSTRAP.md is gone and skipBootstrap=true.

If the bootstrap text still appears now, it’s stale session/context, not a file on disk.

Do this:

openclaw gateway restart

Then open a fresh UI tab/window and send:

/status

If it’s responsive and no bootstrap mention, send:

#
Say exactly pong.

If it still shows bootstrap after no BOOTSTRAP.md, we need to clear the specific session state. First check available session commands:

openclaw sessions list

Paste that if bootstrap persists.

plain fableBOT
pastel lintel
#

@zinc sorrel please sum up the answer to the questions initial message and the conversation briefly. This thread will be closed soon.

zinc sorrelBOT
#

Brief summary for closing:

Gerryatric was trying to run OpenClaw on VPS1 against Ollama/Qwen on GPU VPS2.

What we found/fixed:

  • Don’t point OpenClaw at the Ollama UI/proxy or /v1; use native Ollama API: http://<ollama-host>:11434 with api: "ollama".
  • ZeroTier/private networking was the right path; VPS1 eventually reached VPS2 Ollama on :11434.
  • Big blocker was the GPU VPS: nvidia-smi initially failed and Ollama logged CPU-only / total_vram=0 B. After provider/GPU fix, RTX A4000 appeared and Qwen generation worked.
  • Direct Ollama test succeeded: qwen3:14b returned pong.
  • OpenClaw then reached Ollama too; Ollama logs showed POST /api/chat from VPS1.
  • Remaining OpenClaw-side issues were config/session cleanup:
    • add ollama/qwen3:14b to agents.defaults.models allowlist
    • set default model to ollama/qwen3:14b
    • remove stale BOOTSTRAP.md
    • set agents.defaults.skipBootstrap: true
    • clear stale interrupted task/session state
#
  • Context warning at 16k is only a warning; below 16k is the hard problem. For local Qwen, localModelLean and contextInjection: "continuation-skip" were recommended to reduce prompt size.

Current state: infrastructure path is working; remaining pain is local-model latency/session cleanup rather than VPS connectivity.