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
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;
}
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
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
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.