Serve Grafana through reverse proxy (nginx)

Hey everyone,

apologies for opening another thread on this issue but even after reading through some of them here, and following the documentation I’m still seeing the error message: “If you’re seeing this Grafana has failed to load its application files”.

My Grafana server is reachable only via the internal network, so what I’m doing is accessing the URL at example.com/grafana and forward the request internally via Nginx:

location ~ /grafana/ {
  proxy_pass http://192.168.42.3:3000;
}

This is the server configuration for /etc/grafana/grafana.ini:

[server]
# The public facing domain name used to access grafana from a browser
;domain = localhost
domain = example.com

# 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 = %(protocol)s://%(domain)s:%(http_port)s/
root_url = https://example.com/grafana/

# Serve Grafana from subpath specified in `root_url` setting. By default it is set$
;serve_from_sub_path = false
serve_from_sub_path = true

Am I missing something? I’ve been playing around with this settings for a long time already and I’m getting nowhere.

Any help is much appreciated, thanks!

1 Like

Hi there,

you list the HTTPS protocol in your .ini, which is for secure traffic. Have you also configured TLS? If not, maybe try changing root_url to http://example.com/grafana/

And can you share your full nginx configuration? To troubleshoot, I would first try to proxy traffic to http://localhost/grafana instead of a custom domain. You should be able to accomplish this without modifying the default settings in grafana.ini. Try resetting the settings in grafana.ini and using an nginx config like this:

 server {
            listen 80;
            server_name  localhost;

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

Hi and thanks for the reply,

I have an SSL certificate for the reverse proxy server so when I access my site from the browser it works as expected. But then I want to forward the request to a separate VPS in the internal network which is running Grafana.

So far I’ve configured grafana.ini in many ways without any luck, including as you suggested using http instead of https. I’ve tried other things but I’m lost already so I rather go back to the beginning. I’m back to the default grafana.ini configuration file, and this is my current nginx configuration.

server {
        listen 80;
        listen [::]:80;

        server_name developersojourn.site www.developersojourn.site;

        return 301 https://developersojourn.site$request_uri;
}

server {

        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        root /var/www/developersojourn.site;
        index index.html index.php;

        server_name developersojourn.site www.developersojourn.site;

        include global/optimizations.conf;
        include global/headers.conf;
        include global/wp_super_cache.conf;
        include global/wordpress_security.conf;

        location /grafana {
		        access_log /var/log/nginx/access_test.log;
		        error_log /var/log/nginx/error_test.log;
                proxy_pass http://192.168.42.3:3000;
        }
        
        location = /wp-json/content/posts {
                try_files $uri $uri/ /public_html/index.php$is_args$args;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.3-fpm.sock;
                include global/fastcgi_optimize.conf;
        }  
}

This returns a 404 error when I visit https://developersojourn.site/grafana because by default proxy_pass appends the URI to the path provided, and over at the grafana.ini it’s not setup this way. At this point is where I follow the
Run Grafana behind a reverse proxy
tutorial and make changes as specified:

[server]
domain = developersojourn.site
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
serve_from_sub_path = true

This is when I get the error message that the application files are not loading correctly. The /login page seems to load “correctly” based on the network requests returned from the browser (status 200) but the rest of resources located at public return a 404. This is one example of the request made:

https://developersojourn.site/grafana/public/build/runtime.63a9c1d648180e457252.js

Once again, any help is much appreciated, thanks!

Stab in the dark here, but it might be worth trying it out without the trailing slash in the root_url. At least a lot of the examples I’ve seen are set up that way, though I appreciate that the reverse proxy guide seems to show both (and I’m not sure whether it makes a difference). FWIW, might also be worth trying out different things with respect to trailing slashes in the nginx config (where it definitely matters big time - though what you have looks right to me).

There are a couple of other threads on here where people have shared semi-working configs which might be worth checking out.

Just did a quick check locally as I was curious. Looks like my gut feeling was wrong, and what you are indeed missing are the trailing slashes in your nginx config. I.e. you need:

        location /grafana/ {
		        access_log /var/log/nginx/access_test.log;
		        error_log /var/log/nginx/error_test.log;
                proxy_pass http://192.168.42.3:3000/;
        }

This should actually proxy all requests to the root of your Grafana server. In this case it doesn’t actually matter whether Grafana is being served from the sub-path or not. [I did realize that in my first test the sub-path parameter wasn’t being picked up]

FWIW, if the sub-path serving is working as designed on the Grafana end, the setup should also work if you omit the trailing slashes in your nginx config.

Finally, if you do encounter further issues I’d recommend checking your Grafana log and seeing what requests are coming in, in order to troubleshoot. For example if you see something like

INFO[04-06|19:49:31] Request Completed                        logger=context userId=1 orgId=1 uname=admin method=GET path=/grafana/public/build/runtime.0f5298278016b3e602c9.js status=404 remote_addr=[::1] time_ms=5 size=24558 referer=http://localhost:3000/grafana

with a 404 status, that means that (a) your Nginx proxy isn’t stripping the /grafana path prefix, AND (b) Grafana isn’t serving from the /grafana sub-path - which is when things fail.

Hope this helps get it working!

1 Like

Well, I’m not sure why this worked but I found the issue. First of all thank you both very much for taking the time to help me, I really appreciate that!

I fixed it by using a regex expression for the location directive like so:

location ^~ /grafana/ {
	proxy_pass http://192.168.42.3:3000$request_uri;
}

This makes sure that every requests starting with that URI will match. Then I passed the original URI using the built-in variable $request_uri.

I only realized this because I noticed the access logs for my site showed that these requests were not being forwarded to the grafana server, but the first request for login was. If only I had checked this last night!

About the trailing slash, even though it turned out not to be the issue for me, it seems that if you include it in the proxy_pass path, you have to make sure it’s also above in the location directive. The solution above also works for me even without it. According to the logs at /var/log/grafana/grafana.log you’ll get a double slash and it won’t work.

path=//login status=302

Thanks again for the help, cheers!

1 Like