CLI tool
c0m4r/kula avatar
c0m4r/kula

Kula: a single-binary Linux monitor that reads /proc and keeps its own ring buffer

Lightweight, self-contained Linux server monitoring tool. K U L A Lightweight, self-contained Linux server monitoring tool.** Website | Demo | Docker Hub Zero dependencies.

1,322 stars69 forksGoAGPL-3.0

At a glance

What is it?
Kula collects CPU, memory, network, disk and thermal metrics every second from /proc and /sys, stores them in tiered ring-buffer files, and serves a Web UI, a TUI and a REST API from one Go binary with no external database.
Who is it for?
Adopt Kula when you want per-second Linux telemetry on a host without standing up Prometheus, a database or an agent package tree, and when a rolling history of roughly the configured ring-buffer sizes is enough. Skip it if you need long-term retention, cross-host querying or an alerting pipeline beyond the built-in clock sync, low entropy and system overload alerts.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 10 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 September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Kula solves, and for whom

Most Linux monitoring stacks ask you to accept a chain of components before you see a single graph: an agent, a time-series database, a query layer, a dashboard server. Kula collapses that chain into one Go binary. The README describes it as a "Lightweight, self-contained Linux server monitoring tool" with "Zero dependencies. No external databases. Single binary." The target reader is someone who has just provisioned a VPS or a bare-metal box and wants CPU, memory, network, disk and thermal numbers within minutes, not after an afternoon of configuration.

The scope is deliberately a single host. Kula reads directly from /proc and /sys, so it reports what the kernel exposes and nothing more. It is a poor fit for fleet-wide dashboards or long-horizon capacity planning, and the README never claims otherwise. What it does claim is breadth per host: CPU breakdown including iowait, irq, softirq and steal; per-interface throughput and TCP error counters; per-device disk IOPS; filesystem usage; entropy and clock sync; process state counts; Docker, podman and raw cgroup data; and application metrics for PostgreSQL, MySQL/MariaDB, nginx and apache2. There is also a custom metrics path for anything the built-in collectors miss.

Collectors, tiered ring-buffer files and the HTTP surface

The data flow in the README is short: the kernel exposes /proc/stat, /proc/meminfo and /sys entries; collectors read them every second; the results go to a storage engine and to the live consumers. The storage engine is the part worth understanding before you deploy. Kula writes metrics into fixed-size binary files and wraps around when a file is full, overwriting the oldest entries. There is no compaction step and no external database process.

Older data is downsampled into tiers. Tier 1 holds raw 1-second samples with a default capacity of 250 MB. Tier 2 holds 1-minute aggregations with Avg, Min and Max, default 150 MB. Tier 3 holds 5-minute aggregations with the same statistics, default 50 MB. Those defaults define your retention window, and the README does not state a time-based retention guarantee, so the practical history length depends on how many metrics your host actually emits per second. On startup Kula restores the latest-sample cache and reconstructs pending aggregation buffers, which means a restart does not wipe recent history or leave a tier half-rolled.

On top of storage, the HTTP server exposes a REST API and a WebSocket endpoint for live streaming. Authentication is optional. When enabled, the README states Kula uses Argon2id password hashing, secure session cookies, token-only session validation with sliding expiration, and session persistence hashed at rest. API clients can also pass a bearer session token in the Authorization header. The frontend is a single-page application embedded in the binary, built on Chart.js with custom SVG gauges. It connects over WebSocket for live updates and falls back to the history API for longer ranges. A Prometheus exporter endpoint is also present for scraping into an existing observability stack, which is the escape hatch if you later decide you do want a central system.

Installing Kula and getting a first dashboard

The README offers several amd64 installation paths and points to the Releases page for ARM and RISC-V packages. The guided installer is the shortest route. It downloads a script from the repository and runs it, so the README itself warns: "Never thoughtlessly paste commands into the terminal."

bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/c0m4r/kula/refs/heads/main/addons/install_v2.sh)"

If you prefer to inspect the script first, the README gives a variant that downloads it to a temporary file, checks a published sha256 sum, and only then executes it. The expected checksum in the README is bad61ee9eed4595d20fa7e613bd27c3b8700c67f8a5fcac756d282a811705398.

bash
KULA_INSTALL=$(mktemp)
curl -o ${KULA_INSTALL} -fsSL https://raw.githubusercontent.com/c0m4r/kula/refs/heads/main/addons/install_v2.sh
echo "bad61ee9eed4595d20fa7e613bd27c3b8700c67f8a5fcac756d282a811705398 ${KULA_INSTALL}" | sha256sum -c || rm -f ${KULA_INSTALL}
bash ${KULA_INSTALL}
rm -f ${KULA_INSTALL}

For a manual install, download the release tarball for version 0.18.8, verify it against the published checksum, unpack it and run the binary. The README's example uses wget and a sha256sum check with the value 45ce3a6a06be92caec938d6d01884da0d81f1092ee9741c73b4ee03566411316.

bash
wget https://github.com/c0m4r/kula/releases/download/0.18.8/kula-0.18.8-amd64.tar.gz
echo "45ce3a6a06be92caec938d6d01884da0d81f1092ee9741c73b4ee03566411316 kula-0.18.8-amd64.tar.gz" | sha256sum -c || rm -f kula-0.18.8-amd64.tar.gz
tar -xvf kula-0.18.8-amd64.tar.gz
cd kula
./kula

After ./kula starts, open the dashboard in a browser on the configured port. The README does not print the default port in the excerpt shown here, so read config.yaml from the unpacked directory before you expose anything. The Docker path is the other quick option. It needs the host PID namespace and a read-only /proc mount, and the persistent variant adds a named volume for /app/data so ring-buffer files survive container replacement.

bash
docker run -d --name kula --pid host --network host -v /proc:/proc:ro -v kula_data:/app/data c0m4r/kula:latest
docker logs -f kula

The temporary variant drops --rm in favor of -it and omits the volume, which is fine for a look at the UI but loses all history when the container exits.

Where Kula stops being the right tool

The ring buffer is the central trade-off. Fixed-size files mean bounded disk usage, and bounded disk usage means old data is destroyed rather than archived. If your question is what a host looked like three months ago, Kula has already overwritten the answer unless your tier sizes are large enough to hold it. There is no documented export of ring-buffer contents to cold storage, and the README does not describe rollback or migration of the binary data format between versions. Treat a version upgrade as a point where you should check the release notes before assuming existing data files remain readable.

There is a second boundary around GPU and container coverage. The README notes that monitoring NVIDIA GPUs "might require additional setup" and links to a wiki page for it, so GPU load, power and VRAM are not guaranteed out of the box. Container metrics depend on Docker, podman or raw cgroups being present and readable. Application metrics cover PostgreSQL, MySQL/MariaDB, nginx and apache2; anything else needs the custom metrics path.

The alert system is also narrow. The README lists alerts for clock sync, low entropy and system overload. That is not a general alerting engine with routing, silencing or escalation. If you need paging, you will be scraping the Prometheus exporter endpoint into something that does that job. Finally, the project is Linux-only by construction. It reads /proc and /sys, so BSD, macOS and Windows hosts are out of scope entirely.

How Kula differs from Prometheus and node_exporter

The closest comparison is node_exporter plus Prometheus. node_exporter also reads kernel interfaces and exposes metrics, but it is a scrape target: it holds no history of its own, and Prometheus pulls samples on a scrape interval and stores them in its own time-series database. That architecture buys you cross-host queries, long retention and a mature alerting layer, at the cost of running and sizing a second service and its storage.

Kula inverts the direction. It pushes nothing and pulls nothing; it samples locally every second and writes into its own files, then serves the UI and API from the same process. Per-second resolution is the default rather than a scrape interval you tune, and there is no separate database to back up. The price is that history is local, bounded and single-host, and the query surface is Kula's own REST API rather than PromQL. The README's Prometheus exporter endpoint is the bridge between the two worlds: you can run Kula as the local collector and still scrape it into Prometheus if you later want central storage. If you already operate Prometheus, adding Kula means one more scrape target; replacing Prometheus with Kula means giving up everything PromQL gives you.

Licence, maintenance and the cost of staying current

Kula is licensed under AGPL-3.0. That matters if you modify the source and offer it to users over a network, because the AGPL's network clause is broader than the GPL's. Running the unmodified binary on your own servers is not the scenario the network clause targets, but if you plan to embed Kula in a product or a hosted service, read the licence text rather than a summary. Nothing here is legal advice.

The repository is not archived, and the last push was on 2026-07-29, which is under two months before the date of this writing. Releases are frequent: 0.18.6 on 2026-07-11, 0.18.7 on 2026-07-26 and 0.18.8 on 2026-07-29. That cadence means upgrades arrive often enough that you should decide on a policy rather than upgrade ad hoc. The upgrade cost itself is low by design: the binary is self-contained, and the only state is the ring-buffer directory, which in Docker lives in the kula_data volume and in a manual install sits under the data path named in config.yaml. Copy that directory before an upgrade if the history matters to you, since the README does not document a downgrade path for the binary data format. The dependency list in go.mod is small and mostly Charm libraries for the TUI, database drivers for the application collectors, gorilla/websocket, go-landlock, and golang.org/x packages, which keeps the supply-chain surface modest compared with a stack that pulls in a full metrics server.

Running the local AI assistant without sending data anywhere

The AI assistant is the feature most likely to be misunderstood. It is not a hosted service. When Ollama is enabled in config.yaml, a robot button appears in the dashboard header, and all inference runs locally through the Ollama API. The panel supports multiple conversation threads, a model selector that can switch between any locally available Ollama model mid-session, streaming responses with markdown rendering, and a draggable, resizable layout.

The interesting part is the tool calling. The model can invoke a get_metrics tool to pull metrics on demand, with up to five rounds per turn, and clicking the assistant icon on a chart card opens a session pre-loaded with that chart's recent data as CSV. That design keeps the model grounded in the host's actual numbers rather than in whatever it remembers about Linux in general. It also means the assistant is only as useful as the local model you run and the metrics you point it at. The README does not describe any guardrails on tool-call loops beyond the five-round cap, so treat the panel as an operator convenience, not as an autonomous agent. If you do not enable Ollama, the feature is simply absent and the rest of Kula is unaffected.

Editorial conclusion

Adopt Kula when you want per-second Linux telemetry on a host without standing up Prometheus, a database or an agent package tree, and when a rolling history of roughly the configured ring-buffer sizes is enough. Skip it if you need long-term retention, cross-host querying or an alerting pipeline beyond the built-in clock sync, low entropy and system overload alerts. Before trusting it in production, verify the sha256 checksum published next to the release tarball, check that the default data paths in config.yaml point at storage with the capacity you expect, and confirm on one host that the WebSocket dashboard updates and that the Prometheus exporter endpoint scrapes cleanly.

Frequently asked questions

Does Kula need a database or any external dependency?

No. The README describes Kula as a single binary with zero dependencies and no external databases, and the storage engine writes metrics into fixed-size binary files that wrap around when full. The only state to manage is the ring-buffer data directory.

How much history can Kula keep?

Retention is set by the tier sizes rather than by a time limit: Tier 1 defaults to 250 MB of raw 1-second samples, Tier 2 to 150 MB of 1-minute aggregations, and Tier 3 to 50 MB of 5-minute aggregations. When the files fill, new data overwrites the oldest entries, so the README does not promise a fixed number of days.

Can Kula be scraped by Prometheus?

The README lists a Prometheus exporter endpoint among the dashboard features, so Kula can be scraped into an existing observability stack. That is separate from Kula's own REST API and WebSocket endpoint, which serve the embedded dashboard.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/c0m4r-kula.svg)](https://hysenlabs.com/projects/c0m4r-kula)