dashboard: Proxying the dashboard on a sub path broken

Environment
Installation method: Deployment in Kubernetes, behind an NGINX proxy
Kubernetes version: 1.17.4
Dashboard version: 2.0.0-rc6
Steps to reproduce

Deploy the dashboard and expose it with an nginx that proxies to that dashboard on a sub path, so that the dashboard can be reached by a URL like https://some-host-name/kubernetes-dashboard.

Sample nginx config:

server {
          listen 80;
          server_name some-host-name;

	  location = /kubernetes-dashboard {
		  return 302 https://$server_name/kubernetes-dashboard/;
	  }
	  location /kubernetes-dashboard/ {
		  set $upstream "kubernetes-dashboard.syseleven-kubernetes-dashboard.svc.cluster.local:80";
		  rewrite ^/kubernetes-dashboard(/.*) $1 break;
		  proxy_pass http://$upstream$uri$is_args$args;
		  proxy_http_version 1.1;
		  proxy_pass_request_headers on;
		  proxy_set_header Upgrade $http_upgrade;
		  proxy_set_header Connection $connection_upgrade;
	  }
}
Observed result

The dashboard should be proxied and load correctly.

Expected result

The main HTML can be loaded, but all CSS and JS files can’t be loaded because their href is https://some-host-name/some.css instead of https://some-host-name/kubernetes-dashboard/some.css.

Comments

This used to work in 2.0.0-rc5, but started to break in 2.0.0-rc6, because the main HTML of 2.0.0-rc6 contains an additional <base href="/"> tag, which was not present in 2.0.0-rc5. This is likely related to the Angular 9 upgrade. With a bit of digging I was only able to change the base tag on built time, not on runtime. And I was not able to remove it completely again. It’s likely though that I overlooked an option 😃.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 7
  • Comments: 20 (6 by maintainers)

Most upvoted comments

It is a pity that we need to apply weird workarounds for simple URL rewriting. I managed to get it working on /dashboard path with Nginx Ingress by following manifest:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  labels:
    app.kubernetes.io/name: kubernetes-dashboard  
  annotations:
    kubernetes.io/ingress.class: nginx
    # Add https backend protocol support for ingress-nginx
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Accept-Encoding "";
      sub_filter '<base href="/">' '<base href="/dashboard/">';
      sub_filter_once on;
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: my.example.com
      http:
        paths:
          - path: /dashboard(/|$)(.*)
            backend:
              serviceName: kubernetes-dashboard
              servicePort: 443

update to @vutny, for kubernetes >=1.19 use:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
  labels:
    app.kubernetes.io/name: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Accept-Encoding "";
      sub_filter '<base href="/">' '<base href="/dashboard/">';
      sub_filter_once on;
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /dashboard(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: kubernetes-dashboard
                port:
                  number: 443

tried this a bunch of different ways in my nginx reverse proxy but still to no avail 😦

        location ~ /k8s/dash/ {
            set $backend    "http://kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local/";
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $http_host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            rewrite ^/k8s/dash(/.*) /$2 break;
            proxy_set_header Accept-Encoding "";
            sub_filter '<base href="/">' '<base href="http://kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local/">';
            sub_filter_once off;
            rewrite ^/k8s/dash/(.*\.(js|css|png|gif|svg|ttf|eot|woff|woff2))$ /$2 last; 
            include       /etc/nginx/mime.types;
            proxy_pass $backend;
        }
  

after hours of tinkering i figured it out:

location ~* "^/k8s/dashboard(/|$)(.*)" {
            proxy_set_header Accept-Encoding "";
            sub_filter '<base href="">' '<base href="/k8s/dashboard/">';
            sub_filter_once on;
            rewrite "(?i)/k8s/dashboard(/|$)(.*)" /$2 break;
            proxy_pass $backend;
            proxy_redirect off;
        }

how i figured it out : launched the ingress for it and then looked at the /etc/nginx/nginx.conf of the ingress controller and then took the ingress specific stuff out

update to @vutny, for kubernetes >=1.19 use:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
  labels:
    app.kubernetes.io/name: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Accept-Encoding "";
      sub_filter '<base href="/">' '<base href="/dashboard/">';
      sub_filter_once on;
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /dashboard(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: kubernetes-dashboard
                port:
                  number: 443

With Azure Ingress Controller you can fix subpath issue like below

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/backend-path-prefix: "/"
spec:
  rules:
    - http:
        paths:
          - path: /dashboard/*
            pathType: Prefix
            backend:
              service:
                name: kubernetes-dashboard
                port:
                  number: 9090       

Also note that the order of nginx.ingress.kubernetes.io/rewrite-target and nginx.ingress.kubernetes.io/configuration-snippet matters for anyone bumping their head ^^’

We can confirm that with RC-6 the introduced baseHref = / breaks the possibility to move to a subpath. With RC-5 however it does work. Guess we should consider this a bug?

Hi @floreks , I see that there is a fix for this issue (March 2020…) but how do you configure it ? I went through the doc, github and the fix , and couldn’t find the right way to configure it.

thanks @yonatankahana and @vutny for the work around (following floreks fix, I had to replace the href from “/” to “”)

@jjournet, could you plz explain what have you done to deal with unreachable assets? because in version 6.0.8 there is no “<base href="/">” in html, but static files are tried to be loaded from the root.

Hi @floreks , I see that there is a fix for this issue (March 2020…) but how do you configure it ? I went through the doc, github and the fix , and couldn’t find the right way to configure it.

thanks @yonatankahana and @vutny for the work around (following floreks fix, I had to replace the href from “/” to “”)