Skip to content

Repository files navigation

TraceAnywhere

A self-hosted, Docker-native network diagnostic tool for continuous ICMP traceroute with real-time visualization. Think PingPlotter Pro, but open-source and designed to run on any server you control.

TraceAnywhere answers the question: "Where between point A and point B is the network broken or degraded?"

It runs persistent traceroutes from the host where it's deployed, storing results in a local database and streaming them to a web UI with per-hop latency charts, jitter bands, and packet loss indicators. Leave it running for hours or days to catch intermittent routing issues that one-off diagnostic tools miss.

Why This Exists

Commercial tools like PingPlotter Pro work well from a desktop, but they can't run unattended on a headless server in a data center. Standard CLI tools (mtr, traceroute) give you a snapshot but no history. TraceAnywhere fills the gap: deploy it anywhere Docker runs, point a browser at it, and get persistent, visual traceroute data from the server's perspective.

Built by Volantic Systems as part of ongoing network infrastructure work managing multi-site server deployments across data centers in the US and Europe.

Features

  • Continuous traceroute via mtr with configurable probe intervals (1-300 seconds)
  • Real-time web UI with WebSocket streaming, no polling
  • Per-hop timeline charts with green probe dots, red dashed average line, and jitter range band (min/max fill)
  • Summary bar chart showing average latency across all hops at a glance
  • Sparkline trend lines in the hop table for quick visual triage
  • Multiple concurrent traces in browser tabs, each with independent state
  • Trace history auto-saved to the database with resolved IP addresses
  • JSON export of full trace data for offline analysis or sharing
  • Single container deployment with Docker Compose
  • Non-root execution inside the container; CAP_NET_RAW scoped to the mtr-packet binary via setcap

Quick Start

git clone https://github.com/VolanticSystems/trace-anywhere.git
cd trace-anywhere
docker compose up -d

Open http://localhost:7890 in a browser. Enter a hostname or IP and click Trace.

Requirements

  • Docker and Docker Compose
  • The host must be able to send ICMP packets (most servers can; some cloud VPCs restrict this)

Architecture

Browser (SPA)
    |
    |  REST API + WebSocket
    v
FastAPI (Python 3.12)
    |
    |-- ProbeManager --> mtr-tiny (ICMP probes, CAP_NET_RAW)
    |-- SQLite (WAL mode, file-based migrations)
    |-- Static file server (serves the frontend)

Backend: FastAPI with async SQLite (aiosqlite). The ProbeEngine interface uses dependency injection so the mtr integration can be swapped for a fake engine in tests.

Frontend: Vanilla JavaScript SPA with Chart.js for visualization. No build step, no framework, no node_modules.

Probe engine: Wraps mtr --report --report-wide --report-cycles 1 --no-dns and parses the text report output. The mtr-tiny package in Debian/Ubuntu produces text reports (not JSON), so the parser uses regex extraction rather than JSON parsing.

Database: SQLite with WAL journaling for concurrent read/write. Schema managed via numbered SQL migration files (backend/migrations/). Tables: trace, trace_result, hop_result, saved_target, schema_version.

Configuration

The default configuration works out of the box. The app listens on port 7890 inside and outside the container.

# docker-compose.yml
services:
  traceanywhere:
    build: .
    ports:
      - "7890:7890"    # Change the left side to use a different host port
    cap_add:
      - NET_RAW         # Required for ICMP probes
    volumes:
      - trace-data:/app/data   # Persists SQLite database across restarts
    restart: unless-stopped

API

All endpoints return JSON. Errors use a consistent {error, message, category} format.

Method Endpoint Description
GET /health Health check (mtr available, DB writable)
POST /api/traces Start a new trace
GET /api/traces List all traces
GET /api/traces/{id} Get trace details
PATCH /api/traces/{id} Pause, resume, or stop a trace
DELETE /api/traces/{id} Delete a trace and its results
GET /api/traces/{id}/results Get probe results (supports time range + limit)
GET /api/traces/{id}/export Export full trace data as JSON
GET /api/targets List saved target history
DELETE /api/targets/{id} Delete a saved target
DELETE /api/targets Clear all target history
WS /ws/traces/{id} Real-time probe result stream

Project Structure

trace-anywhere/
  backend/
    app/
      main.py          # FastAPI app, routes, WebSocket handler
      database.py       # SQLite implementation, migrations
      manager.py        # ProbeManager, probe loop orchestration
      probe.py          # ProbeEngine ABC, MtrProbeEngine, FakeProbeEngine
      models.py         # Pydantic models (Trace, HopResult, etc.)
      validation.py     # Target input validation
    migrations/         # Numbered SQL schema files
    requirements.txt
  frontend/
    static/
      index.html        # Single-page application
      css/style.css     # Dark theme UI
      js/app.js         # Client-side logic, Chart.js integration
  Dockerfile
  docker-compose.yml
  SPEC.md              # Full project specification
  DEFERRED.md          # Future improvements (not needed yet, not forgotten)

Design Decisions

Why mtr instead of raw ICMP? mtr handles the probe/response cycle, TTL incrementing, and loss calculation reliably. Reimplementing that in Python would be fragile and add no value.

Why SQLite? A single-file database that needs zero administration is the right choice for a tool that ships as one Docker container. WAL mode gives adequate concurrent performance for this workload.

Why vanilla JS? The frontend is a single page with a hop table and two charts. React/Vue would add a build step, 200KB of framework, and no meaningful capability. Chart.js is the only dependency.

Why non-root with setcap? ICMP requires CAP_NET_RAW. Rather than running the entire container as root, the capability is granted only to the mtr-packet binary. The Python process runs as an unprivileged user.

Roadmap

See DEFERRED.md for planned improvements, organized by phase:

  • Phase 2: Environment variable configuration, data retention policies, WebSocket reconnection, accessibility
  • Phase 3: Target allowlists, rate limiting, Prometheus metrics, ASN/GeoIP enrichment
  • Phase 4: CI/CD pipeline, API versioning, WCAG 2.1 AA compliance, keyboard shortcuts

License

MIT

About

Self-hosted continuous traceroute with a real-time web UI. Docker-native, per-hop latency and loss history from any server you control.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages