{{tag>k8s kubernetes pulumi nginx}}
====== nginx proxy pass to a different domain in k8s  ======
This is applicable when using the [[https://kubernetes.github.io/ingress-nginx/|nginx ingress controller]].
Since k8s already uses the proxy_pass from the ''backend'' directive, you can't overwrite this. The solution is to use [[https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#server-snippet|server-snippet annotation]].
Let's say you need to proxy pass the //example.org/foo/// to //other.domain.org//. Regular location config for this would look like:
location /foo/ {
	proxy_pass              https://other.domain.org/;
        # you may or may not need the below redirect, it depends on what the proxied server returns
	proxy_redirect          https://anoother.domain.org https://www.yetanotherdomain.com/bar/;
	proxy_read_timeout      60;
	proxy_connect_timeout   60;
	proxy_set_header        X-Real-IP $remote_addr;
	proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header        X-Forwarded-Proto $scheme;
	proxy_set_header        Host other.domain.org;
	proxy_set_header        X-NginX-Proxy true;
	proxy_set_header        Connection "";
}
Your kubectl ingress yaml file should look like:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: external-proxy-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      location /foo/ {
        proxy_pass https://other.domain.org/;
        proxy_set_header Host other.domain.org;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
      }
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: dummy-service
            port:
              number: 80
You still need a dummy service even if there are no pods that are backing it:
apiVersion: v1
kind: Service
metadata:
  name: dummy-service
  namespace: default
spec:
  ports:
    - port: 80
      targetPort: 80
  clusterIP: None
When deployed, if you inspect the ingress controller with cmd like
  kubectl -n ingress-nginx --kubeconfig=kubeconfig exec ingress-nginx-799008-controller-f67867867 -- cat /etc/nginx/nginx.conf
  
you will see that there should be at least 2 ''location'' directives, one for the ''dummy-service'' for the backend and another one for your custom location.
Here's the [[https://www.pulumi.com|Pulumi]] go example :-?:
...
	// Create the Ingress resource
	_, err := v1.NewIngress(ctx, ingressName, &v1.IngressArgs{
		Metadata: &metav1.ObjectMetaArgs{
			Name:      pulumi.String(ingressName),
			Namespace: pulumi.String(serviceNamespace),
			Annotations: pulumi.StringMap{
				"nginx.ingress.kubernetes.io/server-snippet": pulumi.String(fmt.Sprintf(`
					location /foo/ {
	proxy_pass              https://other.domain.org/;
        # you may or may not need the below redirect, it depends on what the proxied server returns
	proxy_redirect          https://anoother.domain.org https://www.yetanotherdomain.com/bar/;
	proxy_read_timeout      60;
	proxy_connect_timeout   60;
	proxy_set_header        X-Real-IP $remote_addr;
	proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header        X-Forwarded-Proto $scheme;
	proxy_set_header        Host other.domain.org;
	proxy_set_header        X-NginX-Proxy true;
	proxy_set_header        Connection "";
}
					location /bar/ {
						return 301 /foo/;
					}
					location /test/ {
						return 301 https://www.example.com/;
					}
			`)),
		},
		},
		Spec: &v1.IngressSpecArgs{
			IngressClassName: pulumi.String("nginx"),
			Rules: v1.IngressRuleArray{
				&v1.IngressRuleArgs{
					Host: pulumi.String(domainName),
					Http: &v1.HTTPIngressRuleValueArgs{
						Paths: v1.HTTPIngressPathArray{
							&v1.HTTPIngressPathArgs{
								Path:     pulumi.String("/"),
								PathType: pulumi.String("Prefix"),
								Backend: &v1.IngressBackendArgs{
									Service: &v1.IngressServiceBackendArgs{
										Name: pulumi.String(serviceName),
										Port: &v1.ServiceBackendPortArgs{
											Number: pulumi.Int(servicePort),
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}, pulumi.Provider(k8sProvider))
	if err != nil {
		return err
	}
...
====== Tested on ======
  * kubectl v1.27.3
  * Pulumi v3.149.0
====== See also ======
  * [[wiki:create_docker_config_secret_private_image_pulling_pulumi|Create a Docker config Secret for private image pulling in Pulumi]]
====== References ======
  * https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#server-snippet