k8m: a single-binary Kubernetes console with an AI endpoint baked in
A lightweight, cross-platform Mini Kubernetes AI Dashboard with LLM, agent and MCP support (with configurable operation permissions), integrating multi-cluster management, intelligent analysis and real-time anomaly detection. Supports multiple architectures and single-file deployment for efficient cluster management and ops optimization.
At a glance
- What is it?
- k8m is a lightweight Kubernetes console written in Go with an AMIS front end, multi-cluster management, Lua inspection rules, in-pod shells and forty-nine MCP tools whose permissions follow the invoking user. The two details worth knowing before you deploy it are the default credential pair and the fact that the model name, API key and API endpoint are all linker flags baked into the binary at build time.
- Who is it for?
- k8m suits an operator who wants a cluster console small enough to download as one file and run without a control plane, and who is willing to treat its AI features as a dependency on someone else's endpoint. Four things to do before it faces a cluster.
- 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 7 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- weibaohui/k8m896 ★ · +16
| Repository | 2026-09-12 | 2026-11-14 |
|---|---|---|
| weibaohui/k8m | 880 | 896 |
16 Stars in the last 63 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The default credential pair and the JWT secret are both placeholders
The run instructions are three steps long and the second one hands you the keys to the kingdom. You download a release binary, start it with `./k8m`, and open `http://127.0.0.1:3618`. The default username is `k8m` and the default password is `k8m`. The documentation does follow that immediately with a warning to change both after going live and to enable two-factor verification, and two-factor is genuinely supported rather than aspirational, since a one-time-password library is in the dependency list. The flag list carries the same pattern. There is a flag for the secret used to sign login tokens, and its default value is the literal string `your-secret-key`, which is also what the environment template ships. The flag list itself is truncated mid-line in the documentation, so the remaining options are not visible there. In the compose file the port is published on all interfaces rather than bound to loopback, which means the placeholder credential is reachable from the network unless you change it first.
The model, the key and the endpoint are linker flags, not configuration
The built-in AI feature is not a service call the dashboard makes at runtime using your settings. The container build passes them into the binary at link time.
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.Version=$VERSION -X main.GitCommit=$GIT_COMMIT -X main.GitTag=$GIT_TAG -X main.GitRepo=$GIT_REPOSITORY -X main.BuildDate=$BUILD_DATE -X main.InnerModel=$MODEL -X main.InnerApiKey=$API_KEY -X main.InnerApiUrl=$API_URL" -o /app/k8mThree linker assignments carry the model name, the API key and the API URL into string variables the binary reads. The build defaults fill them with a placeholder key, a public endpoint on the project's own domain, and a hosted seven-billion-parameter instruct model. That is the answer to the question the documentation raises when it says the built-in assistant has worked with no configuration since an early version. It works because the endpoint is compiled in, not because the feature is local. If you want your own model, including one served locally, the documentation points at separate guides for self-hosted models and for a local runtime, which is the supported route for an air-gapped cluster.
One service label decides leader election, and the single-instance value is its absence
The production notes describe a leader-election switch implemented as a label on the service definition, and the two cases are opposites.
For a single instance you must not add the label, because adding it prevents normal access. For multiple instances you must add it, because without it the replicas will not fail over to each other. A separate manifest is provided for the multi-instance case. This is a real footgun, because every other system that uses a label like this treats presence as enabling something, and here presence breaks the single-replica deployment outright rather than degrading it. The documentation states both rules in bold and in a way that is hard to misread if you read it, which is the only reason this works at all. It also implies the election is advisory in a narrow way: with the label absent there is one replica and nothing to coordinate, and the absence is doing double duty as the single-node marker.
In-cluster deploy uses a NodePort that matches no other port
There are two ports and neither documentation nor configuration connects them. The binary serves on 3618, the compose file publishes 3618, and the environment template sets the port variable to 3618. The in-cluster manifest is different: it is applied with the cluster's own command and opens a NodePort, and the instructions tell you to visit port 31999. So the same binary answers on 31999 when deployed to a cluster and on 3618 everywhere else, with an Ingress as the alternative if you would rather not expose a NodePort. A NodePort is reachable from outside the cluster on every node's address, which combined with the placeholder credential is the combination to think about. The manifest is fetched directly from the repository by raw URL rather than pulled from a chart registry, so the version you run is whatever is on that branch at the moment you apply it.
MCP calls run with the invoking user's own permissions
The MCP integration is the most interesting design decision in the project, and it is worth reading twice because it is a security boundary rather than a feature. The console exposes forty-nine built-in Kubernetes tools for multi-cluster work, composable into more than a hundred cluster operations, and it can serve as an MCP server so other model software can call them. Every call can be recorded in detail. The part that matters is the permission bridge: multi-cluster management permissions and MCP model-call permissions are joined, so whoever is using the model has that person's own permissions applied when the tools execute. The stated purpose is to avoid privilege escalation across the boundary. That matters because an agent given a cluster console is exactly the situation where the model would otherwise act with whatever privilege the server process happens to hold. The cost is that an operation the user cannot perform by hand also cannot be performed through the assistant, which is the intended behaviour.
The websocket library is pinned to an unreleased commit
Two entries in the module file deserve a note. The websocket library is not on a release; its version is a pseudo-version carrying a date and a commit hash, which means the build tracks a specific commit on the upstream default branch rather than a tagged release. The other observation is three commented-out dependency-override directives, all for the same library, each mapping one version of it to a pseudo-version of another. That is left-over history from tracking upstream by commit and then reverting it, left in the manifest where it will confuse the next person who needs to make the same override. The rest of the dependency set is conventional for this kind of tool: the Kubernetes client libraries all on one matching minor version, an ORM with drivers for three databases, a migration engine, a Lua interpreter for the scripting feature, a cron library, metrics, OpenID Connect, LDAP, Swagger generation and a WebSocket server.
The runtime image repoints the package mirror and ships aws-cli
The second build stage is short and does three things worth noticing. It rewrites the Alpine package repository from the default content delivery host to a regional mirror, then upgrades all packages and installs a list that includes curl, bash, an inotify tool, timezone data, the AWS command-line tool, certificate authorities, Helm and the usual compression tools. It also removes the temporary Alpine configuration and clears the package cache afterwards, which is tidy. The mirror rewrite is the notable one. It is a sensible choice for build speed and reachability from where the maintainer is, and it also means every published image of this project fetches its runtime packages from a host chosen by the project rather than from Alpine's default, which is a supply-chain fact worth holding in mind when you decide whether to trust the image or build your own. The image runs a reload script as its entry point rather than the binary directly, which is how the container picks up configuration changes.
A source build fails without a front-end build, and the root has working artefacts in it
The development section leads with a trap that has caught people before. Because the front end is embedded in the binary, a project built without a front-end build fails at startup rather than at build time, so the first thing a new contributor does is build the interface.
cd ui
pnpm run buildThe build file does this for you, with a target that creates the embed directory, clears it, and copies the built assets into the location the binary reads them from. After that the backend runs under a hot-reload watcher that is installed on demand if it is missing, or the sources are run directly. For front-end work the development server runs on port 3000 and proxies backend calls to 3618. One inconsistency is easy to trip over: the readme instructs you to use one package manager for the front-end scripts while the build file invokes a different one in its own targets, and the build tool it defaults to is not the one the compose examples assume. There is also a log file sitting in the repository root, which means somebody ran the server from the source tree and committed its output. The compose file in the root is spelled with a transposed pair of letters, so tooling looking for the correctly spelled filename will not find it. Alongside those there are two separate Dockerfiles, one for the application and one apparently for a build action, a script for building the image, the reload script the container entry point calls, a hot-reload configuration, and two assistant configuration sets, one of them a hidden directory and one a markdown file carrying a different assistant name. None of this is harmful. It is a repository that has been worked in rather than curated.
Editorial conclusion
k8m suits an operator who wants a cluster console small enough to download as one file and run without a control plane, and who is willing to treat its AI features as a dependency on someone else's endpoint. Four things to do before it faces a cluster. Change the default credential pair and the JWT secret, both of which ship as literal placeholders, and enable the two-factor option the documentation recommends. Decide where the AI features point, because the shipped default is a public endpoint and the key travels inside the binary rather than in your configuration. Read the leader-election label rules carefully, because the correct value is the opposite of what you would guess and getting it wrong means no access. And if you build from source, build the front end first, or the binary will not start.
Frequently asked questions
What are the default k8m login credentials?
Username `k8m` and password `k8m`, on port 3618. The documentation says to change both after going live and to enable two-factor verification, which is supported. The secret used to sign login tokens also has a literal placeholder default of `your-secret-key`, settable with a command-line flag or the matching environment variable.
How is the built-in AI model configured in k8m?
At build time rather than at runtime. The model name, API key and API URL are passed as linker flags into string variables inside the binary, and the build defaults fill them with a placeholder key, a public endpoint on the project's domain, and a hosted instruct model. The built-in assistant has needed no configuration since an early version for that reason. Self-hosted models and a local runtime are documented separately.
How do I run k8m with more than one replica?
Apply the multi-instance manifest and add the `k8m.io/role: leader` label to the service definition. The rule is inverted for a single instance: do not add that label, because adding it prevents normal access. The multi-instance manifest is fetched from the repository's deploy directory by raw URL.
Which port does k8m listen on?
3618 for the binary, the compose file and the port environment variable, published on all interfaces in the compose example. The in-cluster manifest is different: it opens a NodePort on 31999, or you can configure an Ingress instead.
How many MCP tools does k8m provide?
Forty-nine built-in Kubernetes tools for multi-cluster work, described as composable into more than a hundred cluster operations. The console can act as an MCP server so other model software can call them, every call can be recorded in detail, and the tools execute with the permissions of the person using the model rather than those of the server process.
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/weibaohui-k8m)Star history chart for your README
[](https://hysenlabs.com/projects/weibaohui-k8m)Was this useful?