Self-hosted, phone-friendly hardware monitoring dashboard for a single Linux machine. Single Go binary, no runtime dependencies, embedded HTML frontend, LAN-only.
Reads sensors directly from sysfs / procfs and serves a JSON endpoint plus
a dark, gauge-based dashboard that polls every second.
Linux only. All sensor reads go through sysfs / procfs and the active
hardware is auto-detected at startup — CPU model, GPU name (via Vulkan / sysfs
/ pci.ids), and the busiest network interface.
| Component | Supported |
|---|---|
| CPU temp | Intel (coretemp), AMD (k10temp, zenpower) |
| CPU power | Intel only (RAPL via powercap); AMD not implemented |
| GPU | AMD (amdgpu, radeon), NVIDIA open (nouveau) |
| RAM | any (/proc/meminfo) |
| Network | any (non-loopback iface with most total rx at startup) |
Not supported: the NVIDIA proprietary driver doesn't expose
gpu_busy_percent in sysfs, so GPU usage / temps won't appear there.
Developed and tested on Fedora 44 with an Intel i5-12400F and AMD RX 9070 XT.
- CPU: usage %, package temp (
coretemp), package power (intel-rapl) - GPU: busy %, edge / junction / VRAM temps, VRAM used/total, fan RPM, power
- RAM: used / total / cached / swap
- Net: rx/tx bytes per second on the primary interface
Any field that can't be read returns null instead of crashing the endpoint.
go build -o blutaugur .Requires Go 1.26+. No third-party Go dependencies.
./blutaugur # listens on 0.0.0.0:7171 (all interfaces)
./blutaugur -listen 127.0.0.1:7171 # localhost only (e.g. behind a reverse proxy)
./blutaugur -listen 192.168.1.5:8080GET /— dashboardGET /api/metrics— JSON metrics
The host's DHCP IP can change, so don't bookmark the raw address. If the
machine runs avahi-daemon (mDNS, default on most desktop Linux), reach it by
hostname instead — survives every IP change, no router config:
http://<hostname>.local:7171
Works natively on iOS and on Android 12+. If mDNS is unreliable on your network, add a DHCP reservation in your router to pin the IP.
There is no authentication, no authorization, and no TLS. Anyone who can reach the listen address can read your full hardware telemetry (CPU/GPU model, load, temperatures, RAM/swap usage, network throughput, uptime). This is by design — it's a personal dashboard for a trusted home LAN.
- Do not expose it to the public internet. No port-forwarding, no DMZ.
- The default
0.0.0.0:7171binds every interface. On a laptop that roams onto untrusted networks (cafés, conferences), bind to a specific interface or to127.0.0.1with-listen, or firewall the port. - For remote access, put it behind something that does provide auth/TLS — a reverse proxy (Caddy/nginx + basic auth) or a private overlay network (Tailscale/WireGuard) — rather than opening the port directly.
Reading CPU package power requires a one-time udev rule to make
/sys/class/powercap/intel-rapl:*/energy_uj group-readable. See
RAPL.md. Without it, cpu.power_w is reported as null; the
rest of the dashboard works fine.
~/.config/systemd/user/blutaugur.service (set the two paths to wherever you
built the binary; %h is your home directory):
[Unit]
Description=Blutaugur PC dashboard
After=network.target
[Service]
Type=simple
WorkingDirectory=%h/blutaugur
ExecStart=%h/blutaugur/blutaugur
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.targetEnable:
systemctl --user daemon-reload
systemctl --user enable --now blutaugur
loginctl enable-linger "$USER" # start without a login session.
├── main.go # entry point, HTTP server
├── handlers.go # /api/metrics + / handlers, JSON schema
├── metrics.go # CPU / GPU / RAM / net sensor reads
├── discover.go # one-time hardware discovery (hwmon, drm, RAPL, net iface)
├── templates/
│ └── index.html # embedded single-file dashboard
└── RAPL.md # CPU power setup
LAN-only tool. No TLS, no auth, no historical data, no per-core breakdown.
WTFPL — do what the fuck you want to.

