Repository: kubernetes/ingress-nginx
Pull request #6985 (2021-03-24 07:44:42)

auto backend protocol for HTTP/HTTPS
## What this PR does / why we need it:
It allows to set protocol for proxy_pass according to request scheme

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## How Has This Been Tested?
Manual testing in kubernetes cluster

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [x] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I've read the [CONTRIBUTION](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md) guide
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.


k8s-ci-robot: Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

:memo: **Please follow instructions at <https://git.k8s.io/community/CLA.md#the-contributor-license-agreement> to sign the CLA.**

It may take a couple minutes for the CLA signature to be fully registered; after that, please reply here with a new comment and we'll verify.  Thanks.

---

- If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address.  Check your existing CLA data and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).
- If you signed the CLA as a corporation, please sign in with your organization's credentials at <https://identity.linuxfoundation.org/projects/cncf> to be authorized.
- If you have done the above and are still having issues with the CLA being reported as unsigned, please log a ticket with the Linux Foundation Helpdesk: <https://support.linuxfoundation.org/>
- Should you encounter any issues with the Linux Foundation Helpdesk, send a message to the backup e-mail support address at: login-issues@jira.linuxfoundation.org

<!-- need_sender_cla -->

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
	
k8s-ci-robot: Welcome @vdksystem! <br><br>It looks like this is your first PR to <a href='https://github.com/kubernetes/ingress-nginx'>kubernetes/ingress-nginx</a> 🎉. Please refer to our [pull request process documentation](https://git.k8s.io/community/contributors/guide/pull-requests.md) to help your PR have a smooth ride to approval. <br><br>You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. [Here is the bot commands documentation](https://go.k8s.io/bot-commands). <br><br>You can also check if kubernetes/ingress-nginx has [its own contribution guidelines](https://github.com/kubernetes/ingress-nginx/tree/master/CONTRIBUTING.md). <br><br>You may want to refer to our [testing guide](https://git.k8s.io/community/contributors/devel/sig-testing/testing.md) if you run into trouble with your tests not passing. <br><br>If you are having difficulty getting your pull request seen, please follow the [recommended escalation practices](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#why-is-my-pull-request-not-getting-reviewed). Also, for tips and tricks in the contribution process you may want to read the [Kubernetes contributor cheat sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md). We want to make sure your contribution gets all the attention it needs! <br><br>Thank you, and welcome to Kubernetes. :smiley:
k8s-ci-robot: Hi @vdksystem. Thanks for your PR.

I'm waiting for a [kubernetes](https://github.com/orgs/kubernetes/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fingress-nginx).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/ingress-nginx/pull/6985#" title="Author self-approved">vdksystem</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **elvinefendi** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @elvinefendi` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fingress-nginx).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes/ingress-nginx/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["elvinefendi"]} -->
nicolaballotta: hi, any update on this @cmluciano @ElvinEfendi? Would you be able to review it?
valeriano-manassero: I would like to not drop this one since I think it may be useful.
rikatz: @vdksystem please sign the CLA :)
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/ingress-nginx/pull/6985#" title="Author self-approved">vdksystem</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **rikatz** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @rikatz` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fingress-nginx).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes/ingress-nginx/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["rikatz"]} -->

Patch:
diff --git a/OWNERS b/OWNERS
index 250bce4e8..1d90c4cd5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,15 +1,12 @@
 # See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
 
 approvers:
-  - ingress-nginx-admins
-  - ingress-nginx-maintainers
-  - ElvinEfendi
-  - rikatz
+- ingress-nginx-admins
+- ingress-nginx-maintainers
+- sig-network-leads
 
 reviewers:
-  - ElvinEfendi
-  - cmluciano
-  - rikatz
+- ingress-nginx-reviewers
 
 emeritus_approvers:
-  - aledbf  # 2020-04-02
+- aledbf  # 2020-04-02
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 30f781cfc..b313f36b8 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -2,9 +2,31 @@
 
 aliases:
   sig-network-leads:
-    - caseydavenport
-    - dcbw
-    - thockin
+  - caseydavenport
+  - dcbw
+  - thockin
+
   ingress-nginx-admins:
-    - bowei
+  - bowei
+  - rikatz
+
   ingress-nginx-maintainers:
+  - ElvinEfendi
+  - justinsb
+  - rikatz
+  - strongjz
+
+  ingress-nginx-reviewers:
+  - ElvinEfendi
+  - cmluciano
+  - rikatz
+  - strongjz
+  - tao12345666333
+
+  ingress-nginx-helm-maintainers:
+  - ChiefAlexander
+  - cpanato
+
+  ingress-nginx-helm-reviewers:
+  - ChiefAlexander
+  - cpanato
diff --git a/README.md b/README.md
index cdbd96a4a..3675e690c 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
 # NGINX Ingress Controller
 
 [![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/ingress-nginx)](https://goreportcard.com/report/github.com/kubernetes/ingress-nginx)
-[![GitHub license](https://img.shields.io/github/license/kubernetes/ingress-nginx.svg)](https://github.com/kubernetes/ingress-nginx/blob/master/LICENSE)
+[![GitHub license](https://img.shields.io/github/license/kubernetes/ingress-nginx.svg)](https://github.com/kubernetes/ingress-nginx/blob/main/LICENSE)
 [![GitHub stars](https://img.shields.io/github/stars/kubernetes/ingress-nginx.svg)](https://github.com/kubernetes/ingress-nginx/stargazers)
-[![GitHub stars](https://img.shields.io/badge/contributions-welcome-orange.svg)](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md)
+[![GitHub stars](https://img.shields.io/badge/contributions-welcome-orange.svg)](https://github.com/kubernetes/ingress-nginx/blob/main/CONTRIBUTING.md)
 [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkubernetes%2Fingress-nginx.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkubernetes%2Fingress-nginx?ref=badge_shield)
 
 ## Overview
@@ -20,15 +20,6 @@ See the [Getting Started](https://kubernetes.github.io/ingress-nginx/deploy/) do
 
 If you encounter issues, review the [troubleshooting docs](docs/troubleshooting.md), [file an issue](https://github.com/kubernetes/ingress-nginx/issues), or talk to us on the [#ingress-nginx channel](https://kubernetes.slack.com/messages/ingress-nginx) on the Kubernetes Slack server.
 
-## Contributing
-
-Thanks for taking the time to join our community and start contributing!
-
-- This project adheres to the [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md). By participating in this project, you agree to abide by its terms.
-- See [CONTRIBUTING.md](CONTRIBUTING.md) for information about setting up your environment, the workflow that we expect, and instructions on the developer certificate of origin that we require.
-- Check out the [open issues](https://github.com/kubernetes/ingress-nginx).
-- Join our Kubernetes Slack channel for developer discussion : [#ingress-nginx-dev](https://kubernetes.slack.com/archives/C021E147ZA4).
-
 ## Changelog
 
 See [the list of releases](https://github.com/kubernetes/ingress-nginx/releases) to find out about feature changes.
@@ -45,19 +36,28 @@ For detailed changes on the `ingress-nginx` helm chart, please check the followi
 | v0.47.0               | 1.21, 1.20, 1.19       | 3.13.5         |  1.20.1       |
 | v0.46.0               | 1.21, 1.20, 1.19       | 3.13.2         |  1.19.6       |
 
-# Get Involved
+## Get Involved
 
-- **Contributing**: Pull requests are welcome!
-  - Read [`CONTRIBUTING.md`](CONTRIBUTING.md) and check out [help-wanted](https://github.com/kubernetes/ingress-nginx/labels/help%20wanted) issues.
-  - Submit github issues for any feature enhancements, bugs or documentation problems.
-- **Support**: Join to [Kubernetes Slack](http://slack.kubernetes.io/) in the [#ingress-nginx-users](https://kubernetes.slack.com/messages/CANQGM8BA/) channel to ask questions to get support from the maintainers and other users.
-  - The [github issues](https://github.com/kubernetes/ingress-nginx/issues) in the repository are **exclusively** for bug reports and feature requests.
-- **Discuss**: Tweet using the `#IngressNginx` hashtag.
+Thanks for taking the time to join our community and start contributing!
 
-## Issues
+- This project adheres to the [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md). By participating in this project, you agree to abide by its terms.
+
+- **Contributing**: Contributions of all kind are welcome!
+  
+  - Read [`CONTRIBUTING.md`](CONTRIBUTING.md) for information about setting up your environment, the workflow that we expect, and instructions on the developer certificate of origin that we require.
+
+  - Check out the [open issues](https://github.com/kubernetes/ingress-nginx), especially [help-wanted](https://github.com/kubernetes/ingress-nginx/labels/help%20wanted) ones.
+
+  - Join our Kubernetes Slack channel for developer discussion : [#ingress-nginx-dev](https://kubernetes.slack.com/archives/C021E147ZA4).
+  
+  - Submit github issues for any feature enhancements, bugs or documentation problems. Please make sure to read the [Issue Reporting Checklist](https://github.com/kubernetes/ingress-nginx/blob/main/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines **may be closed immediately**.
 
-Please make sure to read the [Issue Reporting Checklist](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines **may be closed immediately**.
+- **Support**: Join the the [#ingress-nginx-users](https://kubernetes.slack.com/messages/CANQGM8BA/) channel inside the [Kubernetes Slack](http://slack.kubernetes.io/) to ask questions or get support from the maintainers and other users.
+  
+  - The [github issues](https://github.com/kubernetes/ingress-nginx/issues) in the repository are **exclusively** for bug reports and feature requests.
+
+- **Discuss**: Tweet using the `#IngressNginx` hashtag.
 
 ## License
 
-[Apache License 2.0](https://github.com/kubernetes/ingress-nginx/blob/master/LICENSE)
+[Apache License 2.0](https://github.com/kubernetes/ingress-nginx/blob/main/LICENSE)
diff --git a/charts/ingress-nginx/OWNERS b/charts/ingress-nginx/OWNERS
index 0cece5f7c..392bc92f5 100644
--- a/charts/ingress-nginx/OWNERS
+++ b/charts/ingress-nginx/OWNERS
@@ -1,7 +1,10 @@
+# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
+
 approvers:
-  - ChiefAlexander
-  - cpanato
+- ingress-nginx-helm-maintainers
 
 reviewers:
-  - ChiefAlexander
-  - cpanato
+- ingress-nginx-helm-reviewers
+
+labels:
+- area/helm
\ No newline at end of file
diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md
index 53657e56f..d5a2c3ca8 100644
--- a/charts/ingress-nginx/README.md
+++ b/charts/ingress-nginx/README.md
@@ -159,7 +159,7 @@ controller:
       enabled: true
       annotations:
         # Create internal ELB
-        service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
+        service.beta.kubernetes.io/aws-load-balancer-internal: "true"
         # Any other annotation can be declared here.
 ```
 
diff --git a/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml b/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml
index 443e39d8b..d8948d634 100644
--- a/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml
+++ b/charts/ingress-nginx/ci/daemonset-internal-lb-values.yaml
@@ -7,4 +7,4 @@ controller:
     internal:
       enabled: true
       annotations:
-        service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
+        service.beta.kubernetes.io/aws-load-balancer-internal: "true"
diff --git a/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml b/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml
index 892f6de3f..c7f22d636 100644
--- a/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml
+++ b/charts/ingress-nginx/ci/deployment-internal-lb-values.yaml
@@ -6,4 +6,4 @@ controller:
     internal:
       enabled: true
       annotations:
-        service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
+        service.beta.kubernetes.io/aws-load-balancer-internal: "true"
diff --git a/deploy/grafana/kustomization.yaml b/deploy/grafana/kustomization.yaml
index 2069c1a7a..e2744818e 100644
--- a/deploy/grafana/kustomization.yaml
+++ b/deploy/grafana/kustomization.yaml
@@ -9,4 +9,3 @@ resources:
 - service.yaml
 images:
 - name: grafana/grafana
-  newTag: 6.1.6
diff --git a/deploy/prometheus/kustomization.yaml b/deploy/prometheus/kustomization.yaml
index 2d6e0a7e2..a55bd8d2c 100644
--- a/deploy/prometheus/kustomization.yaml
+++ b/deploy/prometheus/kustomization.yaml
@@ -12,7 +12,6 @@ resources:
 - service.yaml
 images:
 - name: prom/prometheus
-  newTag: v2.3.2
 configMapGenerator:
 - name: prometheus-configuration
   files:
diff --git a/docs/OWNERS b/docs/OWNERS
new file mode 100644
index 000000000..1d3805a73
--- /dev/null
+++ b/docs/OWNERS
@@ -0,0 +1,4 @@
+# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
+
+labels:
+- area/docs
\ No newline at end of file
diff --git a/docs/examples/grpc/README.md b/docs/examples/grpc/README.md
index 60e696bfd..8835b5110 100644
--- a/docs/examples/grpc/README.md
+++ b/docs/examples/grpc/README.md
@@ -1,93 +1,152 @@
 # gRPC
 
-This example demonstrates how to route traffic to a gRPC service through the
-nginx controller.
+This example demonstrates how to route traffic to a gRPC service through the nginx controller.
 
 ## Prerequisites
 
 1. You have a kubernetes cluster running.
-2. You have a domain name such as `example.com` that is configured to route
-   traffic to the ingress controller.  Replace references to
-   `fortune-teller.stack.build` (the domain name used in this example) to your
-   own domain name (you're also responsible for provisioning an SSL certificate
-   for the ingress).
-3. You have the nginx-ingress controller installed in typical fashion (must be
-   at least
-   [quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0](https://quay.io/kubernetes-ingress-controller/nginx-ingress-controller)
-   for grpc support.
-4. You have a backend application running a gRPC server and listening for TCP
-   traffic.  If you prefer, you can use the
-   [fortune-teller](https://github.com/kubernetes/ingress-nginx/tree/master/images/grpc-fortune-teller)
-   application provided here as an example.
-
-### Step 1: kubernetes `Deployment`
-
-```sh
-$ kubectl create -f app.yaml
-```
-
-This is a standard kubernetes deployment object.  It is running a grpc service
-listening on port `50051`.
-
-The sample application
-[fortune-teller-app](https://github.com/kubernetes/ingress-nginx/tree/master/images/grpc-fortune-teller)
-is a grpc server implemented in go. Here's the stripped-down implementation:
-
-```go
-func main() {
-	grpcServer := grpc.NewServer()
-	fortune.RegisterFortuneTellerServer(grpcServer, &FortuneTeller{})
-	lis, _ := net.Listen("tcp", ":50051")
-	grpcServer.Serve(lis)
-}
-```
-
-The takeaway is that we are not doing any TLS configuration on the server (as we
-are terminating TLS at the ingress level, grpc traffic will travel unencrypted
-inside the cluster and arrive "insecure").
-
-For your own application you may or may not want to do this.  If you prefer to
-forward encrypted traffic to your POD and terminate TLS at the gRPC server
-itself, add the ingress annotation `nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"`.
-
-### Step 2: the kubernetes `Service`
-
-```sh
-$ kubectl create -f svc.yaml
-```
-
-Here we have a typical service. Nothing special, just routing traffic to the
-backend application on port `50051`.
-
-### Step 3: the kubernetes `Ingress`
-
-```sh
-$ kubectl create -f ingress.yaml
-```
-
-A few things to note:
-
-1. We've tagged the ingress with the annotation
-   `nginx.ingress.kubernetes.io/backend-protocol: "GRPC"`.  This is the magic
-   ingredient that sets up the appropriate nginx configuration to route http/2
-   traffic to our service.
-1. We're terminating TLS at the ingress and have configured an SSL certificate
-   `fortune-teller.stack.build`.  The ingress matches traffic arriving as
-   `https://fortune-teller.stack.build:443` and routes unencrypted messages to
-   our kubernetes service.
+2. You have a domain name such as `example.com` that is configured to route traffic to the ingress controller.
+3. You have the nginx-ingress controller installed as per docs, with gRPC support.
+4. You have a backend application running a gRPC server and listening for TCP traffic.  If you want, you can use <https://github.com/grpc/grpc-go/blob/91e0aeb192456225adf27966d04ada4cf8599915/examples/features/reflection/server/main.go> as an example.
+5. You're also responsible for provisioning an SSL certificate for the ingress. So you need to have a valid SSL certificate, deployed as a Kubernetes secret of type tls, in the same namespace as the gRPC application.
+
+### Step 1: Create a Kubernetes `Deployment` for gRPC app
+
+- Make sure your gRPC application pod is running and listening for connections. For example you can try a kubectl command like this below:
+  ```
+  $ kubectl get po -A -o wide | grep go-grpc-greeter-server
+  ```
+- If you have a gRPC app deployed in your cluster, then skip further notes in this Step 1, and continue from Step 2 below. 
+
+- As an example gRPC application, we can use this app <https://github.com/grpc/grpc-go/blob/91e0aeb192456225adf27966d04ada4cf8599915/examples/features/reflection/server/main.go> .
+
+- To create a container image for this app, you can use [this Dockerfile](../../../images/go-grpc-greeter-server/rootfs/Dockerfile). 
+
+- If you use the Dockerfile mentioned above, to create a image, then given below is an example of a Kubernetes manifest, to create a deployment resource, that uses that image. If needed, then edit this manifest to suit your needs. Assuming the name of this yaml file is  `deployment.go-grpc-greeter-server.yaml` ;
+
+  ```
+  cat <<EOF | kubectl apply -f -
+  apiVersion: apps/v1
+  kind: Deployment
+  metadata:
+    labels:
+      app: go-grpc-greeter-server
+    name: go-grpc-greeter-server
+  spec:
+    replicas: 1
+    selector:
+      matchLabels:
+        app: go-grpc-greeter-server
+    template:
+      metadata:
+        labels:
+          app: go-grpc-greeter-server
+      spec:
+        containers:
+        - image: <reponame>/go-grpc-greeter-server   # Edit this for your reponame
+          resources:
+            limits:
+              cpu: 100m
+              memory: 100Mi
+            requests:
+              cpu: 50m
+              memory: 50Mi
+          name: go-grpc-greeter-server
+          ports:
+          - containerPort: 50051
+  EOF
+  ```
+
+### Step 2: Create the Kubernetes `Service` for the gRPC app
+
+- You can use the following example manifest to create a service of type ClusterIP. Edit the name/namespace/label/port to match your deployment/pod ;
+  ```
+  cat <<EOF | kubectl apply -f -
+  apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: go-grpc-greeter-server
+    name: go-grpc-greeter-server
+  spec:
+    ports:
+    - port: 80
+      protocol: TCP
+      targetPort: 50051
+    selector:
+      app: go-grpc-greeter-server
+    type: ClusterIP
+  EOF
+  ```
+- You can save the above example manifest to a file with name `service.go-grpc-greeter-server.yaml` and edit it to match your deployment/pod, if required. You can create the service resource with a kubectl command like this ;
+
+  ```
+  $ kubectl create -f service.go-grpc-greeter-server.yaml
+  ```
+
+### Step 3: Create the Kubernetes `Ingress` resource for the gRPC app
+
+- Use the following example manifest of a ingress resource to create a ingress for your grpc app. If required, edit it to match your app's details like name, namespace, service, secret etc. Make sure you have the required SSL-Certificate, existing in your Kubernetes cluster, in the same namespace where the gRPC app is. The certificate must be available as a kubernetes secret resource, of type "kubernete.io/tls" https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets. This is because we are terminating TLS on the ingress;
+
+  ```
+  cat <<EOF | kubectl apply -f -
+  apiVersion: networking.k8s.io/v1
+  kind: Ingress
+  metadata:
+    annotations:
+      kubernetes.io/ingress.class: "nginx"
+      nginx.ingress.kubernetes.io/ssl-redirect: "true"
+      nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
+    name: fortune-ingress
+    namespace: default
+  spec:
+    rules:
+    - host: grpctest.dev.mydomain.com
+      http:
+        paths:
+        - path: /
+          pathType: Prefix
+          backend:
+            service:
+              name: go-grpc-greeter-server
+              port:
+                number: 80
+    tls:
+    # This secret must exist beforehand
+    # The cert must also contain the subj-name grpctest.dev.mydomain.com
+    # https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/PREREQUISITES.md#tls-certificates
+    - secretName: wildcard.dev.mydomain.com
+      hosts:
+        - grpctest.dev.mydomain.com
+  EOF
+  ```
+
+- If you save the above example manifest as a file named `ingress.go-grpc-greeter-server.yaml` and edit it to match your deployment and service, you can create the ingress like this ;
+
+  ```
+  $ kubectl create -f ingress.go-grpc-greeter-server.yaml
+  ```
+
+- The takeaway is that we are not doing any TLS configuration on the server (as we are terminating TLS at the ingress level, gRPC traffic will travel unencrypted inside the cluster and arrive "insecure").
+
+- For your own application you may or may not want to do this.  If you prefer to forward encrypted traffic to your POD and terminate TLS at the gRPC server itself, add the ingress annotation `nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"`.
+
+- A few more things to note:
+
+  - We've tagged the ingress with the annotation `nginx.ingress.kubernetes.io/backend-protocol: "GRPC"`.  This is the magic ingredient that sets up the appropriate nginx configuration to route http/2 traffic to our service.
+
+  - We're terminating TLS at the ingress and have configured an SSL certificate `wildcard.dev.mydomain.com`.  The ingress matches traffic arriving as `https://grpctest.dev.mydomain.com:443` and routes unencrypted messages to the backend Kubernetes service.
 
 ### Step 4: test the connection
 
-Once we've applied our configuration to kubernetes, it's time to test that we
-can actually talk to the backend.  To do this, we'll use the
-[grpcurl](https://github.com/fullstorydev/grpcurl) utility:
+- Once we've applied our configuration to Kubernetes, it's time to test that we can actually talk to the backend.  To do this, we'll use the [grpcurl](https://github.com/fullstorydev/grpcurl) utility:
 
-```sh
-$ grpcurl fortune-teller.stack.build:443 build.stack.fortune.FortuneTeller/Predict
-{
-  "message": "Let us endeavor so to live that when we come to die even the undertaker will be sorry.\n\t\t-- Mark Twain, \"Pudd'nhead Wilson's Calendar\""
-}
-```
+  ```
+  $ grpcurl grpctest.dev.mydomain.com:443 helloworld.Greeter/SayHello
+  {
+    "message": "
+  }
+  ```
 
 ### Debugging Hints
 
diff --git a/docs/examples/grpc/app.yaml b/docs/examples/grpc/app.yaml
deleted file mode 100644
index acc4060d0..000000000
--- a/docs/examples/grpc/app.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: fortune-teller-app
-  labels:
-    k8s-app: fortune-teller-app
-  namespace: default
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      k8s-app: fortune-teller-app
-  template:
-    metadata:
-      labels:
-        k8s-app: fortune-teller-app
-    spec:
-      containers:
-      - name: fortune-teller-app
-        image: quay.io/kubernetes-ingress-controller/grpc-fortune-teller:0.1
-        ports:
-        - containerPort: 50051
-          name: grpc
diff --git a/docs/examples/grpc/cert.yaml b/docs/examples/grpc/cert.yaml
deleted file mode 100644
index 562c30313..000000000
--- a/docs/examples/grpc/cert.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-apiVersion: "stable.k8s.psg.io/v1"
-kind: "Certificate"
-metadata:
-  name: fortune-teller.stack.build
-  namespace: default
-spec:
-  domain: "fortune-teller.stack.build"
diff --git a/docs/examples/grpc/ingress.yaml b/docs/examples/grpc/ingress.yaml
deleted file mode 100644
index 1d76476d1..000000000
--- a/docs/examples/grpc/ingress.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-apiVersion: networking.k8s.io/v1beta1
-kind: Ingress
-metadata:
-  annotations:
-    kubernetes.io/ingress.class: "nginx"
-    nginx.ingress.kubernetes.io/ssl-redirect: "true"
-    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
-  name: fortune-ingress
-  namespace: default
-spec:
-  rules:
-  - host: fortune-teller.stack.build
-    http:
-      paths:
-      - backend:
-          serviceName: fortune-teller-service
-          servicePort: grpc
-  tls:
-  # This secret must exist beforehand
-  # The cert must also contain the subj-name fortune-teller.stack.build
-  # https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/PREREQUISITES.md#tls-certificates
-  - secretName: fortune-teller.stack.build
-    hosts:
-      - fortune-teller.stack.build
diff --git a/docs/examples/grpc/svc.yaml b/docs/examples/grpc/svc.yaml
deleted file mode 100644
index 7bfa789fd..000000000
--- a/docs/examples/grpc/svc.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: fortune-teller-service
-  namespace: default
-spec:
-  selector:
-    k8s-app: fortune-teller-app
-  ports:
-  - port: 50051
-    targetPort: 50051
-    name: grpc
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 1707aa0e2..a8cf212b1 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -173,68 +173,47 @@ Verify with the following commands:
 
 ```console
 # start a container that contains curl
-$ kubectl run test --image=tutum/curl -- sleep 10000
-
-# check that container is running
-$ kubectl get pods
-NAME                   READY     STATUS    RESTARTS   AGE
-test-701078429-s5kca   1/1       Running   0          16s
+$ kubectl run -it --rm test --image=curlimages/curl --restart=Never -- /bin/sh
 
 # check if secret exists
-$ kubectl exec test-701078429-s5kca -- ls /var/run/secrets/kubernetes.io/serviceaccount/
-ca.crt
-namespace
-token
-
-# get service IP of master
-$ kubectl get services
-NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
-kubernetes   10.0.0.1     <none>        443/TCP   1d
+/ $ ls /var/run/secrets/kubernetes.io/serviceaccount/
+ca.crt     namespace  token
+/ $
 
 # check base connectivity from cluster inside
-$ kubectl exec test-701078429-s5kca -- curl -k https://10.0.0.1
-Unauthorized
+/ $ curl -k https://kubernetes.default.svc.cluster.local
+{
+  "kind": "Status",
+  "apiVersion": "v1",
+  "metadata": {
+
+  },
+  "status": "Failure",
+  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
+  "reason": "Forbidden",
+  "details": {
+
+  },
+  "code": 403
+}/ $
 
 # connect using tokens
-$ TOKEN_VALUE=$(kubectl exec test-701078429-s5kca -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
-$ echo $TOKEN_VALUE
-eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3Mi....9A
-$ kubectl exec test-701078429-s5kca -- curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H  "Authorization: Bearer $TOKEN_VALUE" https://10.0.0.1
+}/ $ curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H  "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc.cluster.local
+&& echo
 {
   "paths": [
     "/api",
     "/api/v1",
     "/apis",
-    "/apis/apps",
-    "/apis/apps/v1alpha1",
-    "/apis/authentication.k8s.io",
-    "/apis/authentication.k8s.io/v1beta1",
-    "/apis/authorization.k8s.io",
-    "/apis/authorization.k8s.io/v1beta1",
-    "/apis/autoscaling",
-    "/apis/autoscaling/v1",
-    "/apis/batch",
-    "/apis/batch/v1",
-    "/apis/batch/v2alpha1",
-    "/apis/certificates.k8s.io",
-    "/apis/certificates.k8s.io/v1alpha1",
-    "/apis/networking",
-    "/apis/networking/v1beta1",
-    "/apis/policy",
-    "/apis/policy/v1alpha1",
-    "/apis/rbac.authorization.k8s.io",
-    "/apis/rbac.authorization.k8s.io/v1alpha1",
-    "/apis/storage.k8s.io",
-    "/apis/storage.k8s.io/v1beta1",
-    "/healthz",
-    "/healthz/ping",
-    "/logs",
-    "/metrics",
-    "/swaggerapi/",
-    "/ui/",
+    "/apis/",
+    ... TRUNCATED
+    "/readyz/shutdown",
     "/version"
   ]
 }
+/ $
+
+# when you type `exit` or `^D` the test pod will be deleted.
 ```
 
 If it is not working, there are two possible reasons:
diff --git a/docs/user-guide/monitoring.md b/docs/user-guide/monitoring.md
index 4f6376a3b..6471f997e 100644
--- a/docs/user-guide/monitoring.md
+++ b/docs/user-guide/monitoring.md
@@ -7,79 +7,137 @@ This tutorial will show you how to install [Prometheus](https://prometheus.io/)
 
 ## Before You Begin
 
-The NGINX Ingress controller should already be deployed according to the deployment instructions [here](../deploy/index.md).
+- The NGINX Ingress controller should already be deployed according to the deployment instructions [here](../deploy/index.md).
+
+- The controller should be configured for exporting metrics. This requires 3 configurations to the controller. These configurations are :
+  1. controller.metrics.enabled=true
+  2. controller.podAnnotations."prometheus.io/scrape"="true"
+  3. controller.podAnnotations."prometheus.io/port"="10254"
+
+  - The easiest way to configure the controller for metrics is via helm upgrade. Assuming you have installed the ingress-nginx controller as a helm release named ingresscontroller0, then you can simply type the command show below :
+  ```
+  helm upgrade ingresscontroller0 ingress-nginx/ingress-nginx \
+  --namespace ingress-nginx \
+  --set controller.metrics.enabled=true \
+  --set-string controller.podAnnotations."prometheus\.io/scrape"="true" \
+  --set-string controller.podAnnotations."prometheus\.io/port"="10254"
+  ```
+  - You can validate that the controller is configured for metrics by looking at the values of the installed release, like this ;
+  ```
+  helm get values ingress-controller --namespace ingress-nginx
+  ```
+  - You should be able to see the values shown below ;
+  ```
+  ..
+  controller:
+    metrics:
+      enabled: true
+      service:
+        annotations:
+          prometheus.io/port: "10254"
+          prometheus.io/scrape: "true" 
+  ..
+  ```
 
-Note that the kustomize bases used in this tutorial are stored in the [deploy](https://github.com/kubernetes/ingress-nginx/tree/master/deploy) folder of the GitHub repository [kubernetes/ingress-nginx](https://github.com/kubernetes/ingress-nginx).
 
 ## Deploy and configure Prometheus Server
 
-The Prometheus server must be configured so that it can discover endpoints of services. If a Prometheus server is already running in the cluster and if it is configured in a way that it can find the ingress controller pods, no extra configuration is needed.
+Note that the kustomize bases used in this tutorial are stored in the [deploy](https://github.com/kubernetes/ingress-nginx/tree/master/deploy) folder of the GitHub repository [kubernetes/ingress-nginx](https://github.com/kubernetes/ingress-nginx).
+
+- The Prometheus server must be configured so that it can discover endpoints of services. If a Prometheus server is already running in the cluster and if it is configured in a way that it can find the ingress controller pods, no extra configuration is needed.
 
-If there is no existing Prometheus server running, the rest of this tutorial will guide you through the steps needed to deploy a properly configured Prometheus server.
+- If there is no existing Prometheus server running, the rest of this tutorial will guide you through the steps needed to deploy a properly configured Prometheus server.
 
-Running the following command deploys prometheus in Kubernetes:
+- Running the following command deploys prometheus in Kubernetes:
 
-```console
-kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/prometheus/
-```
+  ```
+  kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/prometheus/
+  ```
 
 ### Prometheus Dashboard
 
-Open Prometheus dashboard in a web browser:
+- Open Prometheus dashboard in a web browser:
 
-```console
-kubectl get svc -n ingress-nginx
-NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
-default-http-backend   ClusterIP   10.103.59.201   <none>        80/TCP                                       3d
-ingress-nginx          NodePort    10.97.44.72     <none>        80:30100/TCP,443:30154/TCP,10254:32049/TCP   5h
-prometheus-server      NodePort    10.98.233.86    <none>        9090:32630/TCP                               1m
-```
+  ```console
+  kubectl get svc -n ingress-nginx
+  NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
+  default-http-backend   ClusterIP   10.103.59.201   <none>        80/TCP                                       3d
+  ingress-nginx          NodePort    10.97.44.72     <none>        80:30100/TCP,443:30154/TCP,10254:32049/TCP   5h
+  prometheus-server      NodePort    10.98.233.86    <none>        9090:32630/TCP                               1m
+  ```
 
-Obtain the IP address of the nodes in the running cluster:
+  - Obtain the IP address of the nodes in the running cluster:
 
-```console
-kubectl get nodes -o wide
-```
+  ```console
+  kubectl get nodes -o wide
+  ```
 
-In some cases where the node only have internal IP addresses we need to execute:
+  - In some cases where the node only have internal IP addresses we need to execute:
 
-```console
-kubectl get nodes --selector=kubernetes.io/role!=master -o jsonpath={.items[*].status.addresses[?\(@.type==\"InternalIP\"\)].address}
-10.192.0.2 10.192.0.3 10.192.0.4
-```
+  ```
+  kubectl get nodes --selector=kubernetes.io/role!=master -o jsonpath={.items[*].status.addresses[?\(@.type==\"InternalIP\"\)].address}
+  10.192.0.2 10.192.0.3 10.192.0.4
+  ```
 
-Open your browser and visit the following URL: _http://{node IP address}:{prometheus-svc-nodeport}_ to load the Prometheus Dashboard.
+  - Open your browser and visit the following URL: _http://{node IP address}:{prometheus-svc-nodeport}_ to load the Prometheus Dashboard.
 
-According to the above example, this URL will be http://10.192.0.3:32630
+  - According to the above example, this URL will be http://10.192.0.3:32630
 
-![Dashboard](../images/prometheus-dashboard.png)
+  ![Prometheus Dashboard](../images/prometheus-dashboard.png)
 
 ### Grafana
 
-```console
-kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/grafana/
-```
+  - Install grafana using the below command
+  ```
+  kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/grafana/
+  ```
+  - Look at the services
+  ```
+  kubectl get svc -n ingress-nginx
+  NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
+  default-http-backend   ClusterIP   10.103.59.201   <none>        80/TCP                                       3d
+  ingress-nginx          NodePort    10.97.44.72     <none>        80:30100/TCP,443:30154/TCP,10254:32049/TCP   5h
+  prometheus-server      NodePort    10.98.233.86    <none>        9090:32630/TCP                               10m
+  grafana                NodePort    10.98.233.87    <none>        3000:31086/TCP                               10m
+  ```
+
+  - Open your browser and visit the following URL: _http://{node IP address}:{grafana-svc-nodeport}_ to load the Grafana Dashboard.
+According to the above example, this URL will be http://10.192.0.3:31086
 
-```console
-kubectl get svc -n ingress-nginx
-NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
-default-http-backend   ClusterIP   10.103.59.201   <none>        80/TCP                                       3d
-ingress-nginx          NodePort    10.97.44.72     <none>        80:30100/TCP,443:30154/TCP,10254:32049/TCP   5h
-prometheus-server      NodePort    10.98.233.86    <none>        9090:32630/TCP                               10m
-grafana                NodePort    10.98.233.87    <none>        3000:31086/TCP                               10m
-```
+  The username and password is `admin`
 
-Open your browser and visit the following URL: _http://{node IP address}:{grafana-svc-nodeport}_ to load the Grafana Dashboard.
-According to the above example, this URL will be http://10.192.0.3:31086
+  - After the login you can import the Grafana dashboard from [official dashboards](https://github.com/kubernetes/ingress-nginx/tree/master/deploy/grafana/dashboards), by following steps given below :
+
+    - Navigate to lefthand panel of grafana
+    - Hover on the gearwheel icon for Configuration and click "Data Sources"
+    - Click "Add data source"
+    - Select "Prometheus"
+    - Enter the details (note: I used http://CLUSTER_IP_PROMETHEUS_SVC:9090)
+    - Left menu (hover over +) -> Dashboard
+    - Click "Import"
+    - Enter the copy pasted json from https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/grafana/dashboards/nginx.json
+    - Click Import JSON
+    - Select the Prometheus data source
+    - Click "Import"
 
-The username and password is `admin`
 
-After the login you can import the Grafana dashboard from [official dashboards](https://github.com/kubernetes/ingress-nginx/tree/master/deploy/grafana/dashboards)
 
-![Dashboard](../images/grafana.png)
+  ![Grafana Dashboard](../images/grafana.png)
 
 ## Caveats
 
 ### Wildcard ingresses
 
-By default request metrics are labeled with the hostname. When you have a wildcard domain ingress, then there will be no metrics for that ingress (to prevent the metrics from exploding in cardinality). To get metrics in this case you need to run the ingress controller with `--metrics-per-host=false` (you will lose labeling by hostname, but still have labeling by ingress).
+  - By default request metrics are labeled with the hostname. When you have a wildcard domain ingress, then there will be no metrics for that ingress (to prevent the metrics from exploding in cardinality). To get metrics in this case you need to run the ingress controller with `--metrics-per-host=false` (you will lose labeling by hostname, but still have labeling by ingress).
+
+## Grafana dashboard using ingress resource
+  - If you want to expose the dashboard for grafana using a ingress resource, then you can : 
+    - change the service type of the prometheus-server service and the grafana service to "ClusterIP" like this :
+    ```
+    kubectl -n ingress-nginx edit svc grafana
+    ```
+    - This will open the currently deployed service grafana in the default editor configured in your shell (vi/nvim/nano/other)
+    - scroll down to line 34 that looks like "type: NodePort"
+    - change it to look like "type: ClusterIP". Save and exit.
+    - create a ingress reource with backend as "grafana" and port as "3000"
+  - Similarly, you can edit the service "prometheus-server" and add a ingress resource.
diff --git a/images/OWNERS b/images/OWNERS
index b135a937c..00f162ebd 100644
--- a/images/OWNERS
+++ b/images/OWNERS
@@ -1,7 +1,9 @@
+# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
+
 approvers:
-- aledbf
-- ElvinEfendi
+- ingress-nginx-admins
+- ingress-nginx-maintainers
 
 reviewers:
-- ElvinEfendi
-- aledbf
+- ingress-nginx-admins
+- ingress-nginx-maintainers
diff --git a/images/go-grpc-greeter-server/Makefile b/images/go-grpc-greeter-server/Makefile
new file mode 100644
index 000000000..523b83bfb
--- /dev/null
+++ b/images/go-grpc-greeter-server/Makefile
@@ -0,0 +1,55 @@
+# Copyright 2021 The Kubernetes Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# set default shell
+SHELL=/bin/bash -o pipefail -o errexit
+
+DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
+INIT_BUILDX=$(DIR)/../../hack/init-buildx.sh
+
+TAG ?=v$(shell date +%m%d%Y)-$(shell git rev-parse --short HEAD)
+REGISTRY ?= local
+
+IMAGE = $(REGISTRY)/go-grpc-greeter-server
+
+# required to enable buildx
+export DOCKER_CLI_EXPERIMENTAL=enabled
+
+# build with buildx
+PLATFORMS?=linux/amd64,linux/arm,linux/arm64,linux/s390x
+OUTPUT=
+PROGRESS=plain
+
+build: ensure-buildx
+	docker buildx build \
+		--platform=${PLATFORMS} $(OUTPUT) \
+		--progress=$(PROGRESS) \
+		--pull \
+		-t $(IMAGE):$(TAG) rootfs
+
+# push the cross built image
+push: OUTPUT=--push
+push: build
+
+# enable buildx
+ensure-buildx:
+# this is required for cloudbuild
+ifeq ("$(wildcard $(INIT_BUILDX))","")
+	@curl -sSL https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/hack/init-buildx.sh | bash
+else
+	@exec $(INIT_BUILDX)
+endif
+	@echo "done"
+
+.PHONY: build push ensure-buildx
diff --git a/images/go-grpc-greeter-server/cloudbuild.yaml b/images/go-grpc-greeter-server/cloudbuild.yaml
new file mode 100644
index 000000000..14c64db31
--- /dev/null
+++ b/images/go-grpc-greeter-server/cloudbuild.yaml
@@ -0,0 +1,24 @@
+timeout: 1200s
+options:
+  substitution_option: ALLOW_LOOSE
+  # job builds a multi-arch docker image for amd64,arm,arm64 and s390x.
+  machineType: N1_HIGHCPU_8
+steps:
+  - name: gcr.io/k8s-testimages/gcb-docker-gcloud:v20210622-762366a
+    entrypoint: bash
+    env:
+      - DOCKER_CLI_EXPERIMENTAL=enabled
+      - TAG=$_GIT_TAG
+      - BASE_REF=$_PULL_BASE_REF
+      - REGISTRY=gcr.io/k8s-staging-ingress-nginx
+      # default cloudbuild has HOME=/builder/home and docker buildx is in /root/.docker/cli-plugins/docker-buildx
+      # set the home to /root explicitly to if using docker buildx
+      - HOME=/root
+    args:
+    - -c
+    - |
+      gcloud auth configure-docker \
+      && make push
+substitutions:
+  _GIT_TAG: "12345"
+  _PULL_BASE_REF: "master"
diff --git a/images/go-grpc-greeter-server/rootfs/Dockerfile b/images/go-grpc-greeter-server/rootfs/Dockerfile
new file mode 100644
index 000000000..a528c6cb6
--- /dev/null
+++ b/images/go-grpc-greeter-server/rootfs/Dockerfile
@@ -0,0 +1,16 @@
+FROM golang:buster as build
+
+WORKDIR /go/src/greeter-server
+
+RUN curl -o main.go https://github.com/grpc/grpc-go/blob/91e0aeb192456225adf27966d04ada4cf8599915/examples/features/reflection/server/main.go && \
+  go mod init greeter-server && \
+  go mod tidy && \
+  go build -o /greeter-server main.go
+
+FROM gcr.io/distroless/base-debian10
+
+COPY --from=build /greeter-server /
+
+EXPOSE 50051
+
+CMD ["/greeter-server"]
diff --git a/images/grpc-fortune-teller/.gitignore b/images/grpc-fortune-teller/.gitignore
deleted file mode 100644
index ac51a054d..000000000
--- a/images/grpc-fortune-teller/.gitignore
+++ /dev/null
@@ -1,1 +0,0 @@
-bazel-*
diff --git a/images/grpc-fortune-teller/BUILD.bazel b/images/grpc-fortune-teller/BUILD.bazel
deleted file mode 100644
index b000f8347..000000000
--- a/images/grpc-fortune-teller/BUILD.bazel
+++ /dev/null
@@ -1,15 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "gazelle", "go_prefix")
-
-gazelle(
-    name = "gazelle",
-    args = [
-        "-build_file_name",
-        "BUILD,BUILD.bazel",
-    ],
-    command = "fix",
-    prefix = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller",
-)
-
-go_prefix(
-    prefix = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller",
-)
diff --git a/images/grpc-fortune-teller/Gopkg.lock b/images/grpc-fortune-teller/Gopkg.lock
deleted file mode 100644
index e25ff02dd..000000000
--- a/images/grpc-fortune-teller/Gopkg.lock
+++ /dev/null
@@ -1,104 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  name = "github.com/golang/protobuf"
-  packages = [
-    "proto",
-    "protoc-gen-go/descriptor",
-    "ptypes",
-    "ptypes/any",
-    "ptypes/duration",
-    "ptypes/timestamp"
-  ]
-  revision = "925541529c1fa6821df4e44ce2723319eb2be768"
-  version = "v1.0.0"
-
-[[projects]]
-  name = "github.com/vromero/gofortune"
-  packages = [
-    "lib",
-    "lib/fortune"
-  ]
-  revision = "8a3c485287c0d3d3e4f8f0d9e0058f6cdd29740d"
-  version = "v0.0.1"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/net"
-  packages = [
-    "context",
-    "http2",
-    "http2/hpack",
-    "idna",
-    "internal/timeseries",
-    "lex/httplex",
-    "trace"
-  ]
-  revision = "b3c676e531a6dc479fa1b35ac961c13f5e2b4d2e"
-
-[[projects]]
-  name = "golang.org/x/text"
-  packages = [
-    "collate",
-    "collate/build",
-    "internal/colltab",
-    "internal/gen",
-    "internal/tag",
-    "internal/triegen",
-    "internal/ucd",
-    "language",
-    "secure/bidirule",
-    "transform",
-    "unicode/bidi",
-    "unicode/cldr",
-    "unicode/norm",
-    "unicode/rangetable"
-  ]
-  revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
-  version = "v0.3.0"
-
-[[projects]]
-  branch = "master"
-  name = "google.golang.org/genproto"
-  packages = ["googleapis/rpc/status"]
-  revision = "35de2414665fc36f56b72d982c5af480d86de5ab"
-
-[[projects]]
-  name = "google.golang.org/grpc"
-  packages = [
-    ".",
-    "balancer",
-    "balancer/base",
-    "balancer/roundrobin",
-    "codes",
-    "connectivity",
-    "credentials",
-    "encoding",
-    "encoding/proto",
-    "grpclb/grpc_lb_v1/messages",
-    "grpclog",
-    "internal",
-    "keepalive",
-    "metadata",
-    "naming",
-    "peer",
-    "reflection",
-    "reflection/grpc_reflection_v1alpha",
-    "resolver",
-    "resolver/dns",
-    "resolver/passthrough",
-    "stats",
-    "status",
-    "tap",
-    "transport"
-  ]
-  revision = "d89cded64628466c4ab532d1f0ba5c220459ebe8"
-  version = "v1.11.2"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  inputs-digest = "fcd36504ba120cfbbe161eac2ddd439c884fcef61ce318b5c0a544d27bc47043"
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/images/grpc-fortune-teller/README.md b/images/grpc-fortune-teller/README.md
deleted file mode 100644
index 5cc755ef6..000000000
--- a/images/grpc-fortune-teller/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-
-# grpc-fortune-teller
-
-This is the grpc server application for the nginx-ingress grpc example.  Bazel
-0.12 is used for the building and container management.
-
-## Build
-
-Builds a statically compiled go binary cross-compiled for linux:
-
-```
-$ bazel build //app:fortune 
-Target //app:fortune up-to-date:
-  bazel-bin/app/linux_amd64_static_pure_stripped/fortune
-```
-
-> To build for your host system, comment out the `goos` and `goarch` attributes
-> in the `go_binary` rule.
-
-## Run
-
-Builds a minimal docker image that wraps the go_binary, loads it into your local
-docker image repository, and runs it:
-
-```sh
-$ bazel run //app:image
-Loaded image ID: sha256:aa597c897c873116fcbfccafecf5ab0f6f4178a05e4a00c8e79de91ac0d2e9e7
-Tagging aa597c897c873116fcbfccafecf5ab0f6f4178a05e4a00c8e79de91ac0d2e9e7 as bazel/app:image
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/fortunes.dat
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/literature
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/literature.dat
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/riddles
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/riddles.dat
-2018/05/01 02:13:43 Restored /tmp/fortune-teller/usr/share/games/fortunes/fortunes
-2018/05/01 02:13:43 Assets restored to /tmp/fortune-teller
-2018/05/01 02:13:43 Listening for gRPC requests at 50051
-```
-
-Or run it via docker:
-
-```sh
-$ docker run bazel/app:image
-```
-
-Build image and push to the container registry specified in the `container_push`
-rule:
-
-```sh
-$ bazel run //app:push
-```
-
-## Invoke
-
-```sh
-$ grpcurl -plaintext localhost:50051 build.stack.fortune.FortuneTeller/Predict
-{
-  "message": "Whenever the literary German dives into a sentence, that is the last\nyou are going to see of him until he emerges on the other side of his\nAtlantic with his verb in his mouth.\n\t\t-- Mark Twain \"A Connecticut Yankee in King Arthur's Court\""
-}
-```
diff --git a/images/grpc-fortune-teller/WORKSPACE b/images/grpc-fortune-teller/WORKSPACE
deleted file mode 100644
index a6960d054..000000000
--- a/images/grpc-fortune-teller/WORKSPACE
+++ /dev/null
@@ -1,62 +0,0 @@
-workspace(name = "com_github_kubernetes_ingress_nginx_images_grpc_fortune_teller")
-
-#####################################################################
-# RULES_GO
-#####################################################################
-
-git_repository(
-    name = "io_bazel_rules_go",
-    remote = "https://github.com/bazelbuild/rules_go.git",
-    commit = "161c91485b007c6bf51c0e81808cf4ee2ded299d",
-)
-
-http_archive(
-    name = "com_github_scele_rules_go_dep",
-    urls = ["https://github.com/scele/rules_go_dep/archive/49a5e4ca9f6a16c9b4c930a51ce3a537498bb4e1.tar.gz"],
-    strip_prefix = "rules_go_dep-49a5e4ca9f6a16c9b4c930a51ce3a537498bb4e1",
-    sha256 = "f170d3d6f55e216f1493f975cde6c489d7070da2a8a41fd4de9812d96f4fb38b",
-)
-
-load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
-load("@com_github_scele_rules_go_dep//dep:dep.bzl", "dep_import")
-
-go_register_toolchains(go_version = "1.10.1")
-
-go_rules_dependencies()
-
-dep_import(
-    name = "godeps",
-    prefix = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller",
-    gopkg_lock = "//:Gopkg.lock",
-)
-
-load("@godeps//:Gopkg.bzl", "go_deps")
-
-go_deps()
-
-#############################################################
-# RULES_DOCKER
-#############################################################
-
-RULES_DOCKER_VERSION = "553d5506bb7325185950f91533b967da8f5bc536"
-
-http_archive(
-    name = "io_bazel_rules_docker",
-    url = "https://github.com/bazelbuild/rules_docker/archive/%s.zip" % RULES_DOCKER_VERSION,
-    strip_prefix = "rules_docker-" + RULES_DOCKER_VERSION,
-    sha256 = "e0b3d966f2a5c0fe921b6294df7c823afa63b4c439f0a7f3b9da3ed6534bab83",
-)
-
-load(
-    "@io_bazel_rules_docker//container:container.bzl",
-    container_repositories = "repositories",
-)
-
-container_repositories()
-
-load(
-    "@io_bazel_rules_docker//go:image.bzl",
-    go_image_repositories = "repositories",
-)
-
-go_image_repositories()
diff --git a/images/grpc-fortune-teller/app/BUILD.bazel b/images/grpc-fortune-teller/app/BUILD.bazel
deleted file mode 100644
index 4fffd481e..000000000
--- a/images/grpc-fortune-teller/app/BUILD.bazel
+++ /dev/null
@@ -1,69 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_embed_data")
-load("@io_bazel_rules_docker//go:image.bzl", "go_image")
-load("@io_bazel_rules_docker//container:push.bzl", "container_push")
-
-# Concatenates the fortune databases to a single bundle.
-# May need to adjust paths for your system (built on ubuntu 16.04).
-# $ apt-get install fortune
-genrule(
-    name = "tar",
-    outs = ["fortune.tar"],
-    cmd = " && ".join([
-        "OUT=$$(pwd)/$@",
-        "tar -cvf $$OUT /usr/share/games/fortunes",
-    ]),
-)
-
-# Generates a .go source file with the tarball content in 
-# the fortuneFiles variable.
-go_embed_data(
-    name = "fortune_assets",
-    srcs = [
-        ":tar",
-    ],
-    package = "main",
-    unpack = True,
-    var = "fortuneFiles",
-)
-
-go_library(
-    name = "go_default_library",
-    srcs = [
-        "main.go",
-        ":fortune_assets",  # keep
-    ],
-    importpath = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/app",
-    visibility = ["//visibility:private"],
-    deps = [
-        "//proto/fortune:go_default_library",
-        "@com_github_vromero_gofortune//lib/fortune:go_default_library",
-        "@org_golang_google_grpc//:go_default_library",
-        "@org_golang_google_grpc//codes:go_default_library",
-        "@org_golang_google_grpc//reflection:go_default_library",
-    ],
-)
-
-go_binary(
-    name = "fortune",
-    embed = [":go_default_library"],
-    goarch = "amd64",
-    goos = "linux",
-    pure = "on",
-    static = "on",
-    visibility = ["//visibility:public"],
-)
-
-go_image(
-    name = "image",
-    binary = ":fortune",
-    visibility = ["//visibility:public"],
-)
-
-container_push(
-    name = "push",
-    format = "Docker",
-    image = ":image",
-    registry = "quay.io",
-    repository = "kubernetes-ingress-controller/grpc-fortune-teller",
-    tag = "0.1",
-)
diff --git a/images/grpc-fortune-teller/app/main.go b/images/grpc-fortune-teller/app/main.go
deleted file mode 100644
index d09799cbe..000000000
--- a/images/grpc-fortune-teller/app/main.go
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Copyright 2018 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"net"
-	"os"
-	"path"
-
-	proto "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/proto/fortune"
-	"github.com/vromero/gofortune/lib/fortune"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/reflection"
-)
-
-const (
-	grpcPort = 50051
-)
-
-func main() {
-
-	baseDir := "/tmp/fortune-teller"
-	mustMkdirAll(baseDir)
-
-	opts := []grpc.ServerOption{
-		grpc.MaxConcurrentStreams(200),
-	}
-
-	grpcServer := grpc.NewServer(opts...)
-
-	fortuneTeller := &FortuneTeller{
-		fs: createFortuneFilesystemNodeDescriptor(baseDir),
-	}
-	proto.RegisterFortuneTellerServer(grpcServer, fortuneTeller)
-
-	reflection.Register(grpcServer)
-
-	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort))
-	if err != nil {
-		log.Fatalf("Error while starting grpc server: %v\n", err)
-	}
-
-	log.Printf("Listening for gRPC requests at %d\n", grpcPort)
-	grpcServer.Serve(lis)
-}
-
-// FortuneTeller - struct that will implement the grpc service interface.
-type FortuneTeller struct {
-	fs *fortune.FileSystemNodeDescriptor
-}
-
-// Predict - implementation for the grpc unary request method.
-func (f *FortuneTeller) Predict(ctx context.Context, r *proto.PredictionRequest) (*proto.PredictionResponse, error) {
-	_, data, err := fortune.GetRandomFortune(*f.fs)
-	if err != nil {
-		return nil, grpc.Errorf(codes.Internal, "Unable to render fortune: %v", err)
-	}
-	return &proto.PredictionResponse{
-		Message: data,
-	}, nil
-}
-
-func createFortuneFilesystemNodeDescriptor(baseDir string) *fortune.FileSystemNodeDescriptor {
-
-	// Restore the packed fortune data
-	fortuneDir := path.Join(baseDir, "usr/share/games/fortunes")
-
-	mustRestore(baseDir, fortuneFiles, nil)
-
-	// init gofortune fs
-	fs, err := fortune.LoadPaths([]fortune.ProbabilityPath{
-		{Path: fortuneDir},
-	})
-	if err != nil {
-		log.Fatalf("Unable to load fortune paths: %v", err)
-	}
-
-	fortune.SetProbabilities(&fs, true) // consider all equal probabilities
-	return &fs
-}
-
-// mustRestore - Restore assets.
-func mustRestore(baseDir string, assets map[string][]byte, mappings map[string]string) {
-	// unpack variable is provided by the go_embed data and is a
-	// map[string][]byte such as {"/usr/share/games/fortune/literature.dat":
-	// bytes... }
-	for basename, bytes := range assets {
-		if mappings != nil {
-			replacement := mappings[basename]
-			if replacement != "" {
-				basename = replacement
-			}
-		}
-		filename := path.Join(baseDir, basename)
-		dirname := path.Dir(filename)
-		//log.Printf("file %s, dir %s, rel %d, abs %s, absdir: %s", file, dir, rel, abs, absdir)
-		if err := os.MkdirAll(dirname, os.ModePerm); err != nil {
-			log.Fatalf("Failed to create asset dir %s: %v", dirname, err)
-		}
-
-		if err := ioutil.WriteFile(filename, bytes, os.ModePerm); err != nil {
-			log.Fatalf("Failed to write asset %s: %v", filename, err)
-		}
-		log.Printf("Restored %s", filename)
-	}
-
-	log.Printf("Assets restored to %s", baseDir)
-}
-
-// mustMkdirAll - make all dirs and panic if fail
-func mustMkdirAll(dirs ...string) {
-	for _, dir := range dirs {
-		err := os.MkdirAll(dir, os.ModePerm)
-		if err != nil {
-			panic(fmt.Sprintf("Failed mkdir %s: %v", dir, err))
-		}
-	}
-}
diff --git a/images/grpc-fortune-teller/go.mod b/images/grpc-fortune-teller/go.mod
deleted file mode 100644
index e69de29bb..000000000
diff --git a/images/grpc-fortune-teller/proto/fortune/BUILD.bazel b/images/grpc-fortune-teller/proto/fortune/BUILD.bazel
deleted file mode 100644
index b3008b826..000000000
--- a/images/grpc-fortune-teller/proto/fortune/BUILD.bazel
+++ /dev/null
@@ -1,24 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
-
-go_library(
-    name = "go_default_library",
-    srcs = ["doc.go"],
-    embed = [":build_stack_fortune_go_proto"],  # keep
-    importpath = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/proto/fortune",
-    visibility = ["//visibility:public"],
-)
-
-proto_library(
-    name = "build_stack_fortune_proto",
-    srcs = ["fortune.proto"],
-    visibility = ["//visibility:public"],
-)
-
-go_proto_library(
-    name = "build_stack_fortune_go_proto",
-    compilers = ["@io_bazel_rules_go//proto:go_grpc"],
-    importpath = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/proto/fortune",
-    proto = ":build_stack_fortune_proto",
-    visibility = ["//visibility:public"],
-)
diff --git a/images/grpc-fortune-teller/proto/fortune/fortune.proto b/images/grpc-fortune-teller/proto/fortune/fortune.proto
deleted file mode 100644
index d71b4acb1..000000000
--- a/images/grpc-fortune-teller/proto/fortune/fortune.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-syntax = "proto3";
-
-package build.stack.fortune;
-
-message PredictionRequest {
-}
-
-message PredictionResponse {
-    string message = 1;
-}
-
-service FortuneTeller {
-    rpc Predict(PredictionRequest) returns (PredictionResponse);
-}
\ No newline at end of file
diff --git a/internal/ingress/annotations/backendprotocol/main.go b/internal/ingress/annotations/backendprotocol/main.go
index d6e7beb4c..65566d6e9 100644
--- a/internal/ingress/annotations/backendprotocol/main.go
+++ b/internal/ingress/annotations/backendprotocol/main.go
@@ -31,7 +31,7 @@ import (
 const HTTP = "HTTP"
 
 var (
-	validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`)
+	validProtocols = regexp.MustCompile(`^(AUTO_HTTP|HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`)
 )
 
 type backendProtocol struct {
diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go
index 3aa521c87..a14e2d50b 100644
--- a/internal/ingress/controller/template/template.go
+++ b/internal/ingress/controller/template/template.go
@@ -617,6 +617,8 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
 	proxyPass := "proxy_pass"
 
 	switch location.BackendProtocol {
+	case "AUTO_HTTP":
+		proto = "$scheme://"
 	case "HTTPS":
 		proto = "https://"
 	case "GRPC":
diff --git a/rootfs/etc/nginx/lua/OWNERS b/rootfs/etc/nginx/lua/OWNERS
new file mode 100644
index 000000000..79814fdba
--- /dev/null
+++ b/rootfs/etc/nginx/lua/OWNERS
@@ -0,0 +1,4 @@
+# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
+
+labels:
+- area/lua
\ No newline at end of file


Test patch:
diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go
index 411b24349..c5f40c246 100644
--- a/internal/ingress/controller/template/template_test.go
+++ b/internal/ingress/controller/template/template_test.go
@@ -59,20 +59,22 @@ func init() {
 var (
 	// TODO: add tests for SSLPassthrough
 	tmplFuncTestcases = map[string]struct {
-		Path             string
-		Target           string
-		Location         string
-		ProxyPass        string
-		Sticky           bool
-		XForwardedPrefix string
-		SecureBackend    bool
-		enforceRegex     bool
+		Path              string
+		Target            string
+		Location          string
+		ProxyPass         string
+		AutoHttpProxyPass string
+		Sticky            bool
+		XForwardedPrefix  string
+		SecureBackend     bool
+		enforceRegex      bool
 	}{
 		"when secure backend enabled": {
 			"/",
 			"/",
 			"/",
 			"proxy_pass https://upstream_balancer;",
+			"proxy_pass https://upstream_balancer;",
 			false,
 			"",
 			true,
@@ -83,6 +85,7 @@ var (
 			"/",
 			"/",
 			"proxy_pass https://upstream_balancer;",
+			"proxy_pass https://upstream_balancer;",
 			false,
 			"",
 			true,
@@ -93,6 +96,7 @@ var (
 			"/",
 			"/",
 			"proxy_pass https://upstream_balancer;",
+			"proxy_pass https://upstream_balancer;",
 			true,
 			"",
 			true,
@@ -103,6 +107,7 @@ var (
 			"/",
 			"/",
 			"proxy_pass http://upstream_balancer;",
+			"proxy_pass $scheme://upstream_balancer;",
 			false,
 			"",
 			false,
@@ -113,6 +118,7 @@ var (
 			"/",
 			"/",
 			"proxy_pass http://upstream_balancer;",
+			"proxy_pass $scheme://upstream_balancer;",
 			false,
 			"",
 			false,
@@ -125,6 +131,9 @@ var (
 			`
 rewrite "(?i)/" /jenkins break;
 proxy_pass http://upstream_balancer;`,
+			`
+rewrite "(?i)/" /jenkins break;
+proxy_pass $scheme://upstream_balancer;`,
 			false,
 			"",
 			false,
@@ -137,6 +146,9 @@ proxy_pass http://upstream_balancer;`,
 			`
 rewrite "(?i)/" /something break;
 proxy_pass http://upstream_balancer;`,
+			`
+rewrite "(?i)/" /something break;
+proxy_pass $scheme://upstream_balancer;`,
 			true,
 			"",
 			false,
@@ -149,6 +161,9 @@ proxy_pass http://upstream_balancer;`,
 			`
 rewrite "(?i)/" /something break;
 proxy_pass http://upstream_balancer;`,
+			`
+rewrite "(?i)/" /something break;
+proxy_pass $scheme://upstream_balancer;`,
 			true,
 			"",
 			false,
@@ -162,6 +177,10 @@ proxy_pass http://upstream_balancer;`,
 rewrite "(?i)/there" /something break;
 proxy_set_header X-Forwarded-Prefix "/there";
 proxy_pass http://upstream_balancer;`,
+			`
+rewrite "(?i)/there" /something break;
+proxy_set_header X-Forwarded-Prefix "/there";
+proxy_pass $scheme://upstream_balancer;`,
 			true,
 			"/there",
 			false,
@@ -172,6 +191,7 @@ proxy_pass http://upstream_balancer;`,
 			"/something",
 			`~* "^/something"`,
 			"proxy_pass http://upstream_balancer;",
+			"proxy_pass $scheme://upstream_balancer;",
 			false,
 			"",
 			false,
@@ -344,6 +364,48 @@ func TestBuildProxyPass(t *testing.T) {
 	}
 }
 
+func TestBuildProxyPassAutoHttp(t *testing.T) {
+	defaultBackend := "upstream-name"
+	defaultHost := "example.com"
+
+	for k, tc := range tmplFuncTestcases {
+		loc := &ingress.Location{
+			Path:             tc.Path,
+			Rewrite:          rewrite.Config{Target: tc.Target},
+			Backend:          defaultBackend,
+			XForwardedPrefix: tc.XForwardedPrefix,
+		}
+
+		if tc.SecureBackend {
+			loc.BackendProtocol = "HTTPS"
+		} else {
+			loc.BackendProtocol = "AUTO_HTTP"
+		}
+
+		backend := &ingress.Backend{
+			Name: defaultBackend,
+		}
+
+		if tc.Sticky {
+			backend.SessionAffinity = ingress.SessionAffinityConfig{
+				AffinityType: "cookie",
+				CookieSessionAffinity: ingress.CookieSessionAffinity{
+					Locations: map[string][]string{
+						defaultHost: {tc.Path},
+					},
+				},
+			}
+		}
+
+		backends := []*ingress.Backend{backend}
+
+		pp := buildProxyPass(defaultHost, backends, loc)
+		if !strings.EqualFold(tc.AutoHttpProxyPass, pp) {
+			t.Errorf("%s: expected \n'%v'\nbut returned \n'%v'", k, tc.ProxyPass, pp)
+		}
+	}
+}
+
 func TestBuildAuthLocation(t *testing.T) {
 	invalidType := &ingress.Ingress{}
 	expected := ""
@@ -899,13 +961,14 @@ func TestEscapeLiteralDollar(t *testing.T) {
 
 func TestOpentracingPropagateContext(t *testing.T) {
 	tests := map[*ingress.Location]string{
-		{BackendProtocol: "HTTP"}:  "opentracing_propagate_context;",
-		{BackendProtocol: "HTTPS"}: "opentracing_propagate_context;",
-		{BackendProtocol: "GRPC"}:  "opentracing_grpc_propagate_context;",
-		{BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;",
-		{BackendProtocol: "AJP"}:   "opentracing_propagate_context;",
-		{BackendProtocol: "FCGI"}:  "opentracing_propagate_context;",
-		nil:                        "",
+		{BackendProtocol: "HTTP"}:      "opentracing_propagate_context;",
+		{BackendProtocol: "HTTPS"}:     "opentracing_propagate_context;",
+		{BackendProtocol: "AUTO_HTTP"}: "opentracing_propagate_context;",
+		{BackendProtocol: "GRPC"}:      "opentracing_grpc_propagate_context;",
+		{BackendProtocol: "GRPCS"}:     "opentracing_grpc_propagate_context;",
+		{BackendProtocol: "AJP"}:       "opentracing_propagate_context;",
+		{BackendProtocol: "FCGI"}:      "opentracing_propagate_context;",
+		nil:                            "",
 	}
 
 	for loc, expectedDirective := range tests {
diff --git a/test/e2e/annotations/backendprotocol.go b/test/e2e/annotations/backendprotocol.go
index db7e50908..a215cbe83 100644
--- a/test/e2e/annotations/backendprotocol.go
+++ b/test/e2e/annotations/backendprotocol.go
@@ -46,6 +46,21 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
 			})
 	})
 
+	ginkgo.It("should set backend protocol to $scheme:// and use proxy_pass", func() {
+		host := "backendprotocol.foo.com"
+		annotations := map[string]string{
+			"nginx.ingress.kubernetes.io/backend-protocol": "AUTO_HTTP",
+		}
+
+		ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
+		f.EnsureIngress(ing)
+
+		f.WaitForNginxServer(host,
+			func(server string) bool {
+				return strings.Contains(server, "proxy_pass $scheme://upstream_balancer;")
+			})
+	})
+
 	ginkgo.It("should set backend protocol to grpc:// and use grpc_pass", func() {
 		host := "backendprotocol.foo.com"
 		annotations := map[string]string{