Docs & Code Guide

Embed a diagram in a Grafana dashboard: the text panel, the sanitizer, and the wallboard

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

During an incident, the dashboard is where people already are, and the question they are asking is usually structural: what sits upstream of the service that is red. A Grafana text panel can answer it, because it renders markdown and a markdown image is fetched straight from its address with no proxy in between. The iframe route is a different story and needs an administrator, which is worth knowing before you plan around it.

6 min readFor SRE and platform teams whose incident view is a Grafana dashboard

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

155/20003 credits left
Try:

No account needed · Editable canvas, not a picture

The text panel in markdown mode is the whole feature

Add a visualization, choose Text, set the mode to Markdown, and put an image line in the body. Grafana renders it and the browser fetches the address directly. There is no image proxy and no server-side caching layer of its own, so freshness is decided entirely by the origin cache headers and the browser.

The embed endpoint sends Cache-Control max-age=300 with a long stale-while-revalidate, and an ETag derived from the canvas state. On a wallboard that reloads periodically, that means an edited diagram appears within about five minutes, and readers never sit in front of a cold render while a browser generates one.

Size the panel to the render rather than the other way round. A 1600 by 1000 image in a panel four grid units tall is unreadable; give the diagram a full row, or use the width and height parameters to request a shape that matches the panel.

![Production topology](https://datadef.io/api/embed/my-platform-a1b2c3d4?width=2000&height=900&scale=2)

[Open the interactive view](https://datadef.io/embed/my-platform-a1b2c3d4)

Iframes need an administrator, and a decision

HTML mode in the text panel is sanitized, and iframes are removed. The documented way to change that is disable_sanitize_html under the [panels] section of grafana.ini, or GF_PANELS_DISABLE_SANITIZE_HTML=true in the environment, and it relaxes protection for every text panel in the instance rather than only yours. Anyone who can edit a dashboard can then put arbitrary HTML in front of everyone who opens it.

Managed Grafana offerings frequently do not expose that setting at all, which ends the conversation quickly. Where an interactive panel really matters, a dedicated iframe panel plugin is the narrower option, since it accepts a URL without disabling sanitizing across the instance.

Nothing on the Datadef side blocks framing: the embed page is served with frame-ancestors permitting any parent. The blocker here is a Grafana policy decision, so make the image route your default and treat the frame as an upgrade someone has to approve.

Dashboard variables in the image address

Text panels interpolate dashboard variables, which turns one panel into an environment-aware one. Define a variable for the environment with the diagram slugs as values, and put it in the URL. Switching the dashboard from staging to production switches the topology picture with everything else.

The same trick works per region or per tenant. One dashboard definition, several diagrams, no copies of the panel to keep in step.

<!-- $diagram is a dashboard variable: prod-a1b2c3d4, staging-e5f6g7h8 -->
![Topology](https://datadef.io/api/embed/$diagram?width=2000&height=900)

What belongs on an incident wallboard

The diagram next to the alerts should be the same one the runbook uses. Two different pictures of the same system, one on the dashboard and one in the runbook, is how a 3am responder ends up debugging the documentation instead of the outage.

Keep it to what a responder needs to decide where to look: services, the datastores each one owns, the queues, and the external dependencies. Detail that helps during design review is noise during an incident. The related discipline is covered in keep runbooks in sync with infrastructure and stale runbooks and incident risk.

Anyone with the link can view it

The embed address resolves only while the project is shared publicly, and a public dashboard or a shared snapshot carrying that address exposes the diagram to whoever opens it. Draw the topology without internal hostnames, account ids or credentials. See sharing documentation.

Keeping the topology honest

A dashboard diagram that lags reality is worse than no diagram, because it gets trusted under pressure. Connect the repository read-only from GitHub, GitLab or Azure DevOps and let the daily sync regenerate the picture from the source, including Terraform repositories, where each .tf file is parsed and modules are drawn as zones without init, state or cloud credentials.

How much gets drawn is decided by rule rather than by the model, which is the part that makes a panel readable at 3am. The first version of the Terraform pipeline drew all 62 visible resources of a 123-resource repository and produced something correct, complete and unreadable: a phone book in a column. The rule now is a target of forty drawn nodes for the canvas and at most eight per module zone, raised to sixteen when one module is more than half the repository and squeezing it into eight would hide the subject itself. Repeated minor resources of one type roll into a single node with its count, and whatever still overflows becomes one supporting-resources node. A catalog-shaped repository with nineteen independent stacks gets a wider budget instead, five nodes per stack up to seventy-two, because nineteen three-node architectures read as a grid of zones and would be gutted by forcing them into forty.

For teams running agents, the MCP server exposes repo_status and repo_refresh, so refreshing the diagram after an infrastructure change is one call inside the session that made the change. See repo to diagram and agents.

FAQ

How do I show an architecture diagram in Grafana?

Add a Text panel, set the mode to Markdown, and include an image line pointing at a URL that renders the diagram. Grafana renders the markdown and the browser fetches the image directly, so the panel shows whatever that address returns at load time.

Why is my iframe blank in a Grafana text panel?

Text panel HTML is sanitized and iframes are stripped. Enabling disable_sanitize_html in the panels section of the configuration, or the matching environment variable, allows them instance-wide, which many managed Grafana offerings do not permit. A dedicated iframe panel plugin is the narrower alternative.

How quickly does the panel pick up a changed diagram?

It depends on the origin cache headers, since Grafana does not proxy the image. An endpoint serving max-age of 300 seconds means an edit appears within roughly five minutes on a dashboard that reloads, with no dashboard change required. A long stale-while-revalidate window on top of that means no viewer sits in front of a cold render while a new one is being produced.

Can one panel show a different diagram per environment?

Yes. Text panels interpolate dashboard variables, so a variable holding the diagram identifier can be used inside the image address. Switching the dashboard environment switches the diagram with it, from a single panel definition. The same trick works per region or per tenant, and it leaves one panel to maintain rather than several copies that have to be edited together.

Do dashboard viewers need an account with the diagram tool?

No. A publicly shared diagram serves an image URL that any browser can load, so it renders for every dashboard viewer including read-only ones. The same public sharing means anyone with the address can view the diagram, so keep sensitive detail out of it.