Nginx reverse proxy : Grafana accessible but some requests fail with 502 Bad Gateway

Hi,

I’m trying to setup Grafana behind Nginx as a reverse proxy for SSL. I can login and go to the user panel, but there are background errors : 502 Bad Gateway.

My grafana.ini file is configured like this :

[server]
protocol = http
http_addr = localhost
http_port = 3000
domain = localhost
root_url = %(protocol)s://%(domain)s:%(http_port)s/

And my Nginx conf :

server {
    server_name foo.bar.com

    listen 443 ssl;
    listen [::]:443 ssl;
    # SSL Configuration with cert etc
    # ...
     
    location / {
        proxy_pass http://localhost:3000/;
        proxy_set_header Host $host;
    }
}

We have Grafana behind nginx too. This is what our nginx.config looks like:

http {
    server {
        listen              3070 ssl;
        ssl_certificate     /path/to/cert.crt;
        ssl_certificate_key /path/to/cert.key;
        location / {
            proxy_pass http://localhost:3000/;
        }
    }
}
events {}

I think that you need change your grafana.init

domain=foo.bar.com root_url=https://foo.bar.com/

I made a clean install of grafana and it works now.

Here is my server block in the ini file :

#################################### Server ####################################
[server]
# Protocol (http, https, h2, socket)
protocol = http

# The ip address to bind to, empty will bind to all interfaces
http_addr = localhost

# The http port  to use
http_port = 3000

# The public facing domain name used to access grafana from a browser
domain = localhost

# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = false

# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
root_url = http://localhost:3000/grafana/

# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
;serve_from_sub_path = false

# Log web requests
;router_logging = false

# the path relative working path
;static_root_path = public

# enable gzip
;enable_gzip = false

# https certs & key file
;cert_file =
;cert_key =

# Unix socket path
;socket =

And my nginx config :

server {
    listen 80;
    server_name foo.bar;
    return 301 https://$host$request_uri;
}

server {
    server_name foo.bar;

    # SSL Configuration
    listen 443 ssl;
    listen [::]:443 ssl;
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key  /path/to/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # drop SSLv3 (POODLE vulnerability)
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_dhparam  /path/to/dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    index index.html;

    location / {
        root /var/www/foo.bar;
    }

    location /grafana/ {
        proxy_pass http://localhost:3000/;
    }
}

If you use this setting, you not able use grafana features like links and shared dashboards.
you must setup the param root_url.

If thats public you also want to remove all the other ancient TLS Versions:

ssl_protocols TLSv1.2 TLSv1.3;

There is no reason to allow the old protocols

You’re both right.
I changed the root_url and domain to match my site.
I also added proxy_set_header X-Real-IP $remote_addr; to the nginx configuration to see the real IP from user session.

1 Like