Kubernetes NGINX Ingress configmap 301 redirect - kubernetes

Using an NGINX Ingresss in Kubernetes, I can't see a way to forward my traffic from non-www to www, or to another domain etc on a per-host basis
I've tried looking in configmap docs but can't see what I need. Maybe it can go in the ingress itself?
I've also seen an example using annotations but this seems to be ingress-wide, so I couldn't have specific redirects per host

Indeed a redirect is possible with a simple annotation:
nginx.ingress.kubernetes.io/permanent-redirect: https://www.gothereinstead.com
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
But as you mentioned, it's "Ingress" wide and not configurable per host, per domain or even per path. So you'll have to do it yourself through the ingress.kubernetes.io/configuration-snippet annotation, which gives you a great deal of power thanks to regular expressions:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: self-made-redirect
annotations:
ingress.kubernetes.io/configuration-snippet: |
if ($host = 'blog.yourdomain.com') {
return 301 https://yournewblogurl.com;
}
if ($host ~ ^(.+)\.yourdomain\.com$) {
return 301 https://$1.anotherdomain.com$request_uri;
}
spec:
rules:
- host: ...
If you are not quite used to NGINX, you'll know more about what's possible in the snippet, particularly what is the $host variable right in the NGINX documentation.

To redirect all traffic regardless of using HTTP or HTTPS from example.com and www.example.com to newdomain.example.com I ended up with the following solution.
In this example I'm also using cert-manager.io to request the certs for www.example.com and example.com.
The redirect is done using the annotation nginx.ingress.kubernetes.io/permanent-redirect
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: redirect-example-to-newdomain
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/permanent-redirect: https://newdomain.example.com
spec:
tls:
- hosts:
- example.com
- www.example.com
secretName: example.com-tls
rules:
- host: example.com
- host: www.example.com

I have problem with annotations server-snippet. When the certificate is renewed, the process crashes. When I remove annotations, renewed certificate is successful. Is there another solution? For example, creating a redirect 301 in separate pod?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
ingress.kubernetes.io/ssl-redirect: "true"
meta.helm.sh/release-name: DOMAIN
meta.helm.sh/release-namespace: DOMAIN
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~ ^/online-web {
return 301 /online;
}
if ($host = 'DOMAIN-alias.cz') {
return 301 https://DOMAIN.cz;
}
if ($host ~ ^(.+)\.DOMAIN-alias\.cz$) {
return 301 https://$1.DOMAIN.cz$request_uri;
}
if ($host = 'DOMAIN-alias-2.cz') {
return 301 https://DOMAIN.cz;
}
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-buffer-size: 128k
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ "csas.woltair.cz") {
return 301 https://woltair.cz/zakaznik/doporuceni;
}
............
............
- host: csas.woltair.cz
http:
paths:
- backend:
service:
name: woltair-cz-fe
port:
number: 8080
path: /zakaznik/doporuceni
pathType: ImplementationSpecific

Related

Kubernetes Ingress path redirection from root to some path

I have Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
labels:
app.kubernetes.io/managed-by: Helm
annotations:
kubernetes.io/ingress.class: nginx
meta.helm.sh/release-name: ingress
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~ favicon.ico {
log_not_found off;
}
nginx.ingress.kubernetes.io/cors-allow-headers: content-type, x-att-timezone
nginx.ingress.kubernetes.io/cors-allow-methods: GET, POST, PUT, DELETE, OPTIONS
nginx.ingress.kubernetes.io/cors-allow-origin: '*'
nginx.ingress.kubernetes.io/cors-expose-headers: 'x-att-userrole, x-att-userdetails, x-att-userid, xatt-location '
nginx.ingress.kubernetes.io/enable-cors: 'true'
nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'
nginx.ingress.kubernetes.io/proxy-body-size: 10000m
nginx.ingress.kubernetes.io/proxy-connect-timeout: '6000000'
nginx.ingress.kubernetes.io/proxy-read-timeout: '6000000'
nginx.ingress.kubernetes.io/proxy-send-timeout: '6000000'
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
tls:
- hosts:
- st-my-doamin.com
secretName: ingress
rules:
- host: st-my-doamin.com
http:
paths:
- path: /rootpath/.*
pathType: Prefix
backend:
service:
name: someService
port:
number: 80
And i want to create redirection like this :
if i go to st-my-doamin.com/rootpath i will be redirect to st-my-doamin.com/rootpath/login
i tried to create this redirection and got error :
This page isn’t working st-my-doamin.com redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS
As you are getting the error "ERR_TOO_MANY_REDIRECTS" follow this link it helps in clearing this error. Follow this Link in redirecting the Path.
Add the below annotation in yaml :
nginx.ingress.kubernetes.io/rewrite-target: /get_similarity/$2
And add Path as below:
- path: /rootpath(/|$)(.*)

ingress rewrite domain www to non-www url

I am trying to redirect my domain 'www.test.example.com' to test.example.com
in ingress i have added annotation
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'www.test.wotnot.io' ) {
rewrite ^/(.*)$ https://app.test.wotnot.io/$1 permanent;
}
it's not working as expected.
For testing i have try this
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'test.example.com' ) {
rewrite ^/(.*)$ https://google.com/$1 permanent;
}
which is working fine.
My site is working on test.example.com and ssl certificate.
Whole ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
certmanager.k8s.io/cluster-issuer: wordpress-staging
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
#nginx.ingress.kubernetes.io/configuration-snippet: |
#if ($host = 'www.test.wotnot.io' ) {
# rewrite ^/(.*)$ https://test.example.io/$1 permanent;
#}
name: wordpress-staging-ingress
spec:
rules:
- host: test.example.io
http:
paths:
- backend:
serviceName: wordpress-site
servicePort: 80
path: /
tls:
- hosts:
- test.example.io
secretName: wordpress-staging
Ingress has an annotation nginx.ingress.kubernetes.io/from-to-www-redirect: "true" which already handle this:
In some scenarios is required to redirect from www.domain.com to
domain.com or vice versa. To enable this feature use the annotation
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
Attention: For HTTPS to HTTPS redirects is mandatory the SSL Certificate defined in the Secret, located in the TLS section of Ingress, contains both FQDN in the common name of the certificate.
It's better that you use it instead of fighting/tweaking the configuration-snippet annotation.

How do I redirect a www url to a no-www url using nginx-ingress-controller?

I am trying to get the url www.example.com to redirect itself to example.com while preserving everything about the original request in k8s 1.11.1
I am attempting to do this using a simple Ingress, and am then using annotations to redirect it.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/permanent-redirect: https://example.com
nginx.ingress.kubernetes.io/ssl-redirect: "True"
name: example-redirect
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: example
servicePort: http
The issue here is that I don't want to have any rules/backend. I simply want to redirect www.example.com to example.com using an Ingress, but k8s Ingresses require me to have rules. Are there any workarounds here?
Actually, Ingress resource has strongly defined prerequisites for the relevant API specification. You may exclude rules: field from the general configuration, however backend: should be definitely specified, in the way that Nginx Ingress controller could route network traffic to the target endpoint in case no rules declared or matched.
Whenever you create any specific settings for Nginx Ingress controller either via Annotations or ConfigMaps, both of the options doing the same job of applying some specific configuration to the underlying nginx.conf file which resides on nginx-ingress-controller Pod. It means that Ingress controller applies server {} and location {} blocks into the corresponded Nginx web server Pod for particular host:
server {
server_name www.example.com ;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
listen 443 ssl http2;
listen [::]:443 ssl http2;
.............
location / {
set $namespace "default";
set $ingress_name "example-redirect";
set $service_name "example";
set $service_port "http";
set $location_path "/";
......................
}
}
Therefore, I suppose that you can capture nginx.conf file, based on Ingress resource configuration and then apply it independently inside Ingress controller Pod.
I assume that you may consider also to use nginx.ingress.kubernetes.io/from-to-www-redirect: "true" annotation in order to achieve the goal in current scenario.
Following should do:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'www.example.com' ) {
rewrite ^ https://example.com$request_uri permanent;
}
name: example-redirect
spec:
tls:
- hosts:
- www.example.com
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: example
servicePort: http

Nginx ingress controller still redirect to SSL

I am experiencing this issue. My application needs to receive connection under SSL only with WebSocket. HTTP requests should be forced to not being redirected. My ingress configuration is
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: in-camonline
namespace: cl5
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.org/websocket-services: "svc-ws-api"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
ingress.kubernetes.io/affinity: "ClientIP"
spec:
tls:
- hosts:
- foo.bar.com
secretName: cl5-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /socket.io
backend:
serviceName: svc-ws-api
servicePort: 8000
- path: /
backend:
serviceName: svc-http-service
servicePort: 80
I also disabled the ssl-redirect globally adding an item into the ConfigMap
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
#use-proxy-protocol: "false"
ssl-redirect: "false"
Now if I do request using curl, requests won't being redirected. If I try to run my front-end application every request after the WSS will be forced to being redirected to use HTTPS
Request URL: http://foo.bar.com/2/symbols
Request Method: OPTIONS
Status Code: 307 Internal Redirect
Referrer Policy: no-referrer-when-downgrade
Any suggestion about how to achieve that?
Finally, I sorted it out. If someone is reading this, easy you are not alone!
Jokes aside, nginx-controller was setting header Strict-Transport-Security after the first HTTPS call (socket.io polling in my case). This header forces the browser to use TLS for the next requests. You can read more about this header here https://developer.mozilla.org/it/docs/Web/HTTP/Headers/Strict-Transport-Security
What I did is to disable the option adding the entry hsts: false on the ingress-controller's ConfigMap object.
You can find more here https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#hsts
Hope this can help you :)
There is another solution.
If you want to disable HSTS just make the max-age zero. like this!!
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($scheme = https) {
add_header Strict-Transport-Security "max-age=0;";
}
link : https://justin-g.tistory.com/176

Redirect in Traefik from one domain to another

According to the Traefik 1.7 documentation you should be able to have Traefik perform a 302 redirect using:
traefik.ingress.kubernetes.io/redirect-regex
traefik.ingress.kubernetes.io/redirect-replacement
My goal is to simply remove the www. from the address.
This is what I've tried, but I get a 404 service not found.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: www-redirect
namespace: public
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/redirect-regex: ^https?://www.example.com/(.*)
traefik.ingress.kubernetes.io/redirect-replacement: https://example.com/$1
spec:
rules:
- host: www.example.com
Unfortunately the documentation isn't explicit on how to use them. At the time of writing the only google hit on this is the documentation (above).
My current work around (assuming it'll help explain the question) is to route www. traffic to nginx which returns a 302.
server {
listen 80;
server_name www.example.com;
return 302 https://example.com$request_uri;
}
This seems like overkill.
I was having the same issue and ended up making it work with:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: www-redirect
namespace: public
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/preserve-host: "true"
traefik.ingress.kubernetes.io/redirect-permanent: "true"
traefik.ingress.kubernetes.io/redirect-regex: "^https://www.(.*)"
traefik.ingress.kubernetes.io/redirect-replacement: "https://$1"
spec:
tls:
- hosts:
- "example.com"
- "www.example.com"
secretName: example-tls
rules:
- host: example.com
- host: www.example.com
Basically I needed both rules.
As a side note, I also start the trafik pod with the following flags:
args:
- --api
- --kubernetes
- --logLevel=INFO
- --entryPoints=Name:https Address::443 TLS
- --entrypoints=Name:http Address::80 Redirect.EntryPoint:https
- --defaultentrypoints=https,http