New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Metabase to run at a non-root app context such as /mb/ #2090

Closed
Jacob-Kroeze opened this Issue Mar 5, 2016 · 51 comments

Comments

Projects
None yet
@Jacob-Kroeze
Copy link

Jacob-Kroeze commented Mar 5, 2016

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?

@agilliland agilliland added the Question label Mar 5, 2016

@agilliland

This comment has been minimized.

Copy link
Contributor

agilliland commented Mar 5, 2016

No, there is currently no way to configure Metabase to run at a non-root app context

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Mar 5, 2016

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

@Jacob-Kroeze

This comment has been minimized.

Copy link

Jacob-Kroeze commented Mar 10, 2016

@agilliland Is this up for a pull request? Or, not a priority right now. I may be able to contribute.

@agilliland

This comment has been minimized.

Copy link
Contributor

agilliland commented Mar 10, 2016

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.

@agilliland agilliland changed the title app context for frontend dist allow Metabase to run at a non-root app context such as /mb/ Mar 11, 2016

@agilliland agilliland added the Proposal label Mar 11, 2016

@salsakran salsakran added Help Wanted and removed Proposal labels Mar 24, 2016

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Apr 21, 2016

@Jacob-Kroeze I took a stab at this in #2393. Still very experimental (some images and probably other things are broken)

@tlrobinson tlrobinson self-assigned this Apr 21, 2016

@agilliland agilliland removed the Question label Apr 27, 2016

@TheMP

This comment has been minimized.

Copy link

TheMP commented May 12, 2016

@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?

@lxchavez

This comment has been minimized.

Copy link

lxchavez commented May 24, 2016

+1 for this feature request. I would like to configure a friendly URL like http://mycompanyserver/analytics/ to point to metabase for our enterprise.

@moumny

This comment has been minimized.

Copy link

moumny commented Jun 7, 2016

We have same issue as lxchavez in my company as well.
Small but useful feature

@VikramTiwari

This comment has been minimized.

Copy link
Contributor

VikramTiwari commented Jul 25, 2016

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/

@VikramTiwari

This comment has been minimized.

Copy link
Contributor

VikramTiwari commented Jul 26, 2016

Can someone help me find out what am I missing here?

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Jul 26, 2016

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.

@VikramTiwari

This comment has been minimized.

Copy link
Contributor

VikramTiwari commented Jul 26, 2016

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.

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Aug 8, 2016

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: ReactTraining/react-router#353

@tlrobinson tlrobinson changed the title allow Metabase to run at a non-root app context such as /mb/ Allow Metabase to run at a non-root app context such as /mb/ Aug 8, 2016

@dncpax

This comment has been minimized.

Copy link

dncpax commented Aug 31, 2016

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

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Sep 6, 2016

@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:

  • links: i.e. <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.
  • JS/CSS/image resources: most of these are handled by webpack now, which will also make this pretty easy (my first attempt had trouble with images referenced in .css files but that should be solvable)
  • API endpoints: previously I just made all of these URLs relative and injected a <base href="..."> tag with the root path. Not sure if that's the best way or not.
  • misc: things like window.location = ..., history.pushState(...) etc
@dncpax

This comment has been minimized.

Copy link

dncpax commented Sep 7, 2016

@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 then nothing is displayed because an error occurs (Cannot read property className of undefined in angular.min.js:93).
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...

@luc-poynt

This comment has been minimized.

Copy link

luc-poynt commented Feb 16, 2017

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;
}

}

@dncpax

This comment has been minimized.

Copy link

dncpax commented Feb 16, 2017

@luc-poynt Thanks! Will try it out when time allows. Looks promissing!

@luc-poynt

This comment has been minimized.

Copy link

luc-poynt commented Mar 31, 2017

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;
}
@dncpax

This comment has been minimized.

Copy link

dncpax commented Apr 3, 2017

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

@deitch

This comment has been minimized.

Copy link

deitch commented Apr 8, 2017

@dncpax it might be related to Webpack. Either way, we are backing off of Metabase for now because of it.

tlrobinson added a commit that referenced this issue Apr 10, 2017

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Apr 10, 2017

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

@dncpax

This comment has been minimized.

Copy link

dncpax commented Apr 10, 2017

@tlrobinson Hi there. I can try it out. Can you send the jar file?

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Apr 10, 2017

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Apr 10, 2017

@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

@dncpax

This comment has been minimized.

Copy link

dncpax commented Apr 11, 2017

can i just replace my metabase jar 0.23.1 with this one? and switch back?

@dncpax

This comment has been minimized.

Copy link

dncpax commented Apr 11, 2017

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.

@dncpax

This comment has been minimized.

Copy link

dncpax commented Apr 11, 2017

posted results on PR #4740

@aaronryden

This comment has been minimized.

Copy link

aaronryden commented Apr 14, 2017

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

screen shot 2017-04-14 at 3 28 22 am

@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Apr 14, 2017

@aaronryden Thanks, I've fixed that.

Please put any more issues you find in #4740

@Siddarth434

This comment has been minimized.

Copy link

Siddarth434 commented Sep 27, 2018

@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;
}

}

@Siddarth434

This comment has been minimized.

Copy link

Siddarth434 commented Oct 4, 2018

@tlrobinson , any solution? i am using v0.30.4

@Digma

This comment has been minimized.

Copy link
Contributor

Digma commented Oct 4, 2018

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!

@eirannejad

This comment has been minimized.

Copy link

eirannejad commented Nov 7, 2018

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/;
}
@jiaweicat

This comment has been minimized.

Copy link

jiaweicat commented Nov 30, 2018

@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/;

}
}`

@eirannejad

This comment has been minimized.

Copy link

eirannejad commented Nov 30, 2018

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;
}
@tlrobinson

This comment has been minimized.

Copy link
Member

tlrobinson commented Nov 30, 2018

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.

@csawyerYumaed

This comment has been minimized.

Copy link

csawyerYumaed commented Jan 16, 2019

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?

@flamber

This comment has been minimized.

Copy link

flamber commented Jan 17, 2019

@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;
}
@Siddarth434

This comment has been minimized.

Copy link

Siddarth434 commented Jan 17, 2019

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/;
}

Are you able to download(CSV, XLSX) the embedded reports through Metabase?

@Siddarth434

This comment has been minimized.

Copy link

Siddarth434 commented Jan 17, 2019

@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;
}

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:///metabase/api/public/card/

It goes this way, which results in saying Forbidden page
https:///api/public/card/

My Nginx Configuration is:

location /metabase/ {

proxy_pass http://localhost:3000/;
client_max_body_size 10m;
}

@Siddarth434

This comment has been minimized.

Copy link

Siddarth434 commented Jan 17, 2019

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?

@csawyerYumaed

This comment has been minimized.

Copy link

csawyerYumaed commented Jan 17, 2019

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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment