nginx k8s ingress - forcing www AND https?

2/7/2018

I have a kubernetes setup that looks like this:

nginx ingress -> load balancer -> nginx app

after getting an SSL certificate for www.foo.com, I've installed it in my nginx ingress as a secret, and it works as expected - traffic to www.foo.com gets redirected to the https version instead, and browsers display a secure connection indicator. Great.

What hasn't been easy, however, is getting the ingress to redirect non-www traffic to the www version of the site. I've tried using kubernetes.io/from-to-www-redirect: "true", but it doesn't seem to do anything - navigating to foo.com doesn't redirect me to the www version of the url, but either takes me to an insecure version of my site, or navigates me to default backend - 404 depending on whether i include foo.com as a host with it's own path in my ingress.

I have been able to set up a patchy redirect by adding the following to my actual application's nginx config -

server {
  listen       80;
  server_name  foo.com;
  return       301 http://www.foo.com$request_uri;
}

UPDATE: from-to-www-redirect DOES work; you just have to reference it with nginx.ingress.kubernetes.io rather than kubernetes.io as I was. But, this only works for foo.com - typing in https://foo.com explicitly causes browsers to display a security warning and no redirect to the proper URL of https://www.foo.com occurs.

Here's my current config for the nginx ingress itself:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo-https-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
  rules:
    - host: www.foo.com
      http:
        paths:
          - backend:
              serviceName: foo-prod-front
              servicePort: 80
            path: /
  tls:
      - hosts:
          - www.foo.com
        secretName: tls-secret
-- Artem Zakharov
kubernetes
nginx

4 Answers

6/21/2018

You need to add the certificate for the domain you want to be redirected:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo-https-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
  rules:
    - host: foo.com
      http:
        paths:
          - backend:
              serviceName: foo-prod-front
              servicePort: 80
            path: /
    - host: www.foo.com
      http:
        paths:
          - backend:
              serviceName: foo-prod-front
              servicePort: 80
            path: /
  tls:
      - hosts:
          - foo.com
          - www.foo.com
        secretName: tls-secret

I am not completely sure, whether from-to-www-redirect works with this setup, but you can replace it with the following lines, which do work:

    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'foo.com' ) {
        rewrite ^ https://www.foo.com$request_uri permanent;
      }
-- Marius
Source: StackOverflow

7/31/2019

I found the docs to be confusing here as well. Below is an example i have working. I believe you need to define the naked url in tls certs to avoid a cert error(your cert needs to be valid for both foo.com and www.foo.com). You CANNOT list the naked url under rules: hosts because that will get picked up prior to the redirect.

http://foo.com -> https://www.foo.com

https://foo.com -> https://www.foo.com

http://www.foo.com -> https://www.foo.com

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo-https-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
  rules:
    - host: www.foo.com
      http:
        paths:
          - backend:
              serviceName: foo-frontend
              servicePort: 80
            path: /
  tls:
      - hosts:
          - foo.com
          - www.foo.com
        secretName: tls-secret
-- Steve Miskiewicz
Source: StackOverflow

9/19/2019

I have the following doing the job with the latest nginx-ingress 0.25.1:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-rule-web
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/from-to-www-redirect: 'true'
spec:
  rules:
    - host: foo.org
      http:
        paths:
          - path: /
            backend:
              serviceName: web
              servicePort: 80
  tls:
    - hosts:
        - foo.org
        - www.foo.org
      secretName: letsencrypt-prod
-- demisx
Source: StackOverflow

2/7/2018

This is rather a problem with your ssl certificate than the nginx ingress configuration. My guess is that your certificate is only valid for foo.com and not for www.foo.com. If you access www.foo.com your browser shows a security warning because the certificate isn't valid for the domain you are visiting.

-- Lukas Eichler
Source: StackOverflow