# HaloWebUI, a Chinese-language Open WebUI fork with a model routing layer

> HaloWebUI is a deep customization of the Open WebUI self-hosted AI platform, translated into Chinese and extended with a built-in message gateway, native Claude, Gemini and Grok integration and model usage accounting. It ships as two container images, a full one with the runtimes needed for stdio MCP servers and a slim one without, and it keeps the upstream architecture of a SvelteKit front end over a FastAPI back end.

**ztx888/HaloWebUI** — 基于官方OpenWebUI，汉化界面提高中文使用体验，增加了模型计费和用量统计

- Repository: https://github.com/ztx888/HaloWebUI
- Stars: 1,161 · Forks: 85
- Language: Python
- License: BSD-3-Clause
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/ztx888-halowebui

## A fork of Open WebUI, not a new product

The project describes itself as based on Open WebUI, deeply customized, with the Chinese interface improved for Chinese usage and model billing and usage statistics added. The acknowledgement section is explicit that it is built on Open WebUI and thanks the Open WebUI community, which places it in the same category as the many downstream deployments of that project rather than in a category of its own. The upstream architecture survives intact underneath, which the package metadata confirms in a slightly unexpected way: both the front end package.json and the back end pyproject.toml still name the project open-webui, and the Docker Compose service is still called open-webui. The licence is BSD-3-Clause, the primary language recorded for the repository is Python, and the last push was on 2026-06-04 with the repository not archived.

## The stack: SvelteKit in front, FastAPI behind

The architecture diagram in the project documentation is the clearest summary of the design. The browser or PWA talks to a Svelte 4, TypeScript and Tailwind front end, which talks to a FastAPI back end that carries the AnyRouter, the HaloClaw gateway, the retrieval augmented generation and the pipeline layers, which in turn sit on the model providers and the storage. On the storage side the diagram lists SQLite or PostgreSQL, Redis and a vector database, and the provider row shows Claude and Gemini as native, OpenAI as a compatibility layer and Ollama as local. The dependency list backs this up in detail. The front end is SvelteKit with the Vite plugin and Tailwind 4, and the back end is FastAPI with uvicorn, pydantic, SQLAlchemy, alembic for migrations, peewee and peewee-migrate, psycopg2 and pgvector for PostgreSQL, redis, pymongo, boto3, argon2 and passlib for credentials, and APScheduler for scheduled work. The AI stack includes the openai, anthropic and google-generativeai clients, langchain, tiktoken, chromadb, qdrant, pymilvus, opensearch and elasticsearch, sentence-transformers, transformers, accelerate and playwright.

## Two images, and the difference is the MCP runtimes

The container story is where the project's own engineering decisions are most visible. The official main image is the default recommended one and it ships with uv, uvx, node, npx and git inside, so the common stdio MCP presets work out of the box and MCPs installed through a command such as uvx with a git source also work. The slim image is the minimal one, without uv, uvx, node, npx or git, and it is the right choice when image size and dependency surface matter more than out-of-the-box MCP. The documentation is careful about how stdio MCP servers run: the commands execute inside the HaloWebUI service container, not in your browser and not in your local shell. The compose file follows the same split, with a standard file and a slim override that you combine with the docker compose flags.

```bash
docker run -d -p 3000:8080 \
  --add-host=host.docker.internal:host-gateway \
  -v open-webui:/app/backend/data \
  --name halowebui \
  --restart always \
  ghcr.io/ztx888/halowebui:main
```

## The volume, the port and who becomes the administrator

One detail in the quick start is marked as important and it is the kind of detail that loses a deployment: you must mount the volume at the path that holds the database and the uploaded files. The Compose file shows the same volume, named open-webui, mounted at the backend data path, and the run command uses the same volume name, so the two routes are equivalent. The port mapping is 3000 on the host to 8080 in the container, and the Compose file exposes the host port from a variable with a default of 3000. After startup you visit the local address and the first user who registers automatically becomes the administrator, which is worth understanding before you expose the instance to a network.

```yaml
    volumes:
      - open-webui:/app/backend/data
    ports:
      - ${OPEN_WEBUI_PORT-3000}:8080
```

```yaml
    volumes:
      - open-webui:/app/backend/data
    ports:
      - ${OPEN_WEBUI_PORT-3000}:8080
    restart: unless-stopped
```

## The first-load problem, and the Nginx configuration that fixes it

The documentation spends a lot of space on first-screen load performance, and the reason is a bandwidth constraint rather than a code problem. If the backend server has low bandwidth, the first screen can load slowly, and the recommendation is to put the browser entry point behind Nginx or a CDN so the static front end assets are served from closer to the user while the API and the realtime chat still forward to the back end service. The example configuration is instructive in the details: the immutable build assets under the app path carry a version fingerprint, so they can be given a one-year cache, while the assets, wasm and static paths get a short cache of a day, and the cache directory, uploaded files and API responses are explicitly not recommended for long caching. The websocket path needs the upgrade headers, and the catch-all location forwards the rest.

```nginx
location /_app/immutable/ {
    proxy_pass http://127.0.0.1:8080;
    expires 1y;
    add_header Cache-Control "public, max-age=31536000, immutable" always;
}
```

## The environment variables, and the one that matters in production

The configuration table is the reference for a deployment. The OpenAI compatible key and base URL come first, with the base URL defaulting to the OpenAI endpoint, which is what makes the compatibility layer work against any provider that speaks that API. Then come the certificate verification switches, one for the requests library and one for aiohttp, both defaulting to true, and the guidance is to import the CA certificate into the container trust chain when using a self-signed certificate, with the switches set to false only for temporary troubleshooting. The provider keys for Anthropic and Gemini have no default. The Ollama base URL points at the host gateway, the JWT signing secret must be set in production and is otherwise generated randomly, and the database connection string defaults to a local SQLite file while PostgreSQL is the alternative, with a Redis URL for cache.

## Where it fits, and what to check first

The honest summary is that this is a deployment of a well known open source project with a localisation and an extension layer, and the value depends on whether you need those additions. If your team reads Chinese and wants the model providers connected natively with usage accounting, the fork saves you the work. If you do not, upstream Open WebUI is the better dependency, because a fork is a thing you now have to track. Three checks before deploying. The image variant, because the main and slim images differ in whether the stdio MCP tooling is present, and the documentation notes that the standard MCP path should be used rather than a temporary shell path. The MCP configuration itself, because the documentation says a saved configuration is not validated automatically and you have to open it and click the verify connection button yourself. And the volume, because without it the database and uploads live and die with the container, and the first registered user becomes the administrator of an instance that anyone who reaches it can register against.

## Conclusion

Adopt HaloWebUI if you run Open WebUI for a Chinese-speaking team and want the interface translated, native provider integration and usage accounting without maintaining a fork yourself, and skip it if you are happy with upstream Open WebUI and do not need the Chinese interface. Verify three things before you deploy: that the image tag you pull matches the runtime features you rely on, because the main image and the slim image differ in whether the stdio MCP tooling is present; that the persistent volume is mounted, since the database and uploaded files live there and the first registered user becomes the administrator; and that the environment variables you need for your providers are set, since the defaults point at OpenAI and the other provider keys have no default at all.

## FAQ

### What is HaloWebUI?

It is an open source self-hosted AI platform built on Open WebUI, deeply customized with a Chinese interface, native integration of Anthropic Claude, Google Gemini and xAI Grok, a built-in HaloClaw message gateway, and model billing and usage statistics. The licence is BSD-3-Clause.

### How do I run HaloWebUI with Docker?

Run the container with the persistent volume mounted at the backend data path, map port 3000 to the container port 8080, and use the image from the GitHub container registry. The Compose route is `docker compose up -d`, and the slim variant uses the slim Compose override file combined with the main one. After startup, visit the local address and the first user to register becomes the administrator.

### What is the difference between the main and slim HaloWebUI images?

The main image is the default recommended one and includes uv, uvx, node, npx and git, so the common stdio MCP presets work out of the box. The slim image is the minimal one without those runtimes, meant for deployments that care more about image size and dependency surface, and it suits people willing to add Node.js or uv themselves.

### Where do stdio MCP servers run in HaloWebUI?

Inside the HaloWebUI service container, not in the browser and not in your local shell. Some custom servers installed from a Git source also need git present, and a saved MCP configuration is not validated automatically, so you have to open the configuration and trigger the verify connection action yourself.

## Sources

- [Issues](https://github.com/ztx888/HaloWebUI/issues)
- [License: BSD-3-Clause](https://github.com/ztx888/HaloWebUI/blob/main/LICENSE)
- [README](https://github.com/ztx888/HaloWebUI/blob/main/README.md)
- [ztx888/HaloWebUI on GitHub](https://github.com/ztx888/HaloWebUI)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ztx888-halowebui
