AnGe-ClashBoard: a Clash and Mihomo dashboard that keeps its state on the server
AnGe-ClashBoard - zashboard 完整体
At a glance
- What is it?
- AnGe-ClashBoard is a Vue 3 and TypeScript fork of zashboard that adds SQLite persistence, server-side rule cache and icon management, and it ships as a Docker image that fetches the Mihomo binary at build time. It suits a self-hosted proxy operator who wants a panel that survives a browser change, and it needs a controller it can reach.
- Who is it for?
- AnGe-ClashBoard is worth deploying if you run a Clash, Mihomo, OpenClash, Nikki or sing-box instance and want a panel that remembers your settings, because the state lives in a SQLite database next to the container rather than in a browser profile, because the rule query view resolves a domain to the rule that matched, the source that provided it, the strategy chain and the final node, and because the backend relay lets you reach the panel from outside without publishing the controller port.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 84 days ago.
- What is it written in?
- Mainly Vue, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A zashboard fork with the state moved to the server
AnGe-ClashBoard is a Clash panel built on Vue 3, TypeScript and Vite, aimed at running, observing and debugging Clash API, Mihomo, OpenClash, Nikki and sing-box instances. It is a secondary development of the open source zashboard project.
The fork's additions are the interesting part, and the project documentation lists them as a set of features rather than as a diff. Configuration is persisted in SQLite, so switching browsers keeps your settings. Background images are persisted on the server. Icons support upload, drag and drop, copy and preview, and you can assign a specific icon to a strategy group, a node group or other items. There is a rule cache with queries by domain, IP and keyword, a display of the link chain and a check of the fallback rule. And the backend can relay controller data, so you can access the panel over a public network without exposing the controller port directly.
That last item is a real operational improvement rather than a convenience feature. A Clash controller is a powerful API, and a controller exposed to the internet is a liability. A panel that sits in front of it and talks to it from the server side changes the exposure from a controller port to a panel port, and a panel port is easier to protect.
The project also describes a one-click Docker deployment suited to personal and local network use, and the repository carries a Dockerfile, a Caddyfile for reverse proxying, a scripts/ directory with the install, update and uninstall scripts, a server/ directory for the local persistence and rule cache backend, and src/ for the frontend.
The licence position is stated in the documentation and it is worth being precise about. The project is a secondary development of zashboard, whose upstream licence is the MIT License, so you may continue to modify, publish and distribute it as long as the original licence notice is kept, and the project asks that the LICENSE file in the repository be retained.
The two views that make the panel useful: strategy and rule penetration
Two of the features are described at length in the project documentation, and they are the reason to use this fork rather than the upstream panel.
Strategy penetration expands the strategy groups down into their internal nodes and sub-strategy chains, so you can see which strategy is currently hit, the state of the candidate nodes and the final exit at a glance. On a proxy panel the usual question is why a request went out through the node you did not expect, and the answer is a chain of groups, and this view shows the chain rather than the top of it.
Rule penetration answers the other half. It supports querying rule hit results by domain, IP and keyword, and it shows the rule source, the match type, the strategy chain and the final node, which is what makes it usable for debugging traffic splitting problems. The panel tells you which rule matched, not just that something matched.
The rule page supports querying the source of the rule that was hit for a domain and showing the actual strategy chain. What it can currently handle is listed precisely: a cache of text rule sources, parsing of .mrs domain rule sets, ordering of rules, detection of the fallback rule, automatic cache updates based on the interval in the YAML, and a display of the accumulated rule count with a manual stop during a refresh.
The mechanism behind that is worth understanding, because it determines what the panel can show. Rule sources need the SSH connection to the OpenWrt proxy host configured, and the service reads the proxy host's current configuration over SSH in real time. It does not read local OpenClash files, and it does not ship rule source templates. So the panel is a window onto the configuration of a remote router, not a separate copy of it.
Installing with the one-line script, and choosing a port
The prerequisites are a server with Docker installed, access to ghcr.io, and a decision about which port you are willing to expose for the panel.
The default installation directory is /opt/ange-clashboard, the default data directory is /opt/ange-clashboard/data, and the default port is 2048. The install is:
curl -fsSL https://raw.githubusercontent.com/liandu2024/AnGe-ClashBoard/main/scripts/install.sh | bashAfterwards the panel is at http://<your server IP>:2048.
A custom port is passed to the same script with the arguments after a double dash:
curl -fsSL https://raw.githubusercontent.com/liandu2024/AnGe-ClashBoard/main/scripts/install.sh | bash -s -- 8080The upgrade path is a separate script, and the documentation is careful about what is preserved. The upgrade keeps the existing data directory and does not delete your configuration, background images or rule cache, and the directory that is kept is /opt/ange-clashboard/data. The command is:
curl -fsSL https://raw.githubusercontent.com/liandu2024/AnGe-ClashBoard/main/scripts/update.sh | bashThe documentation also says it still recommends exporting the settings from the panel before an upgrade, to keep an extra copy of the configuration, and that if you installed with the one-line script and have not manually changed the structure of compose.yaml or .env, this upgrade method is a lossless in-place upgrade.
The uninstall script is the mirror image, and it is worth reading before you run it. It deletes the container, the image, /opt/ange-clashboard and the local data directory.
curl -fsSL https://raw.githubusercontent.com/liandu2024/AnGe-ClashBoard/main/scripts/uninstall.sh | bashThose four items are the whole footprint, and none of them is a system directory outside /opt, which is a reasonable boundary for a panel that stores its own data.
Running the image directly, and the health check to verify it
The project recommends using the image published to GHCR:
ghcr.io/liandu2024/ange-clashboard:latestThe published image supports linux/amd64, linux/arm64 and linux/arm/v7, which covers a normal server, an ARM server and a small single board computer, which is a common home lab target for this kind of tool.
The manual run is:
docker run -d \
--name ange-clashboard \
-p 2048:2048 \
-v ./data:/app/data \
--restart unless-stopped \
ghcr.io/liandu2024/ange-clashboard:latestThe documentation explains the --restart unless-stopped flag, meaning the container comes back up automatically after the Docker service restarts unless you stopped it yourself.
The volume mount is the line that matters for persistence. If you run with a mount such as -v ./data:/app/data, upgrading the image keeps the data directory, so it is a lossless upgrade. The manual upgrade sequence is to pull the new image, stop and remove the old container, and start a new one with the same flags:
docker pull ghcr.io/liandu2024/ange-clashboard:latest
docker stop ange-clashboard
docker rm ange-clashboardand then the same docker run command again. The documentation notes that if you used a custom port, a different container name or a different data mount, you should change the parameters to match the set you are actually running, and that if you installed with the one-line script you should prefer update.sh instead.
For a scripted check, the health endpoint is:
http://127.0.0.1:2048/api/healthwhich is the thing to curl in a monitoring job to know the panel is up.
The server side: SQLite, the rule cache and the environment variables
The panel has a lightweight Node service built in, and the documentation lists what it stores: settings, background images and the rule cache. The default database path is ./data/zashboard.sqlite, and it can be overridden with the ZASHBOARD_DB_PATH environment variable.
That is the whole persistence layer, and the choice of SQLite for it is a pragmatic one. The data is a handful of settings, some image blobs and a cache, the service is a single Node process, and SQLite means the state survives a container replacement without a separate database server to run.
The rule source configuration is the other part of the server, and it is where the environment variables are documented:
ZASHBOARD_OPENWRT_SSH_HOST
ZASHBOARD_OPENWRT_SSH_PORT
ZASHBOARD_OPENWRT_SSH_USER
ZASHBOARD_OPENWRT_SSH_PASSWORD
ZASHBOARD_RULE_SOURCE_PLUGINYou can also set the same values in the panel itself, in the change backend configuration dialog, where you fill in the rule source type, the SSH port, the account and the password for the relevant backend. The rule source SSH host uses the host of that backend directly, so the host is not set twice.
The service identifies the proxy side automatically. For OpenClash it reads the remote /etc/config/openclash, parses the real option config_path in it, and then reads the rule-providers of the corresponding YAML. For Nikki it prefers to extract the actual YAML path from the remote process command line and from /etc/config/nikki, and then validates the rule-providers inside it. Two more variables cover the case where the remote OpenClash UCI path is not in the default place, ZASHBOARD_OPENCLASH_UCI_PATH and ZASHBOARD_OPENCLASH_CONFIG_DIR.
Note what is not there: a password in an environment variable is a password in a container configuration. It is workable for a home server and it is not what you would do in a shared or multi-tenant environment, and the panel offers the same setting in its own dialog as an alternative.
How the image is built, and where the project sits
The Dockerfile is worth reading because it explains one thing you would otherwise find out at runtime.
The build is a two-stage one on node:22-alpine. The builder stage installs dependencies with pnpm using a frozen lockfile and the corepack package manager, builds the frontend with the build script, and then uses pnpm deploy to extract the production server runtime into a separate directory. The final image copies the built dist directory and that server runtime, and the entry point is node server/index.mjs with the port set to 2048 and exposed.
The interesting step is in the final image. It copies a script called fetch-mihomo.mjs and runs it with the target architecture and variant passed in as build arguments, then makes the downloaded binary executable and removes the script directory. So the Mihomo core binary is fetched during the image build for the right architecture, and it is baked into the image rather than mounted at runtime. That is what makes the published image work across amd64, arm64 and arm/v7 from one tag.
It also means the image is not self-contained in the sense of being reproducible from a package you can inspect, since a build-time download is involved, and the version that ends up inside the image is whatever the fetch script retrieves on the day the image was built.
On the project side, the package.json is a modern pnpm workspace with a Vue 3 and TypeScript setup, and the scripts are worth a glance. There are several build variants for fonts, with build:no-fonts and per-family builds such as build:firasans-only and build:sarasa-only, which matters for a panel rendered on a server that may not have your preferred fonts installed. There is a dev:full script that runs the server and the client together with concurrently, a test script that runs node's own test runner over the server tests, a type-check script using vue-tsc, and husky configured for the prepare hook. The runtime dependencies include ECharts for the charts, the TanStack table and virtual packages, dompurify for sanitising content, axios, dayjs, lodash and p-limit.
The version story has a wrinkle. The documentation states a current version of 1.91, while the package.json carries 2.06, and the release tags are v2.04, v2.05 and v2.06 with the last two published on 2026-07-31, the same day as the last push to the repository. So the version in the README and the version in the package are not the same number, and the tags are ahead of the README.
Editorial conclusion
AnGe-ClashBoard is worth deploying if you run a Clash, Mihomo, OpenClash, Nikki or sing-box instance and want a panel that remembers your settings, because the state lives in a SQLite database next to the container rather than in a browser profile, because the rule query view resolves a domain to the rule that matched, the source that provided it, the strategy chain and the final node, and because the backend relay lets you reach the panel from outside without publishing the controller port. It is the wrong tool if you do not run a proxy core, and it is the wrong tool if you want a general network dashboard. Before you install it, check three things: that you have Docker and access to ghcr.io, since the image is pulled from there and supports linux/amd64, linux/arm64 and linux/arm/v7; that the default port 2048 and the paths /opt/ange-clashboard and /opt/ange-clashboard/data are acceptable, since the uninstall script removes the container, the image, that directory and the local data; and that you read the rule source requirements carefully, because the rule view needs SSH access to the OpenWrt proxy host, and the panel reads the remote OpenClash or Nikki configuration rather than any local file.
Frequently asked questions
How do I install AnGe-ClashBoard?
With Docker installed and access to ghcr.io, run curl -fsSL https://raw.githubusercontent.com/liandu2024/AnGe-ClashBoard/main/scripts/install.sh | bash. The default install directory is /opt/ange-clashboard, the data directory is /opt/ange-clashboard/data and the panel listens on port 2048, which you can change by passing the port to the same script with bash -s -- 8080.
Where does AnGe-ClashBoard store its settings and rule cache?
In a built-in lightweight Node service, which saves settings, background images and the rule cache to a SQLite database whose default path is ./data/zashboard.sqlite and which can be overridden with the ZASHBOARD_DB_PATH environment variable. With the Docker image the data survives an image upgrade as long as the data directory is mounted.
Does the rule query feature need access to the proxy host?
Yes. Rule sources need the SSH connection to the OpenWrt proxy host configured, and the service reads the proxy host's current configuration over SSH in real time rather than reading local OpenClash files or shipping rule source templates. The SSH host, port, user and password can be set in the panel's backend configuration dialog or through the ZASHBOARD_OPENWRT_SSH_HOST, ZASHBOARD_OPENWRT_SSH_PORT, ZASHBOARD_OPENWRT_SSH_USER and ZASHBOARD_OPENWRT_SSH_PASSWORD environment variables.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/liandu2024-ange-clashboard)Was this useful?