topographer

topographer

apps.detail.types.app from FugginOld's Repository

apps.detail.sections.overview

Homelab network and hardware topology dashboard. Scanners and collectors map your machines and your LAN, a pipeline normalizes and enriches the result (vendor lookup, VLAN by subnet, device kind), and the dashboard draws it live in the browser. Reporting agents on other hosts push their own map plus telemetry to this server. Also serves per-host service widgets and live Glances metrics. Point agents at it with: TOPO_SERVER=http://[Unraid-IP]:8770 Host networking is the default on purpose: the ping/arp/nmap collectors need to see the real LAN, and pushes from agents keep their true source IP (each card is labelled by it). Bridge mode works for the dashboard itself but discovery will be blind.

Topographer

Topographer

CI

I never could find a dashboard service I liked. So...using AI, I prompted what I wanted to see. I always wanted to build a network topology but I figured there had to be a way to do it automatically instead of manually running all the commands to compile the network information then piece it together. Same thing with every machine on the network that had a topology to generate as well as a dashboard for that machine. I like it..it works for me. I hope you enjoy it for what it is. - FugginOld

Two topology tools in one repo:

  1. Network topology — auto-discover a homelab network from live sources, normalize into one canonical model, render as an animated HTML dashboard. (the original pipeline, below)
  2. Hardware topology + fleet dashboard — scan each machine's real hardware fabric (CPU, RAM, PCIe lanes, NVMe, NICs with link state, USB, displays) and watch every machine on your network from one live dashboard, with per-host CPU/net/disk telemetry. See HOWTO.md for the full setup.

The repo is the tooling. Your actual topology (IPs, MACs, hostnames, VLAN policy) is a build artifact and is gitignored — see Security.

Hardware topology + fleet dashboard

Map the real hardware of every machine on your network and watch them live:

   Windows PC ─┐  ./agent/report.sh  (or agent\report.ps1)
   Linux box  ─┼──►  topo_server.py on one host  ──►  live dashboard, one card per machine
   Proxmox    ─┘     (POST /api/ingest + telemetry)
  • One server runs python renderers/html/topo_server.py; open http://HOST:8770.
  • Each machine runs an agent that scans its own hardware and pushes its topology and live telemetry (agent/report.sh on Linux, agent/report.ps1 on Windows, or the bootstrap.sh one-liner for a fresh Debian box).
  • Scanners: scanners/make_pc_topo.py (Windows, PnP/CIM) and scanners/make_linux_topo.py (Linux, sysfs/proc). Live metrics: core/local_telemetry.py (real CPU temp on Linux).

Full step-by-step — server firewall, each reporting machine, persistence, naming, tokens, troubleshooting — is in HOWTO.md.

How it works

sources ──▶ collectors ──▶ topo.json ──▶ renderers
(live)      (read-only)     (canonical)       (live dashboard)

Every collector is read-only and emits raw dicts. core/normalize.py merges them into one Topology (deduped by MAC, then reconciled by IP and hostname), core/enrich.py adds vendor/kind, and renderers consume only the canonical model — so you can add outputs without touching collection.

Quick start

pip install -r requirements.txt            # only PyYAML is required
python renderers/html/topo_server.py   # http://localhost:8770

On a Linux host, ./install.sh sets the dashboard up as a systemd service (starts on boot, prints its own URL); ./uninstall.sh removes it. See HOWTO.md.

Open the dashboard and click SCAN NETWORK — with no config at all it ping-sweeps your subnet and, if it doesn't recognise a gateway collector, fingerprints your router and tells you which one to enable (e.g. "gateway 192.168.1.1 looks like UNIFI — add a unifi API key"). Then:

cp config.example.yaml config.yaml         # edit — this file is gitignored
# enable unifi / proxmox / etc. with their API keys, then re-scan

Prefer the CLI? python scanners/make_network_topo.py --config config.yaml writes out/topo.json directly.

Adding a machine to the fleet: right-click any host in the network map → Generate machine topology. If SSH remote-scan is configured it scans over SSH; otherwise it hands you the one-line bootstrap.sh command to run on that host (persistent service, or TOPO_ONCE=1 for a one-off snapshot).

Collectors

Collector Source Adds Needs
unifi UniFi controller API (UCG/UDM) VLAN zones, clients, gateway + WAN, uplinks API key (stdlib, no deps)
proxmox Proxmox VE API VMs + LXC (incl. NAT'd) nested under host API token (PVEAuditor)
pingsweep OS ping + ARP cache live hosts, MAC, vendor — zero install (Windows-friendly)
arpscan arp-scan / nmap -sn live hosts, MAC, vendor arp-scan or nmap (Linux)
opnsense OPNsense REST API VLAN zones, DHCP names, ARP API key/secret
unifi_snmp SNMP LLDP + FDB physical switch-port edges, uplinks net-snmp, SNMP on switch
docker docker ps over SSH containers nested under hosts key-based SSH
tailscale tailscale status --json overlay mesh (tagged ts) tailscale
dns Pi-hole / hosts file friendly names

MAC is the primary join key; nodes are then reconciled by IP and hostname so a host seen by three collectors collapses into one. unifi/proxmox/pingsweep are stdlib-only (no requests); the gateway/API collectors auto-degrade to [] when their source is absent, so enabling several is safe.

Renderer

  • renderers/html/ — animated dashboard (VLAN zones, firewall hub, Tailscale overlay toggle, click-to-isolate). Reads topo.json; refreshes every 30s.

Automation

Runs on a homelab host, not GitHub Actions (Actions can't reach your LAN). See systemd/ for a timer that regenerates the map every 10 minutes. If you want history/diffing, snapshot each topo.json into SQLite and diff runs.

Security

Your generated topology is a map of your network. Keep it out of git. .gitignore already excludes config.yaml, out/, *.raw.json, and topo.json. Recommended: keep this repo private. If public, only ever commit the tooling and config.example.yaml (dummy values). One accidental git add -A of a build artifact leaks the whole layout.

Layout

collectors/   read-only source adapters (one file per source)
core/         schema · normalize · enrich · detect (gateway fingerprint) · oui.csv
renderers/    html/ (dashboard + topo_server.py) · card.py · network_cards.py
systemd/      units: topo-server (dashboard) · topo-agent · timer
tests/        fixtures + end-to-end pipeline test
scanners/make_network_topo.py   network topology orchestrator (collectors → topo.json)

# hardware topology + fleet dashboard (see HOWTO.md)
scanners/make_pc_topo.py      Windows hardware scan (PnP/CIM)
scanners/make_linux_topo.py   Linux hardware scan (sysfs/proc/USB/thermal)
core/local_telemetry.py       shared live CPU/net/disk/temp sampler
agent/topo_agent.py        push topology + telemetry to the server
install.sh · uninstall.sh  set up / remove the dashboard as a Linux service
agent/report.sh · agent/report.ps1   run the agent (self-updating)
Dockerfile · docker-compose.yml · templates/topographer.xml
                         run the dashboard as a container (incl. Unraid CA)
bootstrap.sh             agent one-liner install (Linux/Unraid): systemd / go-script /
                         TOPO_ONCE snapshot — adapts to the host, git-free
bootstrap.ps1            agent one-liner install (Windows): scheduled task, zip-fetch

Tests

python tests/test_pipeline.py      # no live network; uses fixtures

Every check CI runs is listed in CONTRIBUTING.md — all offline, seconds to run.

License

MIT © 2026 FugginOld. Covers everything in this repository, including the Unraid Community Applications template in templates/.

apps.marketingCta.appInstallTitle

apps.marketingCta.appInstallDescription

apps.installHelp.stepOpen apps.installHelp.stepSearchApp apps.installHelp.stepReview apps.installHelp.stepInstall

apps.detail.sections.requirements

Host networking is strongly recommended — the ping/arp/nmap collectors need to see the real LAN, and agent pushes keep their true source IP.

apps.detail.sections.categories

apps.detail.sections.related

apps.detail.sections.details

apps.detail.details.repository
ghcr.io/fugginold/topographer:latest
apps.detail.details.lastUpdated2026-08-10
apps.detail.details.firstSeen2026-08-07

apps.detail.sections.runtime

apps.detail.details.webui
http://[IP]:8770/
apps.detail.details.network
host
apps.detail.details.shell
bash
apps.detail.details.privileged
false

apps.detail.sections.configuration

DataPathrw

Saved topologies, widget instances and the service-icon cache.

apps.detail.config.target
/app/out
apps.detail.config.default
/mnt/user/appdata/topographer
apps.detail.config.value
/mnt/user/appdata/topographer
WebUI PortPorttcp

Dashboard + agent ingest API. Host networking ignores this — change the container's --port instead.

apps.detail.config.target
8770
apps.detail.config.default
8770
apps.detail.config.value
8770
config.yamlPathro

Optional. Path to a config.yaml FILE (not a folder) enabling the network scan, UniFi/OPNsense collectors, Glances and remote SSH scan. See config.example.yaml. Leave empty if unused.

apps.detail.config.target
/app/config.yaml
SSH keysPathro

Optional. A folder holding an SSH key that can reach your Linux hosts — enables the agentless remote scan. Leave empty if unused.

apps.detail.config.target
/root/.ssh
TOPO_TOKENVariable

Optional shared secret. When set, reporting agents must send it to /api/ingest.