[Resolved] Kubernetes Ingress Error 404 on Non-Root Path of Single Page App

If you’re deploying a web application in Kubernetes using NGINX Ingress, you may encounter a 404 Not Found error when accessing non-root paths. This issue is common when using React Router (SPA), Angular, or Vue.js, as well as APIs mapped to a subpath.

In this guide, we’ll explain why this happens and how to fix it using NGINX Ingress annotations and proper configurations.


Why Does Kubernetes Ingress Return 404 for Non-Root Paths?

By default, NGINX Ingress forwards requests based on the specified path in your Ingress resource. If the backend service doesn’t handle the requested path correctly, it results in a 404 Not Found error.

Common reasons include:

  1. Incorrect Path Handling in the Backend Service – Your service is expecting /, but requests are forwarded with a prefix like /app.
  2. Static Files Not Served Correctly – For SPA applications, direct navigation to a route like /dashboard results in a 404 because there’s no physical file.
  3. NGINX Ingress Path Matching Issues – If you use pathType: Prefix, the request may not be rewritten correctly.

Solution 1: Use rewrite-target in Ingress

To ensure all requests to /app (or any subpath) are properly redirected to / in the backend, use the nginx.ingress.kubernetes.io/rewrite-target annotation.

Example: Ingress YAML for React, Angular, or Vue

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app
        pathType: Prefix
        backend:
          service:
            name: web-app
            port:
              number: 80

How It Works:

  • Requests to /app/dashboard will be rewritten to /dashboard, allowing the frontend app to handle routing correctly.
  • This prevents 404 Not Found errors on page refresh.

Solution 2: NGINX Configuration for Single Page Applications (SPA)

For React, Angular, and Vue, we need to ensure that all paths return index.html. This prevents errors when users directly access a deep route like /dashboard.

Update nginx.conf

If you’re running NGINX inside your container, update the configuration:

server {
    listen 80;
    server_name example.com;

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri /index.html;
    }

    error_page 404 /index.html;
}

Why This Fixes 404 Errors:

  • If a user visits /app/dashboard, and there’s no physical file, NGINX serves index.html, letting React Router (or Vue, Angular) handle routing.

Solution 3: Use pathType: ImplementationSpecific

For more flexible routing in Kubernetes 1.18+, use pathType: ImplementationSpecific to ensure correct request forwarding.

paths:
  - path: /app(/|$)(.*)
    pathType: ImplementationSpecific

This ensures:

  • /app/anything is rewritten properly.
  • Query parameters and subdirectories are preserved.

Solution 4: Serve Your App with a Custom Dockerfile

If you’re deploying a React, Angular, or Vue app in Kubernetes, use the following Dockerfile to serve it with NGINX:

# Build stage
FROM node:18 AS build
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . ./
RUN npm run build

# Serve with NGINX
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

This ensures:

  • The app is built and served correctly.
  • Routing works without 404 errors.

Conclusion

To fix the 404 Not Found issue in Kubernetes Ingress when accessing non-root paths: ✅ Use nginx.ingress.kubernetes.io/rewrite-target: / in Ingress.
Configure NGINX to serve index.html for SPAs.
Use pathType: ImplementationSpecific for better routing.
Ensure your app’s Dockerfile correctly serves static files.

By implementing these solutions, your web application will work smoothly without 404 errors on deep links or refreshes. 🚀

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *