# How Do I Run Open WebUI With Ollama in a Cloud Sandbox?

> Install Ollama in a default Sandboxer sandbox, pull a small model, then run the official Open WebUI Docker image with --network=host and OLLAMA_BASE_URL=http://127.0.0.1:11434. Host port 8080 with sbx host: the URL is private by default, chat streams through it, and your account and chats survive stop and resume.

Source: https://sandboxer.com/guides/run-open-webui-with-ollama-in-a-sandbox. Updated 2026-10-27.

**Short answer:** Install Ollama in a default Sandboxer sandbox, pull a small model, then run the official Open WebUI Docker image with --network=host and OLLAMA_BASE_URL=http://127.0.0.1:11434. Host port 8080 with sbx host: the URL is private by default, chat streams through it, and your account and chats survive stop and resume.

## At a glance

Everything below ran on one `default` sandbox (4 vCPU, 8 GB RAM, 50 GB disk) on October 27, 2026. CPU only: there is no GPU in a sandbox. Single runs, so treat timings as rough.

| Step | What we saw |
| - | - |
| Pull `ghcr.io/open-webui/open-webui:main` | 4.56 GB image, 1 min 41 s |
| First start to `/health` = `{"status":true}` | Under 50 s, including a one-time download of its embedding model |
| Open WebUI version | `0.12.4` |
| Hosted URL without the token | `401` |
| First signup | Became `admin`. Signup then turned off: a second signup got `403` |
| Streaming chat through the URL (`qwen2.5:0.5b`) | `text/event-stream`, first token after 1.7 s cold, 0.2 s with the model loaded |
| Socket.IO WebSocket through the URL | `401` without the cookie, open frame with it |
| `sbx stop --wait` + `sbx resume` | `memoryRestored: true`, same PIDs, chats kept |
| Reboot (cold boot) | Ollama and Open WebUI came back on their own, chats and login kept |

## 1. Create a sandbox and install Ollama

The image is 4.56 GB and Open WebUI loads an embedding model at start, so use `default` rather than `small`. Start the image pull in the background while Ollama installs.

```bash
sbx new --name open-webui --type default
id=sb_ws4ypogjyw    # the id that sbx new printed

sbx exec $id --detach "docker pull ghcr.io/open-webui/open-webui:main > pull.log 2>&1"
sbx exec $id --timeout 600 "curl -fsSL https://ollama.com/install.sh | sh"
sbx exec $id "ollama pull qwen2.5:0.5b && ollama list"
```

```text
>>> Creating ollama systemd service...
>>> Enabling and starting ollama service...
WARNING: Unable to detect NVIDIA/AMD GPU. Install lspci or lshw to automatically detect and install GPU dependencies.
…
NAME            ID              SIZE      MODIFIED
qwen2.5:0.5b    a8b0c5157701    397 MB    Less than a second ago
```

The GPU warning is expected: Ollama runs on the CPU. The install script ([Ollama for Linux](https://ollama.com/download/linux)) adds an enabled `ollama` systemd service that listens on `127.0.0.1:11434`. Model choice, CPU speed and the Ollama API are covered in [Run Ollama on CPU in a cloud sandbox](/guides/run-ollama-on-cpu-in-a-cloud-sandbox). This page is about the web UI.

## 2. Run Open WebUI and connect it to Ollama

Open WebUI's [quick start](https://docs.openwebui.com/getting-started/quick-start/) uses `--add-host=host.docker.internal:host-gateway` to reach Ollama on the host. That only works if Ollama listens beyond loopback. Ollama here listens on `127.0.0.1` only, so use the host-network command from Open WebUI's own [connection troubleshooting page](https://docs.openwebui.com/troubleshooting/connection-error/). Ollama stays unreachable from outside, and the UI listens on port 8080.

```bash
sbx exec $id "docker run -d --network=host \
  -v open-webui:/app/backend/data \
  -e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
  --name open-webui --restart unless-stopped \
  ghcr.io/open-webui/open-webui:main"

sbx exec $id --timeout 300 "until curl -sf localhost:8080/health >/dev/null; do sleep 1; done; \
  curl -s localhost:8080/api/version; ss -ltn | grep -E '8080|11434'"
```

```text
{"version":"0.12.4","deployment_id":""}
LISTEN 0      4096       127.0.0.1:11434      0.0.0.0:*
LISTEN 0      2048         0.0.0.0:8080       0.0.0.0:*
```

Two flags matter later. `-v open-webui:/app/backend/data` keeps users, chats and settings in a Docker volume (about 1.1 GB after first start, mostly cached models). `--restart unless-stopped` brings the container back after a cold boot.

The first start downloads a sentence-transformers model from Hugging Face. The sandbox's internet access is enough. Don't call `/health` failed if it takes 30 to 50 seconds.

## 3. Give it a private HTTPS URL

```bash
sbx host $id 8080 --title "Open WebUI"
```

```text
https://helpful-joyful-eel-8080.box.sandboxer.com?_token=<token>
```

A hosted port is private by default. What the proxy returned:

| Request | Status |
| - | - |
| `https://helpful-joyful-eel-8080.box.sandboxer.com/` (no token) | `401`, and Open WebUI never sees it |
| The full URL with `?_token=` | `302` to `/`, sets the `__sbx_auth` cookie (30 days) |
| `/` with the cookie | `200`, `<title>Open WebUI</title>` |

So there are two locks. The Sandboxer token keeps strangers off the page, and Open WebUI's own login sits behind it. Open the full token URL in your browser once and the cookie does the rest. See [Give a sandbox port an HTTPS URL](/guides/give-a-sandbox-port-an-https-url) for public URLs, `--localhost` and how to revoke a link.

## 4. Create the admin account first

Open the URL and sign up. The first account becomes the administrator. We signed up through the API from Node 24 (the `__sbx_auth` cookie in the `Cookie` header) to record the responses:

```javascript
const r = await fetch(`${base}/api/v1/auths/signup`, {
  method: "POST",
  headers: { Cookie: cookie, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Admin", email: "admin@example.com", password: "…" }),
});
console.log(r.status, (await r.json()).role);
```

| Signup | Result |
| - | - |
| `admin@example.com` (first) | `200`, `"role": "admin"` |
| `second@example.com` | `403` "You do not have permission to access this resource" |

After the first account, `/api/config` reported `"enable_signup": false`. Sign up yourself before you share the link with anyone. Whoever holds the token URL and gets to the signup form first owns the instance. The admin can turn signup back on or add users in the admin panel.

## 5. Chat: streaming and WebSockets through the proxy

Open WebUI streams replies over Server-Sent Events and uses a Socket.IO WebSocket at `/ws/socket.io/` for live updates. Both went through the hosted URL. We called the OpenAI-style endpoint with the admin's JWT and the `__sbx_auth` cookie from Node 24:

```javascript
const r = await fetch(`${base}/api/chat/completions`, {
  method: "POST",
  headers: { Cookie: cookie, Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "qwen2.5:0.5b",
    stream: true,
    messages: [{ role: "user", content: "In two sentences, what is a microVM?" }],
  }),
});
// read r.body line by line and time the first "data:" chunk with content
```

```text
chat: 200 text/event-stream
first token after 1705 ms, 29 chunks in 2447 ms
models: 200 qwen2.5:0.5b
```

The 1.7 seconds includes Ollama loading the model. With the model already loaded, the first token arrived after 198 ms. The answers from a 0.5B model are short and often wrong. Pick a bigger model if you have the RAM; the Ollama guide compares sizes.

The WebSocket handshake to `wss://…-8080.box.sandboxer.com/ws/socket.io/?EIO=4&transport=websocket` returned `401` without the cookie. With it, the first frame was the Socket.IO open packet, `0{"sid":"m6dDZJIjrq5hoL_MAAAA",…`. In a browser you don't need to do anything: the page sends the cookie on its own WebSocket.

## 6. Stop, resume and reboot

We saved a chat titled "Before stop", noted the PIDs, then stopped and resumed.

```bash
sbx stop $id --wait
sbx resume $id
sbx exec $id "docker inspect -f 'pid={{.State.Pid}}' open-webui; systemctl show -p MainPID ollama"
```

```text
ready  memoryRestored=true      # from the resume JSON
pid=954
MainPID=795
```

Same PIDs as before the stop. The URL, the token and the 30-day cookie still worked, `GET /api/v1/chats/` listed "Before stop", and the model was still loaded (first token after 198 ms). Use `--wait` before resuming: a resume during the snapshot is refused.

Memory comes back only when the resume lands on a machine with the same CPU type. Otherwise the sandbox boots from disk with `memoryRestored: false`. To test that path, we rebooted the VM with `sudo systemctl reboot`:

```text
20.64 59.62                    # /proc/uptime: a fresh boot
24.69 72.05                    # /health answered 4 s later
pid=617
active                         # ollama.service
qwen2.5:0.5b    a8b0c5157701    397 MB    2 minutes ago
```

Ollama came back as an enabled systemd service. Open WebUI came back because of `--restart unless-stopped`. The admin could sign in, the "Before stop" chat was there, and the first token took 1.8 s while the model loaded again. A container started without a restart policy would stay down after a cold boot.

## When this setup fits

| Situation | Fits? |
| - | - |
| Try Open WebUI and small models without installing anything locally | Yes |
| A private chat UI for you and a few people you send the link to | Yes, with signup closed after the admin |
| Large models or fast replies | Not on CPU. Bigger models reply more slowly and need more RAM; see the Ollama guide |
| A public service for strangers | Not with `--public`: Open WebUI's login would be the only gate |

## FAQ

### Why not use the quick start's port mapping and host.docker.internal?

That works only if Ollama listens on an address the container can reach. The Ollama service here listens on `127.0.0.1:11434`, so `--network=host` with `OLLAMA_BASE_URL=http://127.0.0.1:11434` is the simplest fix. It is the host-network command from Open WebUI's own troubleshooting page, with `--restart unless-stopped` in place of `--restart always`.

### Do I need a GPU?

No. Everything on this page ran on CPU. Small models like `qwen2.5:0.5b` reply in a second or two. Sandboxes have no GPU, so bigger models are slower.

### Who can open the URL?

Only people with the full token URL or the cookie it sets. Everyone else gets `401` from the proxy before reaching Open WebUI. Inside, they still need an Open WebUI account.

### Do my chats survive a stop?

Yes. They live in the `open-webui` Docker volume on the sandbox disk. They were kept across a memory-restoring resume and across a reboot.

### Does the sandbox stop on its own?

Yes, after one hour by default and after a period of inactivity. Both stops keep memory when possible. Change them with `sbx extend $id --hours 12` or `sbx idle $id 0`.

## Related

- [Run Ollama on CPU in a cloud sandbox](/guides/run-ollama-on-cpu-in-a-cloud-sandbox)
- [Give a sandbox port an HTTPS URL](/guides/give-a-sandbox-port-an-https-url)
- [Run Docker Compose in a sandbox with a URL per service](/guides/run-docker-compose-in-a-sandbox-with-a-url-per-service)
- [Hosting](/docs/hosting)
