Lightweight, self-contained Linux® server monitoring tool
Lightweight, self-contained Linux® server monitoring tool
Kula collects system metrics every second by reading directly from /proc and /sys,
stores them in a built-in tiered ring-buffer storage engine, and serves them through a real-time Web UI dashboard and a terminal TUI.
| Metric | What's Collected |
|---|---|
| CPU | Total usage (user, system, iowait, irq, softirq, steal) + core count |
| GPU | Load, Power consumption, VRAM |
| Load | 1 / 5 / 15 min averages, running & total tasks |
| Memory | Total, free, available, used, buffers, cached, shmem |
| Swap | Total, free, used |
| Network | Per-interface throughput (Mbps), packets/s, errors, drops; TCP errors/s, resets/s, retrans, established; sockets |
| Disks | Per-device I/O (read/write bytes/s, reads/s, writes/s IOPS); filesystem usage |
| System | Uptime, entropy, clock sync, hostname, logged-in user count |
| Processes | Running, sleeping, blocked, zombie counts |
| Self | Kula's own CPU%, RSS memory, open file descriptors |
| Thermal | CPU, GPU and Disk temperatures |
| Battery | /sys/class/power_supply - power supply / battery status |
| Containers | Docker, podman, raw cgroups |
| Applications | PostgreSQL, MySQL/MariaDB, nginx, apache2 |
| Custom | Monitor anything with custom metrics |
Note: Monitoring NVIDIA GPUs might require additional setup. Check GPU monitoring.
The dashboard's System Info button opens a dedicated current-hardware page: motherboard and firmware, CPU topology and caches, memory modules, drives and filesystem usage, network addresses and utilization, PCI/USB devices, sensors, and power supplies. A friendly summary comes first, while low-level identifiers and counters stay available under technical details. It refreshes while open and works independently of chart history. See System Info.
…Kula is powered by a custom-built, high-performance ring-buffer storage system that writes metrics directly into fixed-size binary files. Because the files have a strict maximum capacity, new data seamlessly wraps around to overwrite the oldest entries. On startup, Kula restores the latest-sample cache and reconstructs any pending aggregation buffers so it can resume serving recent data and continue tier rollups after a restart.
To maximize efficiency, Kula employs a multi-tiered architecture that intelligently downsamples older data:
Rollups use explicit per-field policies: sampled gauges and rates are duration-weighted, monotonic counters and metadata retain their latest value, and Min/Max are per-series extrema. Dynamic devices and applications are matched by stable identity, so a missing member is not fabricated as zero. Existing binary history needs no migration: a compatibility layer exposes legacy Min/Max for supported CPU, load, used-memory and used-swap fields. Unsupported series or intervals appear as gaps when Min/Max is selected, with an explanation on the chart. Newly collected extrema remain available even in views that also contain older history. Unavailable readings remain gaps in every aggregation, and filesystem tooltip percentages and byte counts use the same selected aggregation.
Scheduled backups are optional: backup.enabled copies the tier files into a timestamped
directory under /backup on a crontab schedule, with a configurable
per-tier depth, retention window, and gzip compression.
The HTTP server on backend exposes a REST API and a WebSocket endpoint for live streaming.
Authentication is optional. When enabled, Kula uses Argon2id password hashing, secure session cookies, token-only session validation with sliding expiration bounded by an absolute session lifetime (session_max_lifetime, 7 days by default), and hashed-at-rest session persistence. Authenticated API access can also use a bearer session token via the Authorization header.
An expired live session returns the dashboard to login; signing in reloads the selected history range.
The frontend is a single-page application embedded in the binary. Built on Chart.js with custom SVG gauges, it connects via WebSocket for live updates and falls back to history API for longer time ranges. Features include:
Kula features an AI assistant via Ollama.
When Ollama is enabled in config.yaml, a button appears in the dashboard header. The panel supports:
get_metrics to pull metrics on demand (up to 5 rounds per turn)All AI inference runs locally through Ollama API.
Kula was built to have everything in one binary file. You can just upload it to your server and not worry about installing anything else because Kula has no dependencies. It just works out of the box! It is a great tool when you need to quickly start real-time monitoring.
Example installation methods for amd64 (x86_64) GNU/Linux.
Check Releases for ARM and RISC-V packages.
Note: Never thoughtlessly paste commands into the terminal. Even checking the checksum is no substitute for reviewing the code.
bash -c "$(curl -fsSL https://raw.githubusercontent.com/c0m4r/kula/refs/heads/main/addons/install_v2.sh)"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}wget https://github.com/c0m4r/kula/releases/download/0.19.0/kula-0.19.0-amd64.tar.gz
echo "5ce7ef7a17448d31ea0828d0125bc517c4f241cba4973458c646919bc921f701 kula-0.19.0-amd64.tar.gz" | sha256sum -c || rm -f kula-0.19.0-amd64.tar.gz
tar -xvf kula-0.19.0-amd64.tar.gz
cd kula
./kulaTemporary, no persistent storage:
docker run --rm -it --name kula --pid host --network host -v /proc:/proc:ro c0m4r/kula:latestWith persistent storage:
docker run -d --name kula --pid host --network host -v /proc:/proc:ro -v kula_data:/app/data c0m4r/kula:latest
docker logs -f kulawget https://github.com/c0m4r/kula/releases/download/0.19.0/kula-0.19.0-amd64.deb
echo "f2e3f74e33349789fff1b35cc27bfacb5696e70b38cdcf440f990eadc217dfac kula-0.19.0-amd64.deb" | sha256sum -c || rm -f kula-0.19.0-amd64.deb
sudo dpkg -i kula-0.19.0-amd64.deb
journalctl -f -t kulawget https://github.com/c0m4r/kula/releases/download/0.19.0/kula-0.19.0-x86_64.rpm
echo "be8a0ea56dda6d1614b983cb694f63e423d81793ee0fea69fbb0a26c0d580c3b kula-0.19.0-x86_64.rpm" | sha256sum -c || rm -f kula-0.19.0-x86_64.rpm
sudo rpm -i kula-0.19.0-x86_64.rpm
journalctl -f -t kulahttps://aur.archlinux.org/packages/kula
git clone https://aur.archlinux.org/kula.git
cd kula
makepkg -sisudo snap install kulaThe snap uses strict sandbox so by default Kula features will be limited to the basics, which can be extended with snap connect.
See Snap Wiki for the full guide.
git clone https://github.com/c0m4r/kula.git
cd kula
./addons/build.shStarting Kula is as simple as running:
./kulaDashboard will be available at: http://localhost:27960 (or :8080 if you're using earlier versions)
You can change default port and listen address in config.yaml or using environment variables:
export KULA_LISTEN="127.0.0.1"
export KULA_PORT="27960"
./kulaThe default command is serve (./kula serve). Global flags are -config to
select another configuration file and -version (or -v) to print the version.
./kula tuiThe terminal monitor is designed for a fast live read rather than as a second web dashboard. Its overview keeps CPU, memory, traffic, storage pressure, host health, and short-term trends visible in a standard terminal. Numbered tabs switch between the Overview, CPU, Memory, Network, Storage, Processes, and GPU views.
./kula inspectThe report includes each tier's configured resolution, current recorded range,
estimated maximum coverage, and ETA until the tier first fills. Estimates assume
continuous collection and use the average encoded record size observed so far.
Use ./kula inspect --verbose to also decode and print the latest recorded
metrics from every tier.
./kula disksLists available disks and partitions supported by Kula with their persistent IDs.
Copy IDs into collection.devices to select drives across reboots. The command
ignores configured device filters and works without a config file or running
daemon. Devices without a unique ID are marked unavailable (unstable kernel name).
Virtual, logical and optical devices excluded by the disk collector are omitted.
See: Prometheus metrics for more info.
Disk I/O and temperature metrics use the persistent disk ID as the device label
value. kula_disk_info{device="...",kernel_name="sda",identity_source="wwid"} 1
maps that ID to the current kernel name. Unidentified disks use device="kernel:sda"
and identity_source="kernel". Upgrading to 0.20.0 starts new disk metric series;
update dashboards and alert rules that filter by old device="sda" values.
Kula tracks disk I/O and temperatures by hardware identity so history follows the
drive when Linux changes names such as sda or nvme0n1. The JSON API retains
name as the kernel name and adds id; selectors show the name with the ID in
their tooltip. Discovery reads
No open issues yet, or sync has not completed.