v0.2.0 · MIT · self-hosted

Topophany — the appearance of a place

From where, via which path, reaching what — and on what evidence.

Self-hosted monitoring of network topology and service availability, read in the terminal. One Go binary with no dependencies is the client, the collector and the observer. It tells you what was measured, from where and how recently. It never shows a check as green that hasn't passed.

go install github.com/WhitenWhiten/topophany/cmd/topo@latest

01 The terminal UI

Is anything wrong, and where?

The Overview answers before you read a word: a verdict, a map of every place and path, and the short list of what needs attention. Below is topo preview recorded frame by frame from the TUI's own renderer. The evidence is synthetic, but it goes through the real state engine.

~ topo preview replay · 140×42
A recording of the Topophany terminal UI in preview mode, in chapters that can be chosen below.

An outage arrives

All is well until x switches the preview to a scenario where the DMIT line is blocked from mainland China.

1–9 chapters m map v view x scenario space pause, or click the tabs inside the terminal. Run topo preview to try the real thing.

02 Semantics

Evidence, not colors

Health, the source of the evidence and its freshness are separate fields. Nothing turns green without a passing check, a service nobody monitors stays unknown, and a cached view says so.

Nothing is green by default

serviceevidencestate
●Main siteCloudflare ⇢ S1http 200 · 4s agoanswered by Cloudflare NRT · cache DYNAMIC
○Home panelnotes onlyregistered, not monitoredno check configuredunknown
✖VLESS+Reality entryDMIT · Los Angelestcp timeout · 6s agofrom 长沙 MacBook · 3 of 3 samplesDOWN

The state column stays empty for healthy rows, so problems are the only words lit. A service that is registered but has no check is not up. It is registered, not monitored.

Vantage points are explicit

Changshaworker · MacBook New Yorkworker · S1 Los AngelesDMIT entry tcp timeout ×3 http 200 · 182 ms verdict fault on the path from Changsha · server up

Each observer measures from where it actually is. A failure seen from home is a fault on that path, not a server outage, and the incident shows which observers still get through.

The edge answered

visitors Cloudflare NRT S1 origin
● HTTP 521 · edge up ▲ affected

Behind Cloudflare, Vercel or another CDN, any answer from the edge, even an error page, proves the edge. The origin counts only a passing response the edge did not serve from cache. The probe records which edge answered and from where.

A guess is labeled a guess

FAILED CHECKS
m-exit-dmit-aaitr

OTHER-OBSERVER RESPONSE EVIDENCE
w-exit-s2-aaitr, w-exit-s2-qqpr

HYPOTHESIS (NOT A FINDING)
source/path-specific interference, filtering or
routing fault is possible; blocking authority and
untested protocols are not established
No inference about all IP ports, untested UDP,
physical power or GFW authority.

Incidents carry the failed checks and what other observers still see. Nothing is inferred about ports or protocols that nobody tested.

What it will not claim

A TCP connection is accepted
Only that a connection was established. Not the application protocol, not proxy authentication, not the whole path.
A request succeeds, but the egress IP is outside policy
A policy outcome. Reachability and egress policy are judged separately.
An observer stops reporting
Its view goes stale, then unknown. Remote assets are not marked down.
The primary path fails, a candidate succeeds
The candidate is available and redundancy is degraded. It does not claim production traffic has switched.
The collector is unreachable
The cached view is kept, marked CACHED, and every item turns unknown.

03 Architecture

One binary, three roles

No CGO, no database daemon, no Node.js, and zero external Go modules. topo is the terminal client, the collector and the observer, and closing the client does not stop monitoring.

  • binaryclient, collector and worker
  • external Go modulesthe standard library, nothing else
  • release buildsLinux, macOS, Windows · amd64, arm64
  • tabsat 30×10 and up, mouse included

Two collectors, no consensus theatre

Workers deliver to both collectors on their own and buffer in a bounded outbox. Duplicates are dropped by observation ID, and records from a mismatched configuration revision are quarantined.

Read-only by design

There is no remote configuration API, no remote shell and no automated remediation. Topology lives in reviewed local JSON, edited with topo edit and checked with topo validate.

Bounded, and says so

By default it keeps 24 hours or 20,000 raw records and gives the worker outbox 32 MiB. When a quota fills, probing stops with an error rather than dropping evidence.

04 Probes

What it measures

Native probes and explicit proxy chains, plus read-only adapters for the tools already on your hosts.

Native probes

  • HTTP · status, body, headers, egress IP
  • TCP
  • TLS · certificate validation
  • SSH banner
  • DNS A/AAAA
  • UDP echo · random nonce
  • ICMP · IPv4

Proxy chains

  • HTTP CONNECT
  • HTTPS CONNECT
  • SOCKS5 · remote DNS
  • OpenSSH -W · verified hosts

Read-only adapters

  • Mihomo
  • Tailscale
  • WireGuard

Edges and platforms

  • Cloudflare · Workers, Pages
  • Vercel
  • Supabase

05 Install

Up in a minute

Prebuilt archives for Linux, macOS and Windows, or one go install. The demo probes only its own loopback API and generates fresh credentials each time it runs.

go install github.com/WhitenWhiten/topophany/cmd/topo@latest

Needs Go 1.26.9 or newer. Building downloads no modules.

Runs on

systems
Linux, macOS, Windows · amd64, arm64
terminal
100×28 or more recommended, 30×10 at least
color
truecolor, xterm-256, or none under NO_COLOR
services
systemd units for the collector and the worker
storage
a local append-only journal, no database
  1. Look around

    The full TUI on a built-in topology with synthetic evidence. Press x to break something.

    topo preview
  2. Start a collector

    Writes a demo topology and fresh credentials, then serves on 127.0.0.1:7447.

    topo init --dir ./demo topo serve --config ./demo/topology.json \ --auth ./demo/auth.json --data ./demo/collector-data \ --observer demo
  3. Open the TUI

    In another terminal. Later, topo login saves a remote profile, and then plain topo is enough.

    topo --credentials ./demo/credentials.json