ingress nginx redirect from www to https - nginx

I'm trying to redirect http://www... and https://www... to https://... using ingress-nginx. How can I do that?
I've tried adding the following custom configuration using the annotation nginx.ingress.kubernetes.io/server-snippet and nginx.ingress.kubernetes.io/configuration-snippet:
# 1
if($host = "www.example.com") {
return 308 https://example.com$request_uri;
}
# 2
server {
server_name www.example.com;
return 308 https://example.com$request_uri;
}
# 3
server_name www.example.com;
return 308 https://example.com$request_uri;
But I get an error in the nginx controller logs for #1:
2019/12/07 20:58:47 [emerg] 48898#48898: unknown directive "if($host" in /tmp/nginx-cfg775816039:418
nginx: [emerg] unknown directive "if($host" in /tmp/nginx-cfg775816039:418
nginx: configuration file /tmp/nginx-cfg775816039 test failed
For #2 I get an error that the server block is not allowed at that position and using #3 leads to infinite redirects. My ingress yaml looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/ingress.global-static-ip-name: "example-com"
nginx.ingress.kubernetes.io/rewrite-target: "/"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400s"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400s"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/limit-rps: "20"
nginx.ingress.kubernetes.io/client-max-body-size: "100m"
nginx.ingress.kubernetes.io/configuration-snippet: |
# see above
spec:
tls:
- hosts:
- example.com
secretName: certificate-secret
rules:
- host: sub.example.com
http:
paths:
- backend:
serviceName: service-sub
servicePort: 1234
# more subdomains here
- host: example.com
http:
paths:
- backend:
serviceName: service-example
servicePort: 1235
- host: "*.example.com"
http:
paths:
- backend:
serviceName: service-example-wildcard
servicePort: 1236
I've also tried setting the nginx.ingress.kubernetes.io/from-to-www-redirect: "true" annotation, but that leads to a different error:
2019/12/07 21:20:34 [emerg] 51558#51558: invalid server name or wildcard "www.*.example.com" on 0.0.0.0:80
nginx: [emerg] invalid server name or wildcard "www.*.example" on 0.0.0.0:80
nginx: configuration file /tmp/nginx-cfg164546048 test failed

Ok I got it. The missing space after if fixed it. Thank you mdaniel :)
Here is a working configuration that redirects anything to https://... without www:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-nginx-integration
namespace: integration
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/ingress.global-static-ip-name: "example-com"
nginx.ingress.kubernetes.io/rewrite-target: "/"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400s"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400s"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/limit-rps: "20"
nginx.ingress.kubernetes.io/client-max-body-size: "100m"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = "www.example.com") {
return 308 https://example.com$request_uri;
}
spec:
tls:
- hosts:
- example.com
secretName: certificate-integration-secret
rules:
- host: subdomain.example.com
http:
paths:
- backend:
serviceName: service-emviwiki
servicePort: 4000
# ... more rules, NO www here

Related

Nginx 503 ingress controller k8s

I have an application running on nginx port 9000, and a service attached to it. If I put service as a LoadBalancer, I can open IP:PORT/app/pages in my browser (ClusterIP and NodePort with nginx doesn't work). Created Ingress controller with ALB, and A record to point to app.mydomain.com, but I keep getting 503 or 404 errors, even 400 sometimes (tried couple of ports/paths etc). Can someone point me to what should I look at? I want to be able to open https://app.mydomain.com/app/pages. cert-manager is complaining with 400 errors also when retrieving the certificate.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-app-dev
namespace: app-dev
annotations:
cert-manager.io/issuer: letsencrypt-nginx
ingress.kubernetes.io/rewrite-target: /
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.mydomain.com
secretName: letsencrypt-nginx
rules:
- host: app.mydomain.com
http:
paths:
- pathType: Prefix
backend:
service:
name: app-service
port:
number: 8080
path: /
apiVersion: v1
kind: Service
metadata:
name: app-service
namespace: app-dev
spec:
type: LoadBalancer
ports:
- port: 9090
protocol: TCP
targetPort: 8080
selector:
app: app
IP of Ingress is added as a A record to DNS (app.mydomain.com). This is my nginx conf in the docker image
bash-5.1# cat /etc/nginx/conf.d/default.conf
server {
listen 8080 ssl;
ssl_certificate /ssl/cert;
ssl_certificate_key /ssl/key;
location / {
root /www;
autoindex off;
add_header 'Access-Control-Allow-Origin' '*';
}
location /healthz {
return 200 'ok';
}
}

How to capture subdomain in nginx ingress

I want to capture subdomain and rewrite URL with /subdomain, For example bhautik.bhau.tk rewrite to bhau.tk/bhautik.
I also https://github.com/google/re2/wiki/Syntax tried group syntax
Here is my nginx ingress config:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: subdomain
namespace: subdomain
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
# nginx.ingress.kubernetes.io/rewrite-target: /$sub
nginx.ingress.kubernetes.io/server-snippet: |
set $prefix abcd;
if ($host ~ ^(\w+).bhau\.tk$) {
// TODO?
}
nginx.ingress.kubernetes.io/rewrite-target: /$prefix/$uri
spec:
rules:
- host: "*.bhau.tk"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: subdomain
port:
number: 80
How do I capture subdomain from $host?
I believe you want a redirect instead of rewrite. Here is the server-snippet you need:
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ ^(?<subdom>\w+)\.(?<basedom>bhau\.tk)$) {
return 302 https://$basedom/$subdom/ ;
}
If you really want a rewrite where the URL that the user sees remains unchanged but instead the request will be routed to a subpath served by the same service:
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ ^(?<subdom>\w+)\.(?<basedom>bhau\.tk)$) {
rewrite ^/(.*)$ /$subdom/$1 ;
}
Remove the rewrite-target annotation that specifies $prefix. You don't need it.
The ?<capturename> and $capturename pair is the trick you are looking for.
You can try out the
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ "bhautik.bhau.tk")
{
rewrite ^ https://bhau.tk$host permanent;
}
name: test-ingress
spec:
rules:
- host: bhau.tk
http:
paths:
- backend:
serviceName: app-service
servicePort: 3000
path: (/|$)(.*)

Kubernetes Ingress redirecting to directory different than nginx's root

Basically, I have a nginx conf with something like that :
server {
server_name localhost;
listen 80;
root /var/www/projectA/public_html;
}
And a (working) ingress that redirects to the root without a problem :
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: main-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
rules:
- host: projectA.com
http:
paths:
- path: /
backend:
serviceName: main-service
servicePort: 80
Now, I'd need another host ingress, let's say medias.projectA.com, that shows/manages medias (pictures uploaded through projectA's forms).
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: medias-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
rules:
- host: medias.projectA.com
http:
paths:
- path: /
backend:
serviceName: main-service
servicePort: 80
What I'm trying to set is as follows :
projectA.com => /var/www/projectA/public_html
medias.projectA.com => /var/www/projectA/medias
What I tried but failed : Changing the nginx's root to /var/www/projectA, and then set the main ingress's path to /public_html (instead of /), and the media ingress's path to /medias (instead of /) => Got 404
What I also tried : Setting a new nginx conf with a different port (81) that points to /var/www/projectA/medias/public_html as a root. Then create a new service "media-service" that listens to port 81 for the medias ingress => medias.projectA.com/ redirects me to projectA.com
server {
server_name localhost;
listen 80;
root /var/www/projectA/public_html;
}
server {
server_name localhost;
listen 81;
root /var/www/projectA/medias;
}
Added a new port 81 in main-service:
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
- port: 81
targetPort: http
protocol: TCP
Ingress :
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: medias-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
rules:
- host: medias.projectA.com
http:
paths:
- path: /
backend:
serviceName: main-service
servicePort: 81
Still can't get to have medias.projectA.com/ point to /var/www/projectA/medias (always /var/www/projectA/public_html)

Nginx Ingres Redirect only on path to another server

I have setup nginx ingress like this on kubernetes
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: animefanz-ktor-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- mydomain.com
secretName: my-tls
rules:
- host: mydomain.com
http:
paths:
- path: /myapp(/|$)(.*)
backend:
serviceName: myservice
servicePort: 8080
So everything working fine but i want to do one thing when ever https://mydomian.com/myapp/api/history called then i want to redirect it to https://mydomain2.com/myapp2/api/history along with get params that is.
So i want to just forward one api request to another server.
I think you can configure it with nginx server-snippet/configuration-snippet annotation.
There is related stackoverflow question about that.
And examples provided by #Thanh Nguyen Van
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite /preview https://test.app.example.com$uri permanent;
spec:
rules:
- host: test.example.io
http:
paths:
- path: /
backend:
serviceName: service-1
servicePort: 80
- host: test.app.example.io
http:
paths:
- path: /preview/*
backend:
serviceName: service-2
servicePort: 80
And #Harsh Manvar
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/server-snippet: |
location ~ /preview {
rewrite /preview https://test.app.example.com$uri permanent;
}
name: staging-ingress
spec:
rules:
- host: test.example.io
http:
paths:
- path: /
backend:
serviceName: service-1
servicePort: 80
- path: /preview/*
backend:
url:
serviceName: service-2
servicePort: 80
tls:
- hosts:
- test.example.io
secretName: staging
Additionally there is related github issue about that.
Hope you find this useful.

ingress-nginx http redirect code: "301" too many redirects

I tried to change configmap for nginx in order to change default permenant redirection code from 308 to 301, but i faced a "too many redirect".
here is my config:
configmap.yaml
apiVersion: v1
data:
proxy-connect-timeout: "15"
proxy-read-timeout: "600"
proxy-send-timeout: "600"
hsts-include-subdomains: "false"
body-size: "64m"
server-name-hash-bucket-size: "256"
kind: ConfigMap
metadata:
name: nginx
ingress-website.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wordpress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
ingress.kubernetes.io/force-ssl-redirect: 'true'
ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/permanent-redirect: https://www.example.com
nginx.ingress.kubernetes.io/permanent-redirect-code: '301'
spec:
tls:
- hosts:
- example.com
- www.example.com
- blog.example.com
secretName: website-tls
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: domain-website
servicePort: 8080
- host: www.example.com
http:
paths:
- path: /
backend:
serviceName: example-website
servicePort: 8080
- host: blog.example.com
http:
paths:
-
backend:
serviceName: wordpress
servicePort: 80
path: /
i am wondering to redirect to https using 301 code and not 308

Resources