Is there a way to configure application context for front end dist files? I'm trying to serve Metabase behind nginx at, for example {hostname}/mb/
But, for example again, /app/dist/styles.bundle.css is not a relative link. Do I need to do a custom build? Learn more nginx-foo?
No, there is currently no way to configure Metabase to run at a non-root app context
A possible simple fix for this would be to use the value (or at least the path portion?) of the site-url setting in a <base href="..."> tag of the <head> of index.html, and use relative instead of absolute URLs for everything.
https://stackoverflow.com/questions/1889076/is-it-recommended-to-use-the-base-html-tag
@agilliland Is this up for a pull request? Or, not a priority right now. I may be able to contribute.
sure, if you want to take a stab you are welcome to go for it. i'd encourage doing a quick write up of how you plan to proceed and sharing it to get feedback before doing too much coding.
@Jacob-Kroeze I took a stab at this in #2393. Still very experimental (some images and probably other things are broken)
@tlrobinson Hi, I find this feature quite useful. Can I somehow help you with your PR? Do you know why is your branch failing to build?
+1 for this feature request. I would like to configure a friendly URL like http://mycompanyserver/analytics/ to point to metabase for our enterprise.
We have same issue as lxchavez in my company as well.
Small but useful feature
So I was trying to set it up the way @tlrobinson has suggested, and after doing some changes and pushing it up, it gives me following error on browser.
Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://104.198.196.198/metabase/app/dist/styles.bundle.css?4a405a2abca714f472df06e69d1399ff"
Code: https://github.com/VikramTiwari/metabase/tree/feature_non_root_app
Live: http://104.198.196.198/metabase/
Can someone help me find out what am I missing here?
I'm not sure exactly what's going on there. What webserver + configuration are you using in front of Metabase?
As I mentioned above, that branch is experimental. At this points it's diverged a lot from masterand will likely need to be started from scratch.
So I have started from current master (as of yesterday), and updated code is here. The webserver is nginx and with following configuration:
server {
listen 80;
listen [::]:80;
server_name 104.198.196.198;
location /metabase/ {
proxy_pass http://127.0.0.1:8080;
}
}
Inside the server the code is running in a docker container built using dockerfile present in the project.
FYI if anyone wants to attempt this now you'll probably want to take a look at the discussions here now that we're using react-router: https://github.com/reactjs/react-router/issues/353
@tlrobinson do you mean it is possible with a small change to solve this? what would you add/change to allow me to run off /mb/?
I can inject changes using nginx sub_filter directive, that replaces text in files as they are served. So I can fpr instance transform all '="/app/' into '="/mb/app'. It's the react.js router that's giving me trouble...
@dncpax I suspect it would be difficult to use sub_filter to perfectly replace every URL. There are a number of types of URLs we need to make sure get replaced:
<a href="...">s which should now all be using react-router's <Link to="...">, which will make this easy. My last comment was just referring to this case.<base href="..."> tag with the root path. Not sure if that's the best way or not.window.location = ..., history.pushState(...) etc@tlrobinson well I have it replacing all requests already, so I can see on chrome console all requests coming from /mb/.
Now, if I don't add a
If I do add the base href tag, then I can see all content. Only login does not work ;)
I can login using url:3000 and continue browsing /mb/ just fine.
But as soon as I start browsing cards everything breaks apart... this is where I can see the router going crazy...
works for us, in case it can help other: mind you we using SSL, terminated by nginx
upstream metabase_server {
server 127.0.0.1:3000 fail_timeout=0;
}
server {
listen 80;
server _;
return 301 https:://metabase.xxx.com:$request_uri;
}
server {
listen 443;
server_name metabase.xxx.com;
include /etc/nginx/modules.d/ssl.conf;
#pass through headers from metabase which are considered invalid by Nginx server.
ignore_invalid_headers off;
location @metabase {
sendfile off;
proxy_pass http://metabase_server;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
# this is the maximum upload size
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location / {
try_files $uri @metabase;
}
}
@luc-poynt Thanks! Will try it out when time allows. Looks promissing!
sub_filter probably only will work for assets, not quite for api endpoints (if someone succeeds, do let me know).
In the end, messing with the content of a response is just asking for trouble, even for a good proxy like nginx.
This would be really useful.
At the moment, this is a deal breaker for us. None of the suggested workarounds are useable in our context (auto-provisioning of a lot of apps behind a proxy on deployment).
@luc-poynt with your setup what is the metabase url our users use?
@dncpax with my init script it runs as the user metabase
see the attache init script we use
@luc-poynt what I meant was what does your metabase url look like? What url do your enter on the browser?
ok, now I get it. I was trying something like https://server/metabase...
@luc-poynt you have a typo in your init script. line 183:
function relaod_it()
Im traveling, but I think https://server/metabase is doable, just need couple rewrite, is there any info as what url is breaking ?
here some ES/Kibana ngisn config : we would need something very similar
# Kibana web interface
# This is the default behavior, go to kibana
location / {
proxy_pass http://localhost:5601/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_request_headers on;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 8m;
client_body_buffer_size 128k;
}
# Kibana web interface
location ~ ^/kibana/(?<kb>.*) {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 900;
proxy_connect_timeout 900;
proxy_pass http://127.0.0.1:5601/$kb;
proxy_redirect off;
}
# elasticsearch and kopf plugin interface
location ~ ^/es.*$ {
proxy_pass http://127.0.0.1:9200;
rewrite ^/es(.*) /$1 break;
}
location ~ ^/kopf/.*$ {
proxy_pass http://localhost:9200;
rewrite ^/kopf/(.*) /_plugin/kopf/$1 break;
}
location ~ ^/head/.*$ {
proxy_pass http://localhost:9200;
rewrite ^/head/(.*) /_plugin/head/$1 break;
}
@luc-poynt I am very interested on making this work. I'll try revive my config and see what doesn't work. But looking at this thread it seems I got to the point where login and cards didn't work...
I don't know proxying rules enough to fully understand your config...
@dncpax it might be related to Webpack. Either way, we are backing off of Metabase for now because of it.
@maesenka @luc-poynt @dncpax @deitch I've opened a PR for this at #4740. It would be amazing if you could try it out and let me know how it works. It should require very little proxy configuration (I've included examples for nginx and caddy).
@tlrobinson Hi there. I can try it out. Can you send the jar file?
@dncpax Sure, here's a jar: https://www.dropbox.com/s/hyfspysmn5h50qg/metabase-pr-4740.jar?dl=1
@jodok @TheMP @nouney @haolez @jalalmostafa @wvengen @jornh @lkraav @Jacob-Kroeze @lxchavez @moumny @VikramTiwari If you all are still interested in this feature it would be great if you could test it out. See the jar posted above and PR #4740
can i just replace my metabase jar 0.23.1 with this one? and switch back?
Hi there, never mind my question above. I installed a new instance. So far so good. Everything is working just want to try sharing and embedding.
posted results on PR #4740
hi @tlrobinson i noticed an issue with the download option. CSV / JSON apparently don't use the /metabase prefix and try to post directly to /api. Is this fixable?
Cannot POST /api/dataset/csv

@aaronryden Thanks, I've fixed that.
Please put any more issues you find in #4740
@aaronryden @tlrobinson I have the same problem.
My CSV/ JSON/ XLSX downloads does not go with the nginx configuration. this is my conf, please let me know what wrong i am doing.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /usr/share/nginx/html;
location /metabase/ {
proxy_pass http://localhost:3000/;
proxy_force_ranges on;
proxy_set_header Host $host;
proxy_set_header X-Originator-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 10m;
}
}
@tlrobinson , any solution? i am using v0.30.4
Hi @Siddarth434
We are runnnining metabase from a non-root app context. I just tested our nginx config with metabase 0.30.4 and it seems to be working properly even downloading CSVs works.
I am not an nginx guru so I cannot really tell you what does not work with your config but here is our config:
server {
server_name {{ nginx_hostname }};
ignore_invalid_headers off; #pass through headers from metabase which are considered invalid by Nginx server.
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location /{{ app.name }}/metabase/ {
proxy_redirect off;
# Settings for Websocket proxying (see http://nginx.org/en/docs/http/websocket.html)
# Based on https://github.com/metabase/metabase/blob/master/bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Default timeout happens after 60 seconds. Increasing for long time running queries
# Based on https://github.com/metabase/metabase/blob/master/docs/troubleshooting-guide/datawarehouse.md
# and https://www.scalescale.com/tips/nginx/504-gateway-time-out-using-nginx/
proxy_connect_timeout 200;
proxy_send_timeout 200;
proxy_read_timeout 200;
send_timeout 200;
proxy_pass http://localhost:{{ app.port }}/;
}
}
Maybe that helps!
Same here for me. Simple nginx reverse proxy config works. Except for favicon.ico that fails since the directive does not seem to be included in the html code.
location /metabase/ {
proxy_pass http://<machine ip>:3000/;
}
@Digma I am using v0.30.4,but don't work.Not docker,run by jar.this is my conf, please let me know what wrong i am doing.
`server {
# server listening
listen *:80;
server_name -;
ignore_invalid_headers off; #pass through headers from metabase which are considered invalid by Nginx server.
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location /dashboard/metabase/ {
proxy_redirect off;
# Settings for Websocket proxying (see http://nginx.org/en/docs/http/websocket.html)
# Based on https://github.com/metabase/metabase/blob/master/bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Default timeout happens after 60 seconds. Increasing for long time running queries
# Based on https://github.com/metabase/metabase/blob/master/docs/troubleshooting-guide/datawarehouse.md
# and https://www.scalescale.com/tips/nginx/504-gateway-time-out-using-nginx/
proxy_connect_timeout 200;
proxy_send_timeout 200;
proxy_read_timeout 200;
send_timeout 200;
proxy_pass http://localhost:3005/;
}
}`
I updated my nginx config to this and it works very well now. (Metabase is running in a docker container and exposing port# 3000). Even the /favicon.ico GET works.
location /mb/ {
rewrite ^/mb/(.*)$ http://subdomain.company.com:3000/$1;
}
I've started collecting example configurations here: https://github.com/tlrobinson/metabase-proxy-examples, just Caddy so far because that's what I've been using lately.
If anyone wants to contribute equivalent Nginx/Apache/etc examples that would be great.
This worked fine in v0.30.4, i.e. prior to your patch.
browser URL: https://www.example.com/reporting/
stock docker image, setup site-url and configure nginx like this:
site-url: https://www.example.com/reporting/
upstream metabase-prod {
server {{.Address}}:{{.Port}}
}
location /reporting {
proxy_read_timeout 2400;
proxy_pass http://metabase-prod;
rewrite ^/reporting/(.*) /$1 break;
proxy_set_header Host $host;
}
This doesn't work anymore in v0.31.2
instead I get warning messages in the console:
Warning: the Metabase site URL basename "/reporting/" does not match the actual basename "/". reporting:36:21
You probably want to update the Site URL setting to "https://www.example.com/"
Which makes little sense. Sure docker is answering requests at /, but the external browser URL is /reporting/
turning off the rewrite doesn't help because the URL's you are sending to the browser are things like this:
<link href="app/dist/vendor.bundle.css?00f24a2eeccb0afbc72602c65192b43e"
when they should be $site-url/app/dist/vendor.bundle.css?00f24a2eeccb0afbc72602c65192b43e
Setting site-url as suggested:
metabase@dev=# select value from setting where key='site-url';
value
---------------------------------------
https://www.example.com/
(1 row)
returns this:
Warning: the Metabase site URL basename "//" does not match the actual basename "/". reporting:36:21
You probably want to update the Site URL setting to "https://www.example.com/"
and of course still doesn't work, to no-one's surprise.
Or do you see all this working some other way?
@csawyerYumaed
I haven't tested, but I'm pretty sure it's because your rewrite is after the proxy_pass.
location /reporting {
rewrite ^/reporting/(.*) /$1 break;
proxy_read_timeout 2400;
proxy_set_header Host $http_host;
proxy_pass http://metabase-prod/;
}
Same here for me. Simple nginx reverse proxy config works. Except for
favicon.icothat fails since the directive does not seem to be included in the html code.location /metabase/ { proxy_pass http://<machine ip>:3000/; }
Are you able to download(CSV, XLSX) the embedded reports through Metabase?
@csawyerYumaed
I haven't tested, but I'm pretty sure it's because yourrewriteis after theproxy_pass.location /reporting { rewrite ^/reporting/(.*) /$1 break; proxy_read_timeout 2400; proxy_set_header Host $http_host; proxy_pass http://metabase-prod; }
It works the embed part and dashboard download part but report export to CSV Fails as the configuration does not take through the location path defined in the nginx. I am not using docker, i am running the JAR file on the server directly.
Instead of download going this way:
https://
It goes this way, which results in saying Forbidden page
https://
My Nginx Configuration is:
location /metabase/ {
proxy_pass http://localhost:3000/;
client_max_body_size 10m;
}
Hi @Siddarth434
We are runnnining metabase from a non-root app context. I just tested our nginx config with metabase 0.30.4 and it seems to be working properly even downloading CSVs works.
I am not an nginx guru so I cannot really tell you what does not work with your config but here is our config:server { server_name {{ nginx_hostname }}; ignore_invalid_headers off; #pass through headers from metabase which are considered invalid by Nginx server. gzip on; gzip_comp_level 4; gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /{{ app.name }}/metabase/ { proxy_redirect off; # Settings for Websocket proxying (see http://nginx.org/en/docs/http/websocket.html) # Based on https://github.com/metabase/metabase/blob/master/bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # Default timeout happens after 60 seconds. Increasing for long time running queries # Based on https://github.com/metabase/metabase/blob/master/docs/troubleshooting-guide/datawarehouse.md # and https://www.scalescale.com/tips/nginx/504-gateway-time-out-using-nginx/ proxy_connect_timeout 200; proxy_send_timeout 200; proxy_read_timeout 200; send_timeout 200; proxy_pass http://localhost:{{ app.port }}/; } }Maybe that helps!
@Digma ,
My Nginx Configuration is:
location /metabase/ {
proxy_pass http://localhost:3000/;
client_max_body_size 10m;
}
Not able to download embedded reports. could you have a look if i am missing anything?
No difference:
location /reporting/ {
rewrite ^/reporting/(.*) /$1 break;
proxy_read_timeout 2400;
# Settings for Websocket proxying (see http://nginx.org/en/docs/http/websocket.html)
# Based on https://github.com/metabase/metabase/blob/master/bin/aws-eb-docker/.ebextensions/metabase_config/metabase-setup.sh
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://metabase-dev;
}
Console output:
Warning: the Metabase site URL basename "/reporting/" does not match the actual basename "/". reporting:36:21
You probably want to update the Site URL setting to "https://www.example.com/"
Which is not really true. The actual basename from docker's perspective is / but the actual basename from the end-user perspective is /reporting/
I'm still experiencing this issue
docker metabase v0.32.1, with nginx
# docker
docker run -d -p 3005:3000 --name metabase metabase/metabase
# nginx
location /metabase/ {
proxy_pass http://127.0.0.1:3005;
}
Assets file still in /app/dist/ path with <base href="/" />
So where can I configure this base tag? It's never mentioned in docs
@daorren You need to update the "Site URL" in Metabase Admin > Settings > General.
@flamber Thank you for your information!
Is there a way to update Site URL without having the site up? Env var or cli startup param?
@camsaul I would expect MB_SITE_URL to work but it doesn't seem to have any effect. I know there's some weirdness around how we store that setting due to stripping trailing slashes. How hard would it be to get MB_SITE_URL to work?
@redchuck In the meantime the easiest way is probably to connect to the Metabase application database and update the setting. Something like:
UPDATE SETTING
SET VALUE = 'whatever'
WHERE KEY = 'site-url'
Make sure the value doesn't have a trailing slash.
@tlrobinson MB_SITE_URL should work but since the setting has a custom magic getter that might be overriding the env var. If that's the case that's not how I meant for it to work and something I can fix with the Settings framework generally. I will investigate this and fix
@redchuck it turns out MB_SITE_URL actually does work, if you include the trailing slash. See the last couple comments in #9764.
For me it does not load correctly i have used the mb_site_url to define a address hostname:8051/metabase it seems like the data is not downloading completly so the title displays metabase and some content can be loaded but not all.
@tlrobinson is this the correct way?
Define a server for the metabase port
upstream metabase-backend {
server metabase:3000;
}
location /metabase/{
proxy_pass http://metabase-backend;
}
Response in chrome

in gui

The version is docker metabase v0.32.9
@ZerNox I don't have time to look into this right now, but I've got some example configurations for Caddy available at https://github.com/tlrobinson/metabase-proxy-examples (accepting PRs for Nginx examples!)

Still having this issue with MB_SITE_URL. the browser tried access to domain.tld/app/dist/...js first with 404 and then tried domain.tld/metabase/app/dist/...js. The latter path is correct, however blocked by both Firefox and Chrome.
Firefox complains differently, but by large the same
The resource from “http://domain.tld/metabase/app/dist/app-main.bundle.js?0d1325582067a4b57db2” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
I'm using v0.32.9 in docker with nginx reverse proxy from the host.
The issue still persists in v0.33.4. Metabase doesn't reacts to the changes in in Site Url even from GUI, database, env. Works from root only. Is it going to be fixed? Thanks.
@amaris12 There's a regression in 0.33.4, which will be fixed by #11206, and most likely be in 0.33.5
Most helpful comment
Still having this issue with MB_SITE_URL. the browser tried access to
domain.tld/app/dist/...jsfirst with 404 and then trieddomain.tld/metabase/app/dist/...js. The latter path is correct, however blocked by both Firefox and Chrome.Firefox complains differently, but by large the same
I'm using v0.32.9 in docker with nginx reverse proxy from the host.