Skip to content

Repository files navigation

rackattack

An open-source, API-first source-of-truth for datacenter physical infrastructure — with an agent-driven interface.

CI Go 1.25 License: MIT Docs

Model the messy reality of a datacenter — devices, cabling, power, cooling, and spatial relationships across racks, rows, floors, and sites — in a strongly-consistent store, and serve it over a high-throughput gRPC API in Go. On top of that same core, a secondary MCP adapter lets anyone point their agent at it and ask questions like "what goes dark if feed B-3 trips?" and get back structured data plus a rendered diagram.

The full stack ships today: gRPC + REST + GraphQL + MCP over one Go core, OIDC/JWT auth, a read-through cache, a CHANGEFEED audit log, Prometheus/OTel observability, and container + Kubernetes manifests. Clone it, point it at your own infrastructure, and deploy it yourself — it runs locally in one command and scales out from there.


Quick start

Needs Go 1.25, Docker, just, and Graphviz (brew install graphviz — the blast-radius renderer shells out to dot).

git clone https://github.com/lex00/rackattack.git
cd rackattack
just example       # build a fresh sample datacenter, open the guided-tour gallery

just example starts CockroachDB, generates a deterministic sample fleet, runs the guided tour (all six screens, every diagram hoverable/clickable), opens example-out/index.html, then tears the database back down — the gallery is a self-contained artifact that survives. It also prints example prompts you can ask an agent over MCP. To stand up a long-running instance against your own data, rackattack serve (see Deploying below). Full walkthrough — including the MCP and live-API paths — is in the docs site quick start.


Why this shape

The conventional DCIM stack (NetBox/Nautobot) is a Django web app: a data model plus a dense HTML frontend. rackattack keeps the hard part — an expressive, queryable infra model behind a fast Go API — and rethinks the frontend:

  1. API-first, in Go. A gRPC service is the primary contract: typed, high-throughput, with complex filtering, aggregation, and bulk operations. This is the backbone and meets the role's core ask directly. (REST falls out for free via grpc-gateway when wanted.)
  2. An agent as the human interface. Layered on top of the same service core, an MCP adapter exposes the model to any LLM agent. Operators talk to infra conversationally; the agent composes API calls and reads back prose + diagrams. This is the differentiated layer — built last, over a contract that's already proven.
  3. Graphviz as the render engine. Infra is a graph. Queries render to DOT → SVG/PNG: rack elevations, cable paths, power dependency trees, thermal/blast-radius maps.

Single Go core, two transports (gRPC primary, MCP secondary), one render engine.


Prior art & where rackattack fits

The DCIM market splits cleanly, and the split leaves a hole exactly where an AI cloud operates.

Tool Type Strong at API-first / automation Built for
NetBox / Nautobot OSS (Python/Django) source of truth, cabling, IPAM ● (REST/GraphQL, Jobs) network automation teams
Sunbird dcTrack Commercial power and cooling, capacity ◐ (GUI-first, 3–6 mo rollout) enterprise / colo / hyperscale
Nlyte / Schneider EcoStruxure Commercial monitoring, analytics, BMS enterprise facilities ops
Device42 Commercial discovery + CMDB ITAM / ITSM orgs
Hyperview Commercial (cloud) fast rollout, monitoring mid-market
openDCIM / RackTables OSS basic asset + space small shops

Two camps, and neither fits a hyperscaler:

  • Commercial DCIM (Sunbird, Nlyte, Schneider) has rich power/cooling, but is GUI-first, slow to deploy, and not automation-native.
  • OSS source-of-truth (NetBox, Nautobot) is API-first and automatable, but Python/Django, network-centric, and not built for hyperscale performance.

Nobody combines an API-first source of truth + high-throughput Go + agent/MCP-native access + real power and thermal modeling. That gap is why hyperscalers (Google, Meta, AWS, and others) build this in-house: no off-the-shelf tool meets their scale, automation, and API demands at once.

rackattack is an open-source take on that in-house tool, for everyone who isn't a hyperscaler — homelabs, colo tenants, research clusters, edge fleets, and small clouds: the NetBox data-model idea, rebuilt as a fast Go/CockroachDB service, with the power-and-cooling realism of a Sunbird, driven by an API (and an agent) instead of a web GUI. Clone it, point it at your own infrastructure, and deploy it yourself.

Who it's for, precisely: a single organization running its own fleet — one site or a handful — whose job is to communicate physical risk. Multi-tenancy and a geographic map layer are deliberate non-goals for now; the floor plan, however, is spatially representative — racks and rows carry stored positions and facing, so it reads as a walk-up map, not just a heat diagram. The persona and these scope boundaries are written up in docs/personas-and-scope.md.


Architecture

   non-agent callers                 any LLM agent (Claude, etc.)
        │  gRPC (primary)                  │  MCP (secondary, built last)
        ▼                                  ▼
   ┌──────────────────────────────────────────────────┐
   │  rackattack  (Go service)                         │
   │                                                   │
   │  gRPC API  ──┐                                     │
   │  MCP tools ──┴──▶  service core                    │  one core,
   │                    - validation                    │  two transports
   │                    - complex filtering             │
   │                    - aggregation, bulk ops         │
   │                  graph + render  (recursive →      │
   │                  Graphviz layout → custom SVG)     │
   │                  data access   (pgx)               │
   └───────────────────────────┬───────────────────────┘
                               ▼
                       CockroachDB
   site → floor → row → rack → device
   cable    (graph edges, port ↔ port)
   power    (feed → PDU → outlet → port chain)
   cooling  (CRAC/CRAH → room/row → rack thermal budget)

Why CockroachDB (not Postgres)

This is the system of record for physical reality across hundreds of sites:

  • Strong consistency, serializable. You cannot have split-brain about what's cabled to what or which feed powers which rack. Stale read-replica reads would be correctness bugs for an authoritative infra graph.
  • Geo-distributed, survives region/AZ loss. The tooling must stay up across the same sites it models.
  • Horizontal scale without manual sharding as the fleet grows.
  • Postgres wire-compatiblepgx, recursive CTEs, standard SQL all work, so no downside vs. Postgres.

For a single-node evaluation this is just "Postgres that scales out later"; the consistency and survivability properties start to matter once you run more than one node across more than one failure domain.


The data model

A typed infra graph. Core entities and the edges between them:

  • Spatial hierarchy: site → floor → row → rack → rack_unit → device.
  • Devices: servers, switches, patch panels, PDUs — with ports.
  • Cabling: cable rows are edges connecting two device ports (with type, length, medium). Patch panels make paths multi-hop.
  • Power: feed → PDU → outlet → device power port — a dependency chain, plus redundancy (A/B feeds) so blast-radius respects failover.
  • Cooling / thermal (modeled for real): each device has a heat output (derived from power draw); each rack has a thermal budget; rows/rooms have CRAC/CRAH cooling capacity. This lets us compute thermal headroom and find hotspots, not just stub the concept.
  • Optical transceivers: the pluggable optic in a port is a first-class entity (form factor, speed, vendor, wavelength) — one per port — so cabling and fabric reason about the optic, not just the cable medium.

A Graphviz ER diagram of the schema (and the rest of the architecture) lives in the docs site — authored as .dot and compiled to SVG at build time, the same diagram engine the product uses for its renders. The bigger story is how queries are rendered — see Visualization.


Centerpiece capabilities (all of them)

Three recursive/aggregate workloads, each returning structured data and a Graphviz diagram:

  1. Cable-path trace. Follow a logical link end-to-end across physical hops (device port → patch panel → … → device port). Recursive CTE.
  2. Power-dependency rollup / blast radius. Walk feed → PDU → outlet → port to answer "if feed B-3 trips, which racks/devices lose power (respecting A/B redundancy)?" — and the inverse, "what does this device depend on?" Recursive CTE.
  3. Thermal headroom / hotspots. Roll device heat output up to rack and row, compare against cooling capacity, surface racks over budget.

Visualization — the differentiator

The visualization layer is where rackattack beats the field. Not by being a prettier dashboard — by being a different kind of thing.

Thesis: no GUI, answer-shaped artifacts

Update (June 2026): this stance was reversed — a web UI is being added. Live exploration (selectors: pick any feed/rack/floor and re-render) is something a class of users expects, and answer-shaped artifacts plus an agent don't fully cover it. The UI is served by the service itself (serve/ui, Go-rendered + HTMX) so the same surface runs local and cloud. The artifact model below still holds — generated visualizations remain the output and the export/alert format; the UI adds a live way to drive them. Rationale: docs/snapshots-and-history.md → "Resolution".

A GUI is a persistent app you navigate — a thing to build, maintain, and learn. That's the weak part, and we cut it. A visualization is just an artifact the service renders on demand and hands back.

So the model is: the agent is the input, a generated artifact is the output. You ask a question in plain language; rackattack renders exactly the picture that answers it and returns it.

  • A commercial DCIM GUI shows you a floor plan; you hunt for what you need.
  • rackattack generates the diagram for your question — blast radius with only the affected racks lit red, survivors green, everything else dimmed.

The diagram is an answer, not a map. A static-GUI competitor can't do this without infinite pre-built views; rackattack gets infinite bespoke views for free, because the agent composes the query and the renderer paints the result.

Rendering architecture: Graphviz as a layout brain, custom SVG as the painter

Graphviz has two parts people conflate: a world-class layout engine (where do N nodes and their edges go without overlapping) and a dated renderer. We keep the first and throw away the second.

  relationship graphs            geometric grids
  (cable path, power tree,       (rack elevation,
   network fabric)                floor heatmap)
        │                              │
        ▼                              ▼
   Graphviz layout              deterministic geometry
   (dot -Tjson → coords)        (compute x/y — it's a grid)
        │                              │
        └──────────────┬───────────────┘
                       ▼
        ONE Go SVG painter + design system
        (palette · typography · heat gradients · device
         icons · semantic highlight: dead=red, survives=green)
                       ▼
            SVG  (+ PNG fallback, + interactive HTML)
  • Relationship visuals — Graphviz solves layout via dot -Tjson (node positions + edge splines); our Go code paints beautiful, branded SVG from those coordinates. Auto-layout and full aesthetic control.
  • Geometric visuals — layout is just a grid; we compute it directly. Graphviz never touches these.
  • Both feed one shared design system, so everything looks like one product.

Delivery: interactivity without a GUI

  1. SVG (primary) — vector-crisp, tiny, renders inline in agent chat UIs and any browser. The everyday output.
  2. PNG (fallback) — for surfaces that need raster.
  3. Self-contained interactive HTML (wow tier) — one generated .html with the SVG embedded plus minimal vanilla JS for hover / zoom / pan / click-to-drill. A generated artifact, not a maintained app — no server, no build. The agent hands you blast-radius.html and you explore it.

Signature visuals

Power blast-radius render

Hero mockup (hand-painted SVG) of the target render quality: Feed B-3 trips, dead racks go red, A/B-redundant racks stay green with a live feed, the rest dims. In the product this layout comes from Graphviz and is painted by the Go SVG renderer.

  • Blast-radius map(hero) — Graphviz-laid topology, custom-painted: the failed feed highlighted, dead racks red, redundant survivors green, the rest dimmed. (Stretch: animate the cascade.)
  • Cable-path ribbon — elegant left-to-right flow, device cards with port pins, the traced path glowing.
  • Isometric rack elevation — 2.5D racks (isometric = a 2D affine transform, no WebGL), devices as labeled slabs colored by heat or power draw.
  • Floor heatmap — top-down, racks as cells colored by thermal headroom, hotspots glowing. Pure geometric SVG.

Screen gallery

Five signature screens have approved hand-painted mockups, each with base · hover · select frames (hover and select are states of one interactive HTML artifact, not separate renders — the tool call and params behind each are in TOOLS.md). A sixth screen — the floor plan overview — is rendered live in the guided-tour gallery (it opens the gallery) and over the FloorPlan RPC / floor_plan MCP tool; it has no hand-painted mockup, so it isn't listed below.

Power blast radius ⭐ — "what goes dark if feed B-3 trips?" blast radius base · hover · select

Cable path"trace the cable path from tor-12a et-0/0/3" cable path base · hover · select

Rack elevation (isometric) — "show R07 by power draw" rack elevation base · hover · select

Floor heatmap"which racks on floor 1 are running hot?" floor heatmap base · hover · select

Network fabric"where's the congestion in pod A's fabric?" network fabric base · hover · select


Fleet generator & guided tour

Bringing your own data is the point — but an empty source-of-truth is hard to evaluate, so rackattack ships a generator and a guided tour. More than a seeder: a scale knob produces a synthetic datacenter, then it mines its own interesting scenarios, writes the prompts, runs them, and emits the diagrams — so any size of fleet produces its own narrated walkthrough. Use it to explore the model and renders against realistic sample data before wiring in your real inventory.

1. Generate a fleet (tunable, deterministic).

  • Scales from one rack → row → site → multi-site (--sites 8 --racks-per-row 20 --oversub 3:1 --redundancy ab --seed 42).
  • Plausible topology: leaf-spine switching, structured cabling through patch panels, A/B power, realistic device mixes and power/heat profiles.
  • Deterministic from --seed — runs reproduce exactly (benchmarks, tests, and the example preset that reproduces the walkthrough all depend on this).
  • Plants guaranteed-interesting scenarios: a single-point-of-failure feed, an over-budget thermal hotspot, a congested fabric uplink.

2. Take the guided tour (mine → prompt → run → render).

  • Mine the interesting subjects — biggest-blast-radius feed, hottest rack, longest cable path, most-congested link.
  • Prompt: template natural-language questions around them (optionally LLM-phrased for variety).
  • Run: map each prompt to its tool call (TOOLS.md) and execute.
  • Render: emit the diagrams into a narrated gallery — at the example preset this reproduces NARRATIVE.md exactly.

In production the prompt→tool mapping is your own LLM agent over MCP; the tour driver is a scripted stand-in that exercises the pipeline without a live agent.

Used three ways: seed an instance with sample data, generate self-narrated galleries at any scale, and feed load/perf benchmarks on the hot queries.


API surface

Primary — gRPC (the product contract) — 24 RPCs in four groups:

Group RPCs
Queries & screens PowerBlastRadius, TraceCablePath, GetRack, ThermalHeadroom, FabricTopology, FloorPlan, SearchDevices (paginated/filtered + counts), GetDevice, GetPort, Render
Mutations Upsert/Delete × Device / Rack / Crac
Bulk mutations BulkUpsert/BulkDelete × Devices / Racks / Cracs (per-item results)
Edge mutations Upsert/Delete × Cable / FabricLink (keyed by endpoints)

Each screen-generating RPC returns both structured data and a RenderResult. The full table — request/reply shapes and the GraphQL/MCP equivalents — is on the docs site API page.

REST is available essentially for free via grpc-gateway over the same proto, and a GraphQL endpoint (gqlgen, schema-first) serves the screens, the paginated/filtered device search, and the upsert/delete + bulk mutations — all three HTTP transports resolve through the one service core (serve mounts /graphql, /graphql/playground, and the REST gateway on the same port).

Secondary — MCP (built last): a thin adapter mapping the same service core to agent tools, so any LLM can drive the model conversationally. Not required for the gRPC story to stand on its own.

Authentication & authorization

Signed OIDC/JWT bearer tokens are validated at every transport edge — a gRPC unary interceptor plus an HTTP middleware that covers both REST and GraphQL — and the resulting principal flows into a shared Authorizer that gates the surface: reads are open to any authenticated principal, while mutations and bulk operations require a writer/admin role. (Because REST and GraphQL call the service in-process, authorization lives in the wrapper they all share, not only in the gRPC chain.)

Config is environment-driven:

Env Meaning Default
AUTH_ENABLED turn auth on; off = dev bypass (full surface open, no token) false
AUTH_JWKS_URL OIDC JWKS endpoint for RS/ES tokens
AUTH_HS256_SECRET configured symmetric key (use instead of JWKS)
AUTH_ISSUER / AUTH_AUDIENCE checked against the token's iss / aud when set
AUTH_ROLES_CLAIM claim holding roles; dotted for nested (e.g. realm_access.roles) roles
AUTH_WRITER_ROLES roles permitted to mutate writer,admin

Dev-mode bypass: with AUTH_ENABLED unset (the default), the edges inject a dev principal carrying the writer role and the whole surface stays open — no identity provider required, so you can evaluate locally in one command. Set AUTH_ENABLED=true with a key source before exposing rackattack to anything you don't fully trust.


What's built

Everything below is implemented and tested — not a roadmap.

Area What's there
Data model CockroachDB schema as a typed infra graph: spatial hierarchy, cabling edges, power chains with A/B redundancy, cooling/thermal, first-class optical transceivers
Query workloads PowerBlastRadius, TraceCablePath, ThermalHeadroom (recursive/aggregate CTEs), FabricTopology, FloorPlan, SearchDevices (paginated/filtered + counts)
APIs gRPC (primary) · REST via grpc-gateway · GraphQL via gqlgen · MCP adapter — all over one service core
Mutations Upsert/Delete for core + edge entities, BulkUpsert/BulkDelete with per-item results
Rendering Custom Go SVG painter over Graphviz layout; SVG · PNG · self-contained interactive HTML; matches the approved mockups
Security OIDC/JWT bearer validation + role-based authz across gRPC/REST/GraphQL
Caching Read-through cache (in-process LRU or Redis) with write invalidation
Audit / CDC CockroachDB CHANGEFEED → audit log + webhook sink + change-history endpoint
Ops Dockerfile, k8s manifests, CI, Prometheus metrics + alerts + Grafana dashboard, OpenTelemetry traces
Scale Deterministic generator to millions of rows; benchmarked hot queries; concurrent load harness

Deploying

rackattack is a single Go binary plus a CockroachDB. The fastest path:

docker compose up -d --wait               # local single-node CockroachDB
rackattack serve --seed-example           # auto-migrate, seed sample data, serve

serve mounts gRPC, the REST gateway, GraphQL (/graphql, /graphql/playground), and (separately) the MCP adapter. Configuration is environment-driven (DATABASE_URL, the AUTH_* keys above, cache and telemetry settings).

For a real deployment, deploy/ offers three paths — pick by need (full chooser in deploy/README.md):

  • Evaluation (deploy/k8s/base, k3d) — throwaway, insecure, fastest to look at.
  • Minimal · single-host (deploy/compose) — the cheapest real deploy: the whole stack on one box, secure small-prod (auth on, verify-full DB, edge TLS, a tested backup/restore), no Kubernetes. Guide: docs/minimal-deployment.md.
  • Single-region production (deploy/k8s/production) — HA, survives a node/AZ loss. Guide: docs/production-deployment.md.

Then:

  • Harden it — auth (AUTH_ENABLED=true + a JWKS or HS256 key), CockroachDB secure (certs), TLS at the edge. The bare docker compose up defaults above are tuned for one-command local evaluation, not for exposure.
  • Observe it — Prometheus metrics + example alerts and a Grafana dashboard are in deploy/; OpenTelemetry traces span RPC → query → render.

Full instructions are on the docs site.


Contributing

Issues and pull requests are welcome — bug reports, new device/topology models, renderer improvements, and deployment recipes especially. The codebase is laid out as cmd/rackattack + internal/{schema,gen,query,render,server} and friends; just build / just test (the latter expects a local CockroachDB via just up). See the contributing guide.

In one line: a Go gRPC/REST/GraphQL service on CockroachDB that models datacenter physical infrastructure — cabling, power, and cooling — as a graph, renders answers as diagrams, and lets an agent drive the whole thing over MCP.

About

Agent-driven datacenter infrastructure source-of-truth (DCIM): gRPC-first Go service on CockroachDB with generated SVG visualizations

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages