How to Configure Nginx Ingress Redirect from app.example.org to example.org in Kubernetes


2 views

When working with Nginx Ingress in Kubernetes, domain redirects are a common requirement. In your case, you want to redirect traffic from app.example.org to your primary domain example.org. Let's explore the most effective solutions.

Your existing Ingress configuration handles two hosts with the same backend service:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - example.org
        - app.example.org
      secretName: prod-tls
  rules:
    - host: example.org
      http:
        paths:
          - path: /
            backend:
              serviceName: app-service
              servicePort: 80
    - host: app.example.org
      http:
        paths:
          - path: /
            backend:
              serviceName: app-service
              servicePort: 80

The most straightforward approach is using Nginx Ingress annotations to configure the redirect:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-redirect
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/permanent-redirect: https://example.org
    nginx.ingress.kubernetes.io/permanent-redirect-code: "308"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - app.example.org
      secretName: prod-tls
  rules:
    - host: app.example.org
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: dummy-service
                port:
                  number: 80

For more control, you can use a configuration snippet:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-snippet
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'app.example.org') {
        return 308 https://example.org$request_uri;
      }
spec:
  tls:
    - hosts:
        - example.org
        - app.example.org
      secretName: prod-tls
  rules:
    - host: example.org
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80
    - host: app.example.org
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80
  • Use 308 (Permanent Redirect) instead of 301 if you want to preserve the HTTP method
  • Ensure your TLS configuration covers both domains
  • The dummy service in the first solution can be any existing service, as it won't actually receive traffic
  • Test redirects thoroughly as they can affect SEO and user experience

After applying the configuration, test it with curl:

curl -I http://app.example.org
curl -I https://app.example.org

You should see responses containing 308 Permanent Redirect and the Location: https://example.org header.


apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: redirect-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/permanent-redirect: "https://example.org$request_uri"
    nginx.ingress.kubernetes.io/permanent-redirect-code: "308"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - app.example.org
    secretName: prod-tls
  rules:
  - host: app.example.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dummy-service
            port:
              number: 80

To properly redirect traffic from app.example.org to example.org, we need to create a separate Ingress resource dedicated to handling the redirect. The key annotations are:

nginx.ingress.kubernetes.io/permanent-redirect: "https://example.org$request_uri"
nginx.ingress.kubernetes.io/permanent-redirect-code: "308"

Here's a complete implementation example with dummy backend service:

apiVersion: v1
kind: Service
metadata:
  name: dummy-service
spec:
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dummy-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dummy
  template:
    metadata:
      labels:
        app: dummy
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

For more complex redirect scenarios, you can use configuration-snippet:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: snippet-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'app.example.org') {
        return 308 https://example.org$request_uri;
      }
spec:
  rules:
  - host: app.example.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-service
            port:
              number: 80

Make sure your TLS configuration includes both domains if you're using HTTPS redirects:

tls:
- hosts:
  - example.org
  - app.example.org
  secretName: prod-tls

After applying the configuration, verify the redirect works:

curl -v -k https://app.example.org
# Should return 308 status code with Location: https://example.org/

If the redirect isn't working:

  • Check ingress controller logs for errors
  • Verify the annotation syntax is correct
  • Ensure both hostnames resolve properly
  • Check for conflicting Ingress resources