maxuru ~ % cat grafana/enable-tls
Enable TLS and secure cookies on Grafana
/etc/grafana/grafana.ini[server]protocol = httpshttp_port = 3000domain = grafana.example.comroot_url = https://grafana.example.com/cert_file = /etc/grafana/certs/grafana.crtcert_key = /etc/grafana/certs/grafana.keymin_tls_version = TLS1.2
[security]cookie_secure = truecookie_samesite = strictWhat the defaults are
Section titled “What the defaults are”[server]protocol = httphttp_port = 3000min_tls_version = ""
[security]cookie_secure = falsecookie_samesite = laxGrafana serves plain HTTP out of the box, and cookie_secure = false
follows from it — a Secure cookie would not be sent over the plaintext
connection Grafana is expecting.
The consequence is direct: the session cookie that represents a logged-in Grafana user, up to and including the Server Admin, travels unencrypted. Anyone positioned on the path can lift it and replay it. No password needed, and password rotation does not help.
Two ways to do this, and one is more common
Section titled “Two ways to do this, and one is more common”Terminate TLS in Grafana with cert_file and cert_key, as the fix block
shows. Simplest when Grafana is directly exposed.
Terminate at a reverse proxy — nginx, Apache or HAProxy — and speak HTTP to Grafana over loopback. This is the more common production arrangement and it is a perfectly good answer, with one condition people miss:
[server]protocol = httphttp_addr = 127.0.0.1root_url = https://grafana.example.com/
[security]cookie_secure = truecookie_secure = true is still required, even though Grafana itself speaks
HTTP. The cookie’s Secure flag is about the browser’s connection to the proxy,
not the proxy’s connection to Grafana. Leaving it false because “Grafana is on
HTTP” reintroduces the whole problem one hop further out.
http_addr = 127.0.0.1 is the other half — without it Grafana listens on all
interfaces, and the plaintext port stays reachable alongside the TLS one. And
root_url must be the public HTTPS URL or Grafana will generate broken links
and OAuth redirects.
Cookie flags
Section titled “Cookie flags”cookie_samesite defaults to lax, which is reasonable. strict is better for
an internal tool where no cross-site navigation into Grafana is expected; it
will break inbound links that expect to arrive already-authenticated, such as an
alert notification that deep-links to a panel.
Grafana sets HttpOnly on its session cookie regardless, so JavaScript cannot
read it. That is a good default and worth knowing so you do not go looking for a
setting.
[security]strict_transport_security = truestrict_transport_security_max_age_seconds = 31536000Defaults to false. Enable it once HTTPS is confirmed working —
includeSubDomains and preload options exist here too, and carry
the same one-way risk as anywhere else. If a reverse proxy
already sets HSTS, set it in one place, not both.
Related
Section titled “Related”- Change the Grafana admin password — the credential this stops leaking in transit.
- Security headers and CSP — the other browser-side settings, and one bad default.