Why a Grafana reverse proxy setup needs root_url right from the start
A reverse proxy setup places NGINX, Apache, HAProxy or Traefik in front of Grafana so that users reach one company domain over HTTPS, while the Grafana process listens on a private address inside your network. You need one when Grafana is published to staff or customers on a shared hostname, when TLS certificates must be managed centrally, when access is restricted by network zone, or when Grafana is served from a sub path alongside other internal tools. The proxy itself is only half of the design. Grafana has to know the address that users actually type, because it builds links, redirects and OAuth callbacks from that address. The setting that carries this knowledge is root_url in the [server] section of grafana.ini, and it must match the public scheme, host, port and any sub path exactly.
The three pieces depend on each other. The proxy receives the request on the public domain and forwards it to Grafana, usually on a local port. Grafana then uses root_url to generate every absolute URL it returns, including dashboard share links, alert notification links and the callback address sent to your identity provider. If root_url still points at localhost:3000 or an old hostname, the proxy can serve pages correctly while login loops, redirects go to the wrong host or OAuth returns an error about a mismatched redirect URI. The open-source edition exposes no administrative screen or separate option for these values, so grafana.ini, or the matching GF_SERVER_ROOT_URL environment variable, is the only place to set them. Confirm the exact keys for your installed version in the Grafana installation documentation before you change anything in production.
Decide the public URL, the sub path policy and the TLS termination point before you write the proxy configuration, and record them with the identity provider's redirect URI. Changing the domain later means updating root_url, the proxy, certificates and every registered OAuth application together. As an illustrative check, open an alert link or share link from a browser that is not on the Grafana host and confirm it uses the public hostname. Each proxy option in the rest of this topic depends on these values being right from the first deployment.
Which proxy fits which team: NGINX, Apache, HAProxy or Traefik
This table compares the four proxies on the factors that shape a Grafana deployment: VM or Kubernetes hosting, sub path needs, WebSocket handling for Grafana Live and configuration effort. Use it to shortlist one option, then confirm the items marked for checking against your own environment and existing skills.
| Factor | Traefik | NGINX, Apache and HAProxy |
|---|---|---|
| Fit for a VM-based Grafana | Runs as a single Go binary with file configuration, so it can sit in front of a VM without an orchestrator. | Mature choices for VM hosts. Confirm which one your operations team already patches, monitors and supports. |
| Fit for a Kubernetes cluster | Reads routes automatically from Kubernetes Ingress, Gateway API and CRDs, so Grafana routes follow the Service objects. | Usually run as an ingress controller or external proxy. Confirm the controller, annotations and support model your cluster uses. |
| Sub path requirement | Path-based routing and prefix handling are configured per router. Test the sub path against your Grafana root_url before rollout. | Path rewriting and proxy_pass style rules are well documented. Confirm the exact rules your Grafana version needs in a test environment. |
| WebSocket support for Grafana Live | WebSocket is listed among its supported features. Verify the upgrade path end to end, since Grafana Live has limitations in HA. | All three can proxy WebSocket connections with upgrade headers. Confirm the header settings and timeouts in your own build. |
| TLS and certificates | Let's Encrypt certificates are built in, including wildcards, which suits many domains under one zone. | Certificates are handled through your chosen tooling or a separate ACME client. Confirm how renewal is automated. |
| Licensing | MIT licensed, so the proxy itself carries no commercial license fee. Commercial support is sold separately by Traefik.io. | Confirm the license and support terms for the version and distribution you plan to run. |
| Configuration effort | Low for dynamic environments because routes are generated from labels or resources. Adds effort if you need hand-written rules outside the orchestrator. | Usually moderate, with explicit configuration files that a team must write, review and version. Effort depends on how many services sit behind the proxy. |
| Team skill to confirm | Teams already working with Docker, Kubernetes or Consul will recognize the label and resource model quickly. | Teams with long-running VM estates often already run NGINX, Apache or HAProxy. Reuse existing skills where possible. |
Domain root_url or a sub path: choosing the public address
Serving Grafana at the root of its own hostname, such as a dedicated monitoring name, is the simpler pattern. Grafana assumes it owns the whole host, so the proxy forwards every path to the same backend without rewriting. The public address is then the scheme and host users type into the browser, and it is the value the root_url setting in the [server] section should carry.
- Fewer rewrites: Assets, API calls and redirects all resolve from the root, so the proxy needs no path prefix handling.
- Clean certificate scope: A dedicated name maps to one certificate and one DNS record that can be managed separately from other applications.
- Simple cookie scope: Session cookies bind to one host, which is easier to reason about for security review.
- Single source of truth: The same host value appears in
root_url, the proxy's server name and the identity provider's redirect URI. - Clear ownership: Platform or monitoring teams can change the hostname without touching other sites.
Before you start, confirm the hostname, the DNS record and the certificate plan with the team that owns your DNS and certificate authority, because those choices determine every later URL.
Serving Grafana from a sub path such as /grafana is used when the organization wants monitoring under an existing portal or domain. The proxy strips or keeps the prefix, and Grafana must be told it is running under that path. This is controlled by the serve_from_sub_path setting together with a root_url that includes the path. If these two settings disagree with the proxy, pages load without styles or scripts, and redirects send users to the wrong location.
- Full public URL in root_url: The value includes the path, for example the host followed by
/grafana/, so generated links carry the prefix. - Matching prefix at the proxy: The proxy location for the prefix must forward to Grafana in the way the settings expect, with the trailing slash handled consistently.
- Asset paths follow the prefix: Static files, plugin assets and API calls are generated relative to the configured address, so a mismatch shows up as broken pages.
- Shared domain cookies: Other applications on the same host can interfere with session cookies, so review cookie paths and names during testing.
- Upgrade regression checks: Confirm sub path behavior after each Grafana upgrade, since path handling is tested only against the documented configuration.
Check the exact setting names and their current behavior in the Grafana configuration documentation for your release before you write the proxy rules.
Single sign-on flows send users to the identity provider and expect a redirect back to a fixed callback URL. Grafana builds that callback from its configured public address, so the address in root_url must match the redirect URI registered with the identity provider exactly. Scheme, host, port, path and trailing slash all count. A mismatch typically produces an error at the identity provider or a sign-in loop after the user returns to Grafana.
- Exact string match: Register the redirect URI as Grafana generates it for the chosen address, including the sub path if one is used.
- Scheme must be correct: A
root_urlthat sayshttpwhile users arrive overhttpscauses redirect errors and insecure callbacks. - Separate registrations per address: If you change the public address, add the new redirect URI before you remove the old one so users are not locked out during cutover.
- Multiple entry points: Internal and external addresses, or a test and production host, each need their own registration.
- Authentication settings: Review the OAuth settings for the identity provider with the same address in mind, and confirm the expected callback path for your provider in its own documentation.
Before go-live, sign in through each public address and confirm the identity provider accepts the callback without manual edits.
The choice between a dedicated hostname and a sub path is usually settled by ownership, certificates and the number of applications already on the domain. Making the decision in writing before the proxy build prevents a rework of certificates, redirect URIs and bookmarks later. The address also becomes part of user links, alert notifications and dashboard sharing, so changing it after rollout has visible effects.
- Ownership of the domain: Dedicated names suit teams that manage their own DNS and certificates, while sub paths suit portals owned by another team.
- Number of applications: Several tools behind one host make path routing attractive, but each additional path adds prefix handling to test.
- Link stability: Alert messages, shared dashboard links and bookmarks embed the public address, so decide early and document it.
- Certificate scope: Plan the certificate and renewal process for the chosen names, including any wildcard certificates your organization already uses.
- Environments: Separate names for test, staging and production keep redirect URIs and cookies from colliding.
Ask your platform and identity teams to confirm the final public address and the list of redirect URIs before writing any proxy configuration.
How to configure the proxy, root_url and TLS in order
This sequence moves Grafana from direct access to a single public HTTPS address behind your proxy, with correct redirects, live streaming and sign-in working end to end before users depend on it.
Choose the public domain and sub path
Decide the public hostname users will type, such as grafana.example.com, and whether Grafana will sit at the root of that host or under a sub path such as /grafana. Record both values before touching any file, because every later step depends on them. Your network or platform team owns the DNS record and the certificate request for that name. Check: the hostname resolves to the proxy's address from a client outside the cluster or server, and you have written down the exact scheme, host and path that users will see in the browser.
Set root_url and domain in grafana.ini
Set the public address in the [server] section of grafana.ini, using the
root_urlkey for the full public URL including scheme and any sub path, and thedomainkey for the host name. In containers or Kubernetes, the same keys can be supplied as GF_SERVER_ROOT_URL and GF_SERVER_DOMAIN environment overrides, which is usually easier to keep in version control. Restart Grafana so the values load. Check: open the Grafana log at startup and confirm it reports the expected root URL, and that the login page loads without redirecting to an internal address such as localhost or a pod name.Forward host and protocol headers at the proxy
Configure NGINX, Apache, HAProxy or Traefik to pass the original Host header and an X-Forwarded-Proto header carrying the scheme the browser used, and to forward the client address. Without these, Grafana builds links and redirects from the internal address it receives. In Traefik, these are normally set by default for routes you define, so confirm the behavior in your version. Check: send a request through the proxy to a diagnostic route or the login page and confirm the redirect Location headers point to the public hostname over https, not to an internal address.
Terminate TLS at the proxy
Install the certificate and private key on the proxy, and configure it to accept HTTPS from users and to serve the Grafana site over that connection. The connection between the proxy and Grafana can stay on a private network, but make the choice deliberately and document it. Set the cookie security settings in Grafana so session cookies are marked secure once users reach it over https, as the security hardening guidance describes. Check: from an outside client, the certificate chain validates for the public name, plain HTTP redirects to HTTPS, and the login cookie carries the Secure attribute.
Add WebSocket upgrade headers for Grafana Live
Grafana Live uses WebSocket connections for streaming updates to dashboards. Add the proxy settings that allow the Upgrade and Connection headers to pass through to Grafana, and set a read timeout long enough that idle streams are not dropped. In NGINX this means proxy_http_version 1.1 with the upgrade headers; in HAProxy, Traefik and Apache the equivalent needs to be confirmed against each product's WebSocket documentation. Note that Grafana Live has limitations when several Grafana servers run behind one load balancer, so check the high availability guidance for your topology. Check: open a dashboard with a live streaming panel and confirm the browser's network tab shows an established WebSocket connection with status 101.
Register the redirect URI with the identity provider
If users sign in through an OAuth or OIDC provider, add the exact callback URL to the provider's allowed redirect list. The callback is built from root_url, so it must match the public scheme, host and sub path character for character. Confirm the client ID and secret are set in the authentication section of grafana.ini or as environment overrides. Your identity team usually owns the provider configuration, and the mismatch is the most common cause of a failed sign-in after a proxy change. Check: a sign-in attempt reaches the provider and returns to Grafana without a redirect_uri mismatch error.
Verify sign-in, dashboards and live streaming
Test the full path from a clean browser session outside the internal network. Sign in, open a dashboard that uses several data sources, follow a link that includes a sub path if you use one, and watch a live panel update. Repeat the sign-in after a Grafana restart and after a proxy reload. Record the results and the configuration values in your change record so a later upgrade or certificate renewal can be checked against them. Check: login completes, dashboards render with data, links stay on the public address, and the live panel keeps streaming for several minutes without a dropped connection.
Why a wrong root_url breaks OAuth sign-in and how to diagnose it
Grafana builds the OAuth redirect URI from the root_url setting in the [server] section of grafana.ini, not from the address the browser used to reach the proxy. The identity provider compares the redirect URI in the authorization request against the callback URLs registered for the application, and it rejects the sign-in when they differ in scheme, host, port or path. Behind a reverse proxy that terminates TLS, the most common failure is that root_url still holds the internal address, such as or the http scheme. Grafana then sends the browser to a callback that does not match what is registered, and the provider returns a redirect_uri mismatch error before Grafana sees anything. Set root_url to the exact public URL users type, including https` and any sub path, and make sure the same value is registered with each provider, whether that is generic OAuth or one of the Entra ID, Okta, GitHub, GitLab or Google options that the Grafana authentication docs list for every edition.
Start diagnosis in the browser. Open the developer tools network panel, clear the log, and start a sign-in. Find the request to the provider's authorize endpoint and read the redirect_uri query parameter. Compare it character by character with the callback URL you registered. If the scheme reads http or the host is an internal name, the problem is in Grafana's configuration, not in the provider. Next, check the Grafana server log for the OAuth flow. Errors from the generic OAuth or provider-specific connector usually name the failed step, such as the token exchange or user lookup, and they point you to whether the redirect itself was accepted. Also confirm that the proxy forwards the original Host and X-Forwarded-Proto headers, because a proxy that rewrites the host can make Grafana build the wrong URL even when root_url looks correct. Confirm these details with your identity provider's documentation and your own environment before you change production settings.
Security settings to review once Grafana sits behind a proxy
Once a proxy terminates TLS and forwards traffic to Grafana, several settings that assumed direct browser access need a second look. The cards below cover cookies, forwarded headers, browser policy, version exposure, metrics access and host validation, and each one is a place where a proxy change can quietly weaken a default.
Secure and SameSite cookies
When TLS ends at the proxy, Grafana still sees plain HTTP from the proxy, so cookie flags set on the Grafana side may not match what browsers receive. Set the cookie options that mark session cookies as secure and SameSite in grafana.ini, then confirm in the browser developer tools that the Set-Cookie headers carry those attributes after the request passes through the proxy. Check that login still works across the sign-in redirect.
Trusting forwarded headers
Grafana uses X-Forwarded-For and related headers for logging, rate decisions and some auth flows, so a client that can set those headers directly can spoof its address. Restrict trust to the proxy's own network range, and make sure the proxy overwrites client-supplied forwarding headers instead of appending to them. Test by sending a request directly to Grafana with a forged header and confirming it is ignored.
Content Security Policy and Trusted Types
Grafana's hardening guidance recommends a Content Security Policy and Trusted Types to limit script injection in the browser. Proxies that inject their own scripts, banners or error pages can break these policies, and a permissive policy added at the proxy can override the one Grafana sends. Review the headers the proxy adds or strips, and load the UI with a browser console open to catch blocked resources after each change.
Hiding the version from unauthenticated users
The Grafana version is visible in the UI and in some responses, which helps an attacker match known issues to your instance. Configure Grafana to hide the version from unauthenticated users, and at the proxy remove or avoid adding headers that reveal server software. Verify by requesting the login page and public endpoints without a session and reviewing what comes back.
Authenticating the metrics endpoint
Grafana exposes a metrics endpoint for Prometheus scraping, and the hardening guidance recommends requiring authentication for it. Behind a proxy, a path rule that routes /metrics to the public internet exposes internal data, so either block that path at the proxy for external clients or require a token. Confirm that the scrape job still succeeds from the monitoring network and that an anonymous request from outside is refused.
Domain verification against DNS rebinding
DNS rebinding attacks use a hostname that resolves to an internal address to reach services that trust the host name. Grafana's domain verification setting, combined with the correct domain and root_url values, limits which host names it answers to. Set these to the public hostname only, and confirm that requests with an unexpected Host header are rejected at the proxy or in Grafana.
Questions teams ask before setting up a Grafana reverse proxy
How much effort does a Grafana reverse proxy setup take?
The effort depends mostly on how many public hostnames you publish, whether you serve Grafana from a sub path or a dedicated domain, and how many nodes sit behind the proxy. A single Grafana server behind one hostname with a certificate from your existing CA is a small change. Effort grows when you add a sub path, WebSocket handling for Grafana Live, multiple nodes behind a load balancer, or an OAuth provider that must redirect back to the correct address. Each of these adds configuration to set, then a test pass for login, dashboards, live panels and alerts. Ask any partner to show the test list it will run before agreeing on scope.
Can our team set up a Grafana reverse proxy without outside help?
Yes, if you already run NGINX, Apache, HAProxy or Traefik in production and your team can manage certificates and DNS. The work is mostly configuration: setting the domain and root_url in the Grafana configuration, forwarding the original host and protocol headers, passing the WebSocket upgrade headers, and checking the identity provider's redirect URL. Teams with no experience running a proxy in front of a web application often find the redirect and sub path problems take longer than the proxy itself. A short review by someone who has done it before can shorten that learning curve.
What does a reverse proxy setup need from our team?
Plan for four inputs before work begins:
- DNS control over the hostname that users will type, so you can create the record and point it at the proxy.
- A certificate source for TLS termination, either an internal certificate authority or a public one such as Let's Encrypt, with a renewal process you own.
- Administrative access to the identity provider so its redirect URI can be updated to the final public address and tested.
- A test window where users can sign in, open dashboards and confirm live panels and alert pages behave as expected, with a rollback plan if something fails.
Confirm the exact names, network paths and approval steps with your own change process, since these vary by organization.
Should we choose Traefik or NGINX for Grafana?
Choose the proxy your operations team already runs and can patch, monitor and troubleshoot. NGINX is a common choice for hosts and virtual machines because its configuration is explicit and widely documented. Traefik fits environments where routes are generated from orchestrators such as Docker or Kubernetes, since it listens to providers and updates routes without restarts. Traefik is MIT-licensed and distributed as a single Go binary and an official Docker image. If you are moving from the retired NGINX Ingress Controller on Kubernetes, the Traefik documentation describes an Ingress NGINX provider that supports many of its annotations. Confirm each annotation you rely on against the provider documentation before you assume it carries over.
How does a reverse proxy change when Grafana runs on multiple nodes?
Grafana high availability uses two or more active-active servers behind a load balancer, sharing a MySQL or PostgreSQL database, with database-backed auth tokens so users can reach any node. The proxy therefore needs health checks for each node, consistent forwarding headers on every backend, and a plan for sticky sessions if your deployment requires them. Grafana's documentation notes that alerting needs extra configuration to avoid duplicate notifications and that Grafana Live has limitations in high availability, so test live panels through the load balancer before relying on them. Your database and shared storage also sit in this design and need their own review.
What does a partner's fixed-scope engagement cover for a reverse proxy?
DeployOpen's engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. For this topic, a typical written scope would name the proxy product, the public hostnames, whether Grafana is served from a sub path, the TLS approach, the WebSocket and OAuth redirect checks, the test cases, and the handover documents. DeployOpen implements and documents the configuration inside your infrastructure and can prepare the test evidence you need. It does not issue audit reports or certifications. Ask for the written scope and its exclusions, such as identity provider changes or DNS work owned by another team, before comparing quotes.
What does a Grafana reverse proxy change cost over time?
The initial configuration is one-time work, but the proxy keeps recurring costs: certificate renewal, proxy version upgrades, configuration changes when hostnames or identity providers change, and re-testing after each Grafana upgrade. The Grafana docs describe minor releases every other month and patch releases at least monthly, so plan for regular re-verification of login and live panels. Ask any quote to separate one-time implementation from ongoing support, and to state who performs certificate renewals and proxy patching after the handover.
How DeployOpen scopes and delivers a Grafana reverse proxy setup
DeployOpen plans and builds Grafana reverse proxy setups inside your own infrastructure, whether the proxy is NGINX, Apache, HAProxy or Traefik. We start from the public hostname, the sub path decision, TLS termination and the identity provider's redirect URLs, then test each path, header and redirect before handover.
How we scope
- Written scope names the proxy product, the public hostname and whether Grafana serves from a root path or a sub path.
- Scope records TLS certificate sources, renewal method and which hop terminates encryption inside your network.
- Scope lists identity provider callback URLs, WebSocket needs for Grafana Live and the environments that must be covered.
How we build
- We set root_url and domain in the Grafana configuration to match the external address that users and identity providers see.
- We configure proxy headers, WebSocket upgrade handling and timeouts, then test Grafana Live streams and dashboard refresh through the proxy.
- For multi-node high availability, we check that the proxy routes users consistently and that sessions behave across nodes.
How we hand over
- Deliverables include proxy configuration files, Grafana settings and a dated record of the redirect URLs registered with each identity provider.
- We document the test cases used, including login, OAuth callback, sub path asset loading, Live streaming and certificate renewal.
- Operators receive a runbook for changing hostnames, rotating certificates and diagnosing a wrong root_url.
How we support
- Ongoing support, proxy upgrades and periodic re-testing are available as a retainer after the fixed-scope build.
- Support can cover changes to Grafana upgrades, proxy version updates and new identity provider callbacks.
- Confirm with us in the quote which proxy versions, environments and response windows the retainer includes.

