c0m4r/kula

Gokula.ovh
Linux

Lightweight, self-contained Linux® server monitoring tool

gogolanglinuxmonitoringmonitoring-toolmonitoring-toolsreal-time-monitoringtuiwebuilinux-server-monitoringserver-monitoringlinux-monitoring
Star 增长趋势
Star
1.3k
Forks
65
周增长
+-1
Issues
1
1.1k1.2k1.3k
26年3月26年5月26年7月26年9月
制品库Go Modules
README
image

K U L A

Lightweight, self-contained Linux® server monitoring tool.

Linux Go JS Bash License: GPL v3

🌏 Website | 👀 Demo | 🐋 Docker Hub

Zero dependencies. No external databases. Single binary. Just deploy and go.

image

📦 What It Does

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.


🪩 How It Works

    ╭──────────────────────────────────────────────╮
    │                  Linux Kernel                │
    │      /proc/stat  /proc/meminfo  /sys/...     │
    ╰───────────────────────┬──────────────────────╯
                            │ Read every 1s
                            ▼
    ╭──────────────────────────────────────────────╮
    │                   Collectors                 │
    │        (CPU, Mem, Net, Disk, System)         │
    ╰───────────────────────┬──────────────────────╯
                            │ Live Data
         ╭──────────────────┼─────────────────────╮
         ▼                  ▼                     ▼
╭─────────────────╮  ╭────────────────╮  ╭─────────────────╮
│ Storage Engine  │  │   Web Server   │  │   TUI Terminal  │
╰───┬─────────┬───╯  ╰──────┬─────────╯  ╰─────────────────╯
    │         │             │
    │         ╰──(History)──┤              ╭───────────────╮
    │                       ╰──(HTTP/WS)─► |   Dashboard   |
    ▼                                      ╰───────────────╯
╭──────────┬──────────┬──────────╮
│  Tier 0  │  Tier 1  │  Tier 2  │
│    1s    │    1m    │    5m    │
│  250 MB  │  150 MB  │  50 MB   │
╰──────────┴──────────┴──────────╯
 Ring-buffer binary files
 with circular overwrites

Storage Engine

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:

  • Tier 0 — Raw 1-second samples (default 250 MB)
  • Tier 1 — 1-minute metric rollups (default 150 MB)
  • Tier 2 — 5-minute metric rollups (default 50 MB)

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. Legacy rollups remain readable but do not advertise Min/Max as valid.

HTTP server

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, and hashed-at-rest session persistence. Authenticated API access can also use a bearer session token via the Authorization header.

Dashboard

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:

  • Live/Back/Forward/Zoom out navigation with exact shareable ranges
  • Straight historical lines with trusted Min–Max bands and explicit gaps
  • Bucket-aware tooltips and Local/UTC timestamps, with secondary choices in Customization
  • Drag, modifier-wheel, touch/pinch, and keyboard pan/zoom plus a shared pinnable crosshair
  • Accessible chart names and keyboard exploration; Data tables and CSV are opt-in
  • Chart updates limited to the viewport, with plot-width sampling and full-range live refreshes
  • Focus mode to display only specific charts and request only their history sections
  • Configurable Y-axis bounds (Manual limits or Auto-detect)
  • Per-device selectors for Network, Disk I/O, and Thermal monitoring
  • Grid / stacked list layout toggle
  • Alert system for clock sync, low entropy, and system overload
  • Modern aesthetics with light/dark theme support
  • Optional AI assistant powered by a local Ollama model (see below)
  • Prometheus exporter endpoint for scraping into existing observability stacks

AI Assistant

Kula features an AI assistant via Ollama.

When Ollama is enabled in config.yaml, a 🤖 button appears in the dashboard header. The panel supports:

  • Multi-session conversations — open independent threads and switch between them
  • Per-chart analysis — click the 🤖 icon on any chart card to open a session pre-loaded with that chart's recent data as CSV
  • Agentic tool calling — the model can call get_metrics to pull metrics on demand (up to 5 rounds per turn)
  • Model selector — switch between any locally available Ollama model mid-session
  • Draggable & resizable panel — drag by the header, resize from the bottom-right grip
  • Streaming responses with markdown rendering

All AI inference runs locally through Ollama API.


💾 Installation

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.

Guided

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

Guided (verify installer)

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}

Standalone

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
./kula

Docker

Temporary, no persistent storage:

docker run --rm -it --name kula --pid host --network host -v /proc:/proc:ro c0m4r/kula:latest

With 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 kula

Debian / Ubuntu (.deb)

wget 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 kula

RHEL / Fedora / CentOS / Rocky / Alma (.rpm)

wget 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 kula

Arch Linux / Manjaro (AUR)

https://aur.archlinux.org/packages/kula

git clone https://aur.archlinux.org/kula.git
cd kula
makepkg -si

Snap

sudo snap install kula

The 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.

Build from Source

git clone https://github.com/c0m4r/kula.git
cd kula
./addons/build.sh

💻 Usage

Quick Start

Starting Kula is as simple as running:

./kula

Dashboard 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"
./kula

TUI

./kula tui

The 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.

Inspect storage

./kula inspect

The 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.

List disks

./kula disks

Lists 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.

Prometheus metrics

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.

Persistent disk identities

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 sysfs directly, preferring WWID, NVMe namespace UUID/NGUID/EUI, then vendor/model/serial. NVMe serial fallback includes the namespace number. No external tools or raw block-device access are required.

Automatic discovery needs no configuration change. To monitor particular drives, copy IDs from kula disks (or disk.devices[].id in /api/current) into collection.devices. Legacy kernel names still work as filters but may select a different drive after reboot. Explicit partitions use the parent ID followed by :part:<number>; this tracks a numbered partition on that drive, not a filesystem across repartitioning. Filesystem capacity history continues to follow mount points.

Disks without usable identifiers, or with duplicate identifiers, remain visible as unstable with a warning and kernel-name history. Their API id is absent; cross-reboot physical identity cannot be guaranteed for these devices. Duplicate paths to the same storage are treated as ambiguous, not combined as multipath I/O. Containers must expose the corresponding host sysfs metadata to obtain stable IDs.

Existing tier files remain readable. Old records have no physical identity and stay in separate name-based series: Kula cannot safely assign their history to today's drives. New physical-disk series therefore begin at upgrade. The binary format extension is backward-readable by the new version; older binaries cannot read the newly extended records, so retain a pre-upgrade backup if downgrading.

Health endpoints

Kula exposes lightweight liveness endpoints at:

http://localhost:27960/health
http://localhost:27960/status

Both return:

200 OK
kula is healthy

Authentication (Optional)

# Generate password hash
./kula hash-password

# Add the output to config.yaml under web.auth

When authentication is enabled, Kula issues a random session token after login, stores only its hash on disk, and validates requests by token expiry/validity rather than binding sessions to client IP or User-Agent.

Service Management

Init system files are provided in addons/init/:

# systemd
sudo cp addons/init/systemd/kula.service /etc/systemd/system/
sudo systemctl enable --now kula

# OpenRC
sudo cp addons/init/openrc/kula /etc/init.d/
sudo rc-update add kula default

# runit
sudo cp -r addons/init/runit/kula /etc/sv/
sudo ln -s /etc/sv/kula /var/service/

⚙️ Configuration

All settings live in config.yaml. See config.example.yaml for defaults.


🧰 Development

# Lint + test suite
./addons/check.sh

# Build
./addonsh.build.sh

# Build dev (Binary size: ~20MB)
CGO_ENABLED=0 go build -o kula ./cmd/kula/

# Build prod (Binary size: ~14MB, xz: ~4MB)
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -buildvcs=false -o kula ./cmd/kula/

Updating Dependencies

To safely update only the Go modules used by Kula to their latest minor/patch versions, and prune any unused dependencies:

./addons/go_modules_updates.py
go get -u ./...
go mod tidy

Testing & Benchmarks

# Run unit tests with race detector
go test -race ./...

# Run the full storage benchmark suite (default: 3s per bench)
./addons/benchmark.sh

# Generate a repeatable realistic history fixture in an isolated directory
KULA_DIRECTORY=/tmp/kula-mock go run ./cmd/gen-mock-data \
  -config config.example.yaml -duration 6h -yes \
  -seed 1263881281 -start 2026-09-07T00:00:00Z

# Python scripts formatter and linters
black addons/*.py
pylint addons/*.py
mypy --strict addons/*.py

Cross-Compile

./addons/build.sh cross    # builds amd64, arm64, riscv64

Debian / Ubuntu (.deb)

./addons/build_deb.sh
ls -1 dist/kula-*.deb

Arch Linux / Manjaro (AUR)

./addons/build_aur.sh
cd dist/aur && makepkg -si

RHEL / Fedora / CentOS / Rocky / Alma (.rpm)

./addons/build_rpm.sh
ls -1 dist/kula-*.rpm

Docker

./addons/docker/build.sh
docker compose -f addons/docker/docker-compose.yml up -d

Snap

Requires snapcraft and a build backend (LXD recommended):

snap install snapcraft --classic
snap install lxd
lxd init --auto
./addons/build_snap.sh            # host arch, into dist/
./addons/build_snap.sh cross      # cross-build amd64/arm64/riscv64 locally
ls -1 dist/kula-*.snap

🔒 Privacy

Privacy is a core pillar, not an afterthought.

Kula is built for privacy-conscious infrastructure. It is a completely self-contained binary that requires no cloud connection and no third-party APIs. Designed to function perfectly in air-gapped networks, Kula never sends metadata to external servers, never serves advertisements, and requires no user registration. Your monitoring starts and ends on your infrastructure, exactly where it should be.


📖 License

GNU Affero General Public License v3.0


🫶 Attributions

相关仓库
avelino/awesome-go

A curated list of awesome Go frameworks, libraries and software

GoGo ModulesawesomeMIT Licensegolanggolang-library
awesome-go.com
183.6k13.5k
ollama/ollama

Get up and running with Kimi-K2.6, GLM-5.2, MiniMax, DeepSeek, gpt-oss, Qwen, Gemma and other models.

GoGo ModulesMIT Licensellamallm
ollama.com
180.5k17.8k
golang/go

The Go programming language

GoGo ModulesBSD 3-Clause "New" or "Revised" Licenseprogramming-languagelanguage
go.dev
138k19.4k
kubernetes/kubernetes

Production-Grade Container Scheduling and Management

GoGo ModulesApache License 2.0kubernetesgo
kubernetes.io
126.9k44k
fatedier/frp

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

GoGo ModulesApache License 2.0proxyreverse-proxy
109.3k15.2k
gohugoio/hugo

The world’s fastest framework for building websites.

GoGo ModuleslibraryApache License 2.0gohugo
gohugo.io
89.8k8.4k
gin-gonic/gin

Gin is a high-performance HTTP web framework written in Go. It provides a Martini-like API but with significantly better performance—up to 40 times faster—thanks to httprouter. Gin is designed for building REST APIs, web applications, and microservices.

GoGo ModuleslibraryMIT Licenseservermiddleware
gin-gonic.com
89.2k8.7k
syncthing/syncthing

Open Source Continuous File Synchronization

GoGo ModulesappMozilla Public License 2.0synchronizationgo
syncthing.net
88.4k5.5k
junegunn/fzf

:cherry_blossom: A command-line fuzzy finder

GoGo ModulescliMIT Licensefzfgo
junegunn.github.io/fzf/
82.9k2.9k
grafana/grafana

The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.

TypeScriptnpmGNU Affero General Public License v3.0grafanamonitoring
grafana.com
76.7k14.7k
caddyserver/caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

GoGo ModulesApache License 2.0goweb-server
caddyserver.com
75.6k4.9k
moby/moby

The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems

GoGo ModulesApache License 2.0dockercontainers
mobyproject.org
72.1k19.2k