Search code examples
phpnginxkubernetesnginx-ingress

Trouble getting assets to serve for legacy PHP application behind ingress-nginx


So this is what I'd like to do because my /admin/v2 route continues to work properly... however, the static assets cannot be found for the legacy (<= 2013) PHP application at the /admin route:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-dev"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: ingress-dev
  namespace: dev
spec:
  tls:
    - hosts:
        - localhost
      secretName: tls-localhost-dev
  rules:
    - host: localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: client-cluster-ip-service-dev
                port:
                  number: 3000
          - path: /admin
            pathType: Prefix
            backend:
              service:
                name: admin-cluster-ip-service-dev
                port:
                  number: 4000
          - path: /admin/v2
            pathType: Prefix
            backend:
              service:
                name: admin-v2-cluster-ip-service-dev
                port:
                  number: 4001
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-cluster-ip-service-dev
                port:
                  number: 5000

That being said, I can the assets to load properly with the following, but then the /admin/v2 route (or /admin-v2) no longer works and instead goes to the /admin route:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-dev"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/add-base-url: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.org/client-max-body-size: "500m"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^(/admin)$ $1/ permanent;
  name: ingress-dev
  namespace: dev
spec:
  tls:
    - hosts:
        - localhost
      secretName: tls-localhost-dev
  rules:
    - host: localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: client-cluster-ip-service-dev
                port:
                  number: 3000
          - path: /admin/?(.*)
            pathType: Prefix
            backend:
              service:
                name: admin-cluster-ip-service-dev
                port:
                  number: 4000
          - path: /admin/v2
            pathType: Prefix
            backend:
              service:
                name: admin-v2-cluster-ip-service-dev
                port:
                  number: 4001
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-cluster-ip-service-dev
                port:
                  number: 5000

So I'd like to keep the first configuration, but also have the static assets load properly for /admin and I'm stuck on how to do that.

ingress-nginx traffic to /admin should be going to nginx running in the Pod. I think the solution will likely have to come from there. This is the config for it:

server {
  listen 4000;
  # rewrite ^([^.]*[^/])$ $1/ permanent;
  root   /usr/share/nginx/html/src;

  include /etc/nginx/default.d/*.conf;

  index app.php index.php index.html index.htm;

  client_max_body_size 500m;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    # Mitigate https://httpoxy.org/ vulnerabilities
    fastcgi_param HTTP_PROXY "";
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fastcgi.conf;
  }
}

In addition, this is how the assets are being referred to in the index.tbs HTML template file, which I've tried appending admin/ to, but that just makes the URL localhost/admin/admin/css/default.css when you check it in the Elements tab:

<link rel="STYLESHEET" type="text/css" href="css/portal.css" />
<link rel="STYLESHEET" type="text/css" href="css/default.css" />

Suggestions for how to fix this?

And to clarify, when I look at the .css it is trying to serve, it is just the compiled HTML for the website.


EDIT:

A little bit of progress... I added the following to the nginx.conf:

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
    rewrite  ^/admin/(.*) /$1 break;
  }

Now when I land at the localhost/admin route it is serving CSS assets correctly, but then I login which directs me to localhost/admin/index.php and it says "File not found." So I need to exclude .php from this somehow.


Solution

  • OK, got it sorted out. Maybe not best practice...

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-dev"
        nginx.ingress.kubernetes.io/ssl-redirect: "true"
    
        # this is apparently needed otherwise it doesn't serve the assets
        # trying to do this in nginx.conf, just automatically re-routes to
        # localhost:4000/admin for some reason
        nginx.ingress.kubernetes.io/configuration-snippet: |
          rewrite ^(/admin)$ $1/ permanent;
      name: ingress-dev
      namespace: dev
    spec:
      tls:
        - hosts:
            - localhost
          secretName: tls-localhost-dev
      rules:
        - host: localhost
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: client-cluster-ip-service-dev
                    port:
                      number: 3000
              - path: /admin
                pathType: Prefix
                backend:
                  service:
                    name: admin-cluster-ip-service-dev
                    port:
                      number: 4000
              - path: /admin/v2
                pathType: Prefix
                backend:
                  service:
                    name: admin-v2-cluster-ip-service-dev
                    port:
                      number: 4001
              - path: /api
                pathType: Prefix
                backend:
                  service:
                    name: api-cluster-ip-service-dev
                    port:
                      number: 5000
    
    server {
      listen 4000;
      root   /usr/share/nginx/html/src;
    
      include /etc/nginx/default.d/*.conf;
    
      index app.php index.php index.html index.htm;
    
      client_max_body_size 500m;
    
      location / {
        try_files $uri $uri/ /index.php$is_args$args;
        rewrite  ^/admin/?(.*) /$1 break;
      }
    
      location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        rewrite  ^/admin/?(.*) /$1 break;
        fastcgi_param HTTP_PROXY "";
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
      }
    }