Grafana reverse proxy setup with NGINX, Apache, HAProxy or Traefik

How to place self-hosted Grafana behind a reverse proxy with the right domain, root_url, TLS and WebSocket handling, and how a wrong root_url breaks OAuth sign-in.

On this page

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.

FactorTraefikNGINX, Apache and HAProxy
Fit for a VM-based GrafanaRuns 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 clusterReads 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 requirementPath-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 LiveWebSocket 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 certificatesLet'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.
LicensingMIT 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 effortLow 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 confirmTeams 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.

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.

  1. 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.

  2. Set root_url and domain in grafana.ini

    Set the public address in the [server] section of grafana.ini, using the root_url key for the full public URL including scheme and any sub path, and the domain key 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.