> ## Content Index
> Fetch the complete content index at: https://blog.bsd-unix.net/llms.txt
> Use this file to discover other available public pages before exploring further.

# Heliograph: rebuilding SmokePing in Go
- URL: https://blog.bsd-unix.net/heliograph-rebuilding-smokeping-in-go/
- Published: 2026-09-10T16:36:09.000Z
- Updated: 2026-09-10T16:52:09.000Z
- Description: A from-scratch reimplementation of SmokePing in Go and TimescaleDB — the smoke graphs and pluggable probes, minus the Perl and RRD, plus multi-vantage federation and browser-editable config.
- Author: Bryan Seitz
- Tags: Projects, Networking, Go

**Source:** [github.com/seitzbg/heliograph](https://github.com/seitzbg/heliograph?ref=blog.bsd-unix.net)

SmokePing has been around for twenty years and still does one thing better than anything else: its "smoke" latency graph. The percentile bands show jitter. The loss-coloured median line shows drops. Together they tell you how a path behaves over time instead of just whether it is up. I did not want the rest of it though. It is Perl. It stores data in RRD files. Changing the config means editing text on the box and reloading. So I rewrote it. Heliograph is that graph in Go, backed by TimescaleDB.

It keeps the smoke graphs and the pluggable probe model. It drops the Perl and the RRD files. It adds two things SmokePing does not have: multi-vantage federation and a browser-editable config. The daemon is still called `smoked`.

## Why Go

SmokePing forks a process per probe. Go's goroutines make parallel probing with per-target timeouts cheap. Heliograph runs one bounded worker pool. Every target gets its own schedule and timeout. Both binaries build with `CGO_ENABLED=0` so the container and FreeBSD builds stay simple.

## The graph

A smoke graph is only trustworthy if it reflects the real spread of round-trip times rather than an average. So Heliograph keeps the full sample array for every round. Each round is one row in a TimescaleDB hypertable. Loss is stored as SQL `NULL` rather than zero. The percentile bands get computed at query time. Hourly and daily continuous aggregates keep long time ranges fast. The dashboard redraws the graph on an HTML canvas. Nested percentile bands darken toward the median over an eight-bucket loss-coloured line, and it follows the site theme.

## Probes

There are eight built-in probes behind a self-registering plugin registry: ICMP, an `fping` wrapper, TCP connect, DNS, HTTP time-to-first-byte, SSH banner timing, IRTT, and NTP clock offset. The native ping is pure Go. It uses an unprivileged datagram socket with a raw-socket fallback, so there is no `fping` dependency and no `setcap` step in the common case.

```bash
# Measure a demo target set and print a table
go run ./cmd/smoked -rounds 2 -pings 10

# Serve the live dashboard + JSON API, persisting to TimescaleDB
go run ./cmd/smoked -serve -addr :8087 \
  -dsn 'postgres://user:pass@host:5432/smoke?sslmode=disable'
```

## Federation

Remote `smoke-agent` collectors report to the hub and overlay a median line per vantage. You can watch one target from several networks at once and see where the paths split. There are no API keys. `smoked` bootstraps its own certificate authority and issues each vantage a client certificate that acts as its identity. That runs over mutual TLS on a listener that is never proxied. Revoking a vantage means removing its name. Its next request is then rejected even though the certificate is still valid.

## Config in the database

The target tree lives in the database. You edit it from a Config tab in the browser with drag-to-reorder. Every target keeps a stable server-assigned id. Renaming or moving a node preserves its graph history and its alert state, because reconciliation happens by identity rather than by name.

## An MCP server

`smoked mcp` exposes thirteen tools so an assistant can diagnose a path or edit the config. The write path is narrow on purpose. The staging and review tools work on an in-process buffer that the daemon's own parser validates. Only `config_apply` writes anything, and it sits behind `-admin-pass`.

## Where it is

Heliograph is at v2.2.0 under the MIT licence. There are prebuilt GHCR images, native FreeBSD binaries with rc.d scripts, and a SmokePing importer (`smoked import smokeping`, with `--history` to backfill old RRD data). It is at [github.com/seitzbg/heliograph](https://github.com/seitzbg/heliograph?ref=blog.bsd-unix.net). If you have a tired SmokePing box the migration is meant to be uneventful.