Lightweight, self-contained Linux® server monitoring tool.
🌏 Website | 👀 Demo | 🐋 Docker Hub
Zero dependencies. No external databases. Single binary. Just deploy and go.
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.
╭──────────────────────────────────────────────╮
│ 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 1 │ Tier 2 │ Tier 3 │
│ 1s │ 1m │ 5m │
│ 250 MB │ 150 MB │ 50 MB │
╰──────────┴──────────┴──────────╯
Ring-buffer binary files
with circular overwrites
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:
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.
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.18.3/kula-0.18.3-amd64.tar.gz
echo "b1196aee70709215586f818e2ee377bfa1ceb5b182020579199898aa717e253b kula-0.18.3-amd64.tar.gz" | sha256sum -c || rm -f kula-0.18.3-amd64.tar.gz
tar -xvf kula-0.18.3-amd64.tar.gz
cd kula
./kula
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
wget https://github.com/c0m4r/kula/releases/download/0.18.3/kula-0.18.3-amd64.deb
echo "113d710916941a9d98e6b397ea323fc5ea61133d2485ae790d6d61edbb829b9c kula-0.18.3-amd64.deb" | sha256sum -c || rm -f kula-0.18.3-amd64.deb
sudo dpkg -i kula-0.18.3-amd64.deb
journalctl -f -t kula
wget https://github.com/c0m4r/kula/releases/download/0.18.3/kula-0.18.3-x86_64.rpm
echo "fcbab15bcab9fe097fde89332772c322105379549caff9c7e6fbd3883f2520de kula-0.18.3-x86_64.rpm" | sha256sum -c || rm -f kula-0.18.3-x86_64.rpm
sudo rpm -i kula-0.18.3-x86_64.rpm
journalctl -f -t kula
https://aur.archlinux.org/packages/kula
git clone https://aur.archlinux.org/kula.git
cd kula
makepkg -si
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.
git clone https://github.com/c0m4r/kula.git
cd kula
./addons/build.sh
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
./kula tui
./kula inspect
See: Prometheus metrics for more info.
Kula exposes lightweight liveness endpoints at:
http://localhost:27960/health
http://localhost:27960/status
Both return:
200 OK
kula is healthy
# 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.
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/
All settings live in config.yaml. See config.example.yaml for defaults.
# 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/
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
# Run unit tests with race detector
go test -race ./...
# Run the full storage benchmark suite (default: 3s per bench)
./addons/benchmark.sh
# Python scripts formatter and linters
black addons/*.py
pylint addons/*.py
mypy --strict addons/*.py
./addons/build.sh cross # builds amd64, arm64, riscv64
./addons/build_deb.sh
ls -1 dist/kula-*.deb
./addons/build_aur.sh
cd dist/aur && makepkg -si
./addons/build_rpm.sh
ls -1 dist/kula-*.rpm
./addons/docker/build.sh
docker compose -f addons/docker/docker-compose.yml up -d
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 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.
GNU Affero General Public License v3.0