How to capture subdomain in nginx ingress - nginx

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: (/|$)(.*)

Related

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)

kubernetes nginx ingress error with configuration-snippet

I have following ingress.yaml file
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-configuration-snippet
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/configuration-snippet: |
location /base/path/v1/api/update {
deny all;
return 404;
}
spec:
rules:
- http:
paths:
- path: /base/path(/|$)(.*)
backend:
serviceName: myApi
servicePort: 8080
But when I send a request to https:///base/path/v1/api/update it succeeds and I got following error in nginx ingress controller
Error: exit status 1
2020/08/06 18:35:07 [emerg] 1734#1734: location "/base/path/v1/api/update" is outside location "^/base/path(/|$)(.*)" in /tmp/nginx-cfg008325631:2445
nginx: [emerg] location "/base/path/v1/api/update" is outside location "^/base/path(/|$)(.*)" in /tmp/nginx-cfg008325631:2445
nginx: configuration file /tmp/nginx-cfg008325631 test failed
Can somebody help?
The configuration-snippet is to add configs to locations.
If you want to add a custom location to the server context, you should use the server-snippet instead:
Using the annotation nginx.ingress.kubernetes.io/server-snippet it is
possible to add custom configuration in the server configuration
block.
You also need to use some modifiers and regex to make it work (~* and ^).
The following config should work:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-configuration-snippet
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/server-snippet: |
location ~* "^/base/path/v1/api/update" {
deny all;
return 403;
}
spec:
rules:
- http:
paths:
- path: /base/path(/|$)(.*)
backend:
serviceName: myApi
servicePort: 8080
The final nginx.config should end like this:
$ kubectl exec -n kube-system nginx-ingress-controller-6fc5bcc8c9-chkxf -- cat /etc/nginx/nginx.conf
[...]
location ~* "^/base/path/v1/api/update" {
deny all;
return 403;
}
location ~* "^/base/path(/|$)(.*)" {
[...]
}

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.

Nginx ingress kubernetes Proxy Pass

I need configure a proxy pass in a nginx ingress.
The rule must be:
%USER%.test.domain.com to app.test.domain.com/%USER%
*It must be a proxy pass NOT a redirect
I created this Ingress but it does not work
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test02-ingress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/server-snippet: |
server_name ~^(?<subdomain>.+)\.test\.domain\.it;
location = / {
proxy_pass https://app.test.domain.it/$subdomain/;
proxy_set_header Host $subdomain.test.domain.it;
}
spec:
rules:
- host: "*.test.domain.it"
http:
paths:
- path: /
backend:
serviceName: test01-svc
servicePort: 80
``

ingress nginx redirect from www to https

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

Resources