ingress nginx FAQ For example the Ingress NGINX control plane has global and per Ingress configuration options that make it insecure if enabled in a multi tenant environment For example enabling snippets a global configuration allows any Ingress object to run arbitrary Lua code that could affect the security of all Ingress objects that a controller is running Do not use in multi tenant Kubernetes production installations This project assumes that users that can create Ingress objects are administrators of the cluster Multi tenant Kubernetes

Answer:
# FAQ

## Multi-tenant Kubernetes

Do not use in multi-tenant Kubernetes production installations. This project assumes that users that can create Ingress objects are administrators of the cluster.

For example, the Ingress NGINX control plane has global and per Ingress configuration options that make it insecure, if enabled, in a multi-tenant environment.

For example, enabling snippets, a global configuration, allows any Ingress object to run arbitrary Lua code that could affect the security of all Ingress objects that a controller is running.

We changed the default to allow snippets to `false` in https://github.com/kubernetes/ingress-nginx/pull/10393.

## Multiple controller in one cluster

Question - How can I easily install multiple instances of the ingress-nginx controller in the same cluster?

You can install them in different namespaces.

- Create a new namespace

  ```
  kubectl create namespace ingress-nginx-2
  ```

- Use Helm to install the additional instance of the ingress controller
- Ensure you have Helm working (refer to the [Helm documentation](https://helm.sh/docs/))
- We have to assume that you have the helm repo for the ingress-nginx controller already added to your Helm config.
  But, if you have not added the helm repo then you can do this to add the repo to your helm config;

  ```
  helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
  ```

- Make sure you have updated the helm repo data;

  ```
  helm repo update
  ```

- Now, install an additional instance of the ingress-nginx controller like this:

  ```
  helm install ingress-nginx-2 ingress-nginx/ingress-nginx  \
  --namespace ingress-nginx-2 \
  --set controller.ingressClassResource.name=nginx-two \
  --set controller.ingressClass=nginx-two \
  --set controller.ingressClassResource.controllerValue="example.com/ingress-nginx-2" \
  --set controller.ingressClassResource.enabled=true \
  --set controller.ingressClassByName=true
  ```

If you need to install yet another instance, then repeat the procedure to create a new namespace,
change the values such as names & namespaces (for example from "-2" to "-3"), or anything else that meets your needs.

Note that `controller.ingressClassResource.name` and `controller.ingressClass` have to be set correctly.
The first is to create the IngressClass object and the other is to modify the deployment of the actual ingress controller pod.

### I can't use multiple namespaces, what should I do?

If you need to install all instances in the same namespace, then you need to specify a different **election id**, like this:

```
helm install ingress-nginx-2 ingress-nginx/ingress-nginx  \
--namespace kube-system \
--set controller.electionID=nginx-two-leader \
--set controller.ingressClassResource.name=nginx-two \
--set controller.ingressClass=nginx-two \
--set controller.ingressClassResource.controllerValue="example.com/ingress-nginx-2" \
--set controller.ingressClassResource.enabled=true \
--set controller.ingressClassByName=true
```

## Retaining Client IPAddress

Question - How to obtain the real-client-ipaddress ?

The goto solution for retaining the real-client IPaddress is to enable PROXY protocol.

Enabling PROXY protocol has to be done on both, the Ingress NGINX controller, as well as the L4 load balancer, in front of the controller.

The real-client IP address is lost by default, when traffic is forwarded over the network. But enabling PROXY protocol ensures that the connection details are retained and hence the real-client IP address doesn't get lost.

Enabling proxy-protocol on the controller is documented [here](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-proxy-protocol) .

For enabling proxy-protocol on the LoadBalancer, please refer to the documentation of your infrastructure provider because that is where the LB is provisioned.

Some more info available [here](https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#source-ip-address)

Some more info on proxy-protocol is [here](https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#proxy-protocol)

### client-ipaddress on single-node cluster

Single node clusters are created for dev & test uses with tools like "kind" or "minikube". A trick to simulate a real use network with these clusters (kind or minikube) is to install Metallb and configure the ipaddress of the kind container or the minikube vm/container, as the starting and ending of the pool for Metallb in L2 mode. Then the host ip becomes a real client ipaddress, for curl requests sent from the host.

After installing ingress-nginx controller on a kind or a minikube cluster with helm, you can configure it for real-client-ip with a simple change to the service that ingress-nginx controller creates. The service object of --type LoadBalancer has a field service.spec.externalTrafficPolicy. If you set the value of this field to "Local" then the real-ipaddress of a client is visible to the controller.

```
% kubectl explain service.spec.externalTrafficPolicy
KIND:       Service
VERSION:    v1

FIELD: externalTrafficPolicy <string>

DESCRIPTION:
    externalTrafficPolicy describes how nodes distribute service traffic they
    receive on one of the Service's "externally-facing" addresses (NodePorts,
    ExternalIPs, and LoadBalancer IPs). If set to "Local", the proxy will
    configure the service in a way that assumes that external load balancers
    will take care of balancing the service traffic between nodes, and so each
    node will deliver traffic only to the node-local endpoints of the service,
    without masquerading the client source IP. (Traffic mistakenly sent to a
    node with no endpoints will be dropped.) The default value, "Cluster", uses
    the standard behavior of routing to all endpoints evenly (possibly modified
    by topology and other features). Note that traffic sent to an External IP or
    LoadBalancer IP from within the cluster will always get "Cluster" semantics,
    but clients sending to a NodePort from within the cluster may need to take
    traffic policy into account when picking a node.

    Possible enum values:
     - `"Cluster"` routes traffic to all endpoints.
     - `"Local"` preserves the source IP of the traffic by routing only to
    endpoints on the same node as the traffic was received on (dropping the
    traffic if there are no local endpoints).
```

### client-ipaddress L7

The solution is to get the real client IPaddress from the ["X-Forward-For" HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)

Example : If your application pod behind Ingress NGINX controller, uses the NGINX webserver and the reverseproxy inside it, then you can do the following to preserve the remote client IP.

- First you need to make sure that the X-Forwarded-For header reaches the backend pod. This is done by using a Ingress NGINX conftroller ConfigMap key. Its documented [here](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-forwarded-headers)

- Next, edit `nginx.conf` file inside your app pod, to contain the directives shown below:

```
set_real_ip_from 0.0.0.0/0; # Trust all IPs (use your VPC CIDR block in production)
real_ip_header X-Forwarded-For;
real_ip_recursive on;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" '
                'host=$host x-forwarded-for=$http_x_forwarded_for';

access_log /var/log/nginx/access.log main;

```

## Kubernetes v1.22 Migration

If you are using Ingress objects in your cluster (running Kubernetes older than
version 1.22), and you plan to upgrade your Kubernetes version to K8S 1.22 or
above, then please read [the migration guide here](./user-guide/k8s-122-migration.md).

## Validation Of **`path`**

- For improving security and also following desired standards on Kubernetes API
spec, the next release, scheduled for v1.8.0, will include a new & optional
feature of validating the value for the key `ingress.spec.rules.http.paths.path`.

- This behavior will be disabled by default on the 1.8.0 release and enabled by
default on the next breaking change release, set for 2.0.0.

- When "`ingress.spec.rules.http.pathType=Exact`" or "`pathType=Prefix`", this
validation will limit the characters accepted on the field "`ingress.spec.rules.http.paths.path`",
to "`alphanumeric characters`", and  `"/," "_," "-."` Also, in this case,
the path should start with `"/."`

- When the ingress resource path contains other characters (like on rewrite
configurations), the pathType value should be "`ImplementationSpecific`".

- API Spec on pathType is documented [here](https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types)

- When this option is enabled, the validation will happen on the Admission
Webhook. So if any new ingress object contains characters other than
alphanumeric characters, and, `"/,","_","-"`, in the `path` field, but
is not using `pathType` value as `ImplementationSpecific`, then the ingress
object will be denied admission.

- The cluster admin should establish validation rules using mechanisms like
"`Open Policy Agent`", to validate that only authorized users can use
ImplementationSpecific pathType and that only the authorized characters can be
used. [The configmap value is here](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#strict-validate-path-type)

- A complete example of an Openpolicyagent gatekeeper rule is available [here](https://kubernetes.github.io/ingress-nginx/examples/openpolicyagent/)

- If you have any issues or concerns, please do one of the following:
  - Open a GitHub issue
  - Comment in our Dev Slack Channel
  - Open a thread in our Google Group <ingress-nginx-dev@kubernetes.io>

## Why is chunking not working since controller v1.10 ?

- If your code is setting the HTTP header `"Transfer-Encoding: chunked"` and
the controller log messages show an error about duplicate header, it is
because of this change <http://hg.nginx.org/nginx/rev/2bf7792c262e>

- More details are available in this issue <https://github.com/kubernetes/ingress-nginx/issues/11162>

FAQ     Multi tenant Kubernetes  Do not use in multi tenant Kubernetes production installations  This project assumes that users that can create Ingress objects are administrators of the cluster   For example  the Ingress NGINX control plane has global and per Ingress configuration options that make it insecure  if enabled  in a multi tenant environment    For example  enabling snippets  a global configuration  allows any Ingress object to run arbitrary Lua code that could affect the security of all Ingress objects that a controller is running    We changed the default to allow snippets to  false  in https   github com kubernetes ingress nginx pull 10393      Multiple controller in one cluster  Question   How can I easily install multiple instances of the ingress nginx controller in the same cluster   You can install them in different namespaces     Create a new namespace          kubectl create namespace ingress nginx 2          Use Helm to install the additional instance of the ingress controller   Ensure you have Helm working  refer to the  Helm documentation  https   helm sh docs      We have to assume that you have the helm repo for the ingress nginx controller already added to your Helm config    But  if you have not added the helm repo then you can do this to add the repo to your helm config           helm repo add ingress nginx https   kubernetes github io ingress nginx          Make sure you have updated the helm repo data           helm repo update          Now  install an additional instance of the ingress nginx controller like this           helm install ingress nginx 2 ingress nginx ingress nginx        namespace ingress nginx 2       set controller ingressClassResource name nginx two       set controller ingressClass nginx two       set controller ingressClassResource controllerValue  example com ingress nginx 2        set controller ingressClassResource enabled true       set controller ingressClassByName true        If you need to install yet another instance  then repeat the procedure to create a new namespace  change the values such as names   namespaces  for example from   2  to   3    or anything else that meets your needs   Note that  controller ingressClassResource name  and  controller ingressClass  have to be set correctly  The first is to create the IngressClass object and the other is to modify the deployment of the actual ingress controller pod       I can t use multiple namespaces  what should I do   If you need to install all instances in the same namespace  then you need to specify a different   election id    like this       helm install ingress nginx 2 ingress nginx ingress nginx      namespace kube system     set controller electionID nginx two leader     set controller ingressClassResource name nginx two     set controller ingressClass nginx two     set controller ingressClassResource controllerValue  example com ingress nginx 2      set controller ingressClassResource enabled true     set controller ingressClassByName true         Retaining Client IPAddress  Question   How to obtain the real client ipaddress    The goto solution for retaining the real client IPaddress is to enable PROXY protocol   Enabling PROXY protocol has to be done on both  the Ingress NGINX controller  as well as the L4 load balancer  in front of the controller   The real client IP address is lost by default  when traffic is forwarded over the network  But enabling PROXY protocol ensures that the connection details are retained and hence the real client IP address doesn t get lost   Enabling proxy protocol on the controller is documented  here  https   kubernetes github io ingress nginx user guide nginx configuration configmap  use proxy protocol     For enabling proxy protocol on the LoadBalancer  please refer to the documentation of your infrastructure provider because that is where the LB is provisioned   Some more info available  here  https   kubernetes github io ingress nginx user guide miscellaneous  source ip address   Some more info on proxy protocol is  here  https   kubernetes github io ingress nginx user guide miscellaneous  proxy protocol       client ipaddress on single node cluster  Single node clusters are created for dev   test uses with tools like  kind  or  minikube   A trick to simulate a real use network with these clusters  kind or minikube  is to install Metallb and configure the ipaddress of the kind container or the minikube vm container  as the starting and ending of the pool for Metallb in L2 mode  Then the host ip becomes a real client ipaddress  for curl requests sent from the host   After installing ingress nginx controller on a kind or a minikube cluster with helm  you can configure it for real client ip with a simple change to the service that ingress nginx controller creates  The service object of   type LoadBalancer has a field service spec externalTrafficPolicy  If you set the value of this field to  Local  then the real ipaddress of a client is visible to the controller         kubectl explain service spec externalTrafficPolicy KIND        Service VERSION     v1  FIELD  externalTrafficPolicy  string   DESCRIPTION      externalTrafficPolicy describes how nodes distribute service traffic they     receive on one of the Service s  externally facing  addresses  NodePorts      ExternalIPs  and LoadBalancer IPs   If set to  Local   the proxy will     configure the service in a way that assumes that external load balancers     will take care of balancing the service traffic between nodes  and so each     node will deliver traffic only to the node local endpoints of the service      without masquerading the client source IP   Traffic mistakenly sent to a     node with no endpoints will be dropped   The default value   Cluster   uses     the standard behavior of routing to all endpoints evenly  possibly modified     by topology and other features   Note that traffic sent to an External IP or     LoadBalancer IP from within the cluster will always get  Cluster  semantics      but clients sending to a NodePort from within the cluster may need to take     traffic policy into account when picking a node           Possible enum values           Cluster   routes traffic to all endpoints           Local   preserves the source IP of the traffic by routing only to     endpoints on the same node as the traffic was received on  dropping the     traffic if there are no local endpoints            client ipaddress L7  The solution is to get the real client IPaddress from the   X Forward For  HTTP header  https   developer mozilla org en US docs Web HTTP Headers X Forwarded For   Example   If your application pod behind Ingress NGINX controller  uses the NGINX webserver and the reverseproxy inside it  then you can do the following to preserve the remote client IP     First you need to make sure that the X Forwarded For header reaches the backend pod  This is done by using a Ingress NGINX conftroller ConfigMap key  Its documented  here  https   kubernetes github io ingress nginx user guide nginx configuration configmap  use forwarded headers     Next  edit  nginx conf  file inside your app pod  to contain the directives shown below       set real ip from 0 0 0 0 0    Trust all IPs  use your VPC CIDR block in production  real ip header X Forwarded For  real ip recursive on   log format main   remote addr    remote user   time local    request                      status  body bytes sent   http referer                       http user agent                     host  host x forwarded for  http x forwarded for    access log  var log nginx access log main           Kubernetes v1 22 Migration  If you are using Ingress objects in your cluster  running Kubernetes older than version 1 22   and you plan to upgrade your Kubernetes version to K8S 1 22 or above  then please read  the migration guide here    user guide k8s 122 migration md       Validation Of    path       For improving security and also following desired standards on Kubernetes API spec  the next release  scheduled for v1 8 0  will include a new   optional feature of validating the value for the key  ingress spec rules http paths path      This behavior will be disabled by default on the 1 8 0 release and enabled by default on the next breaking change release  set for 2 0 0     When   ingress spec rules http pathType Exact   or   pathType Prefix    this validation will limit the characters accepted on the field   ingress spec rules http paths path    to   alphanumeric characters    and                   Also  in this case  the path should start with           When the ingress resource path contains other characters  like on rewrite configurations   the pathType value should be   ImplementationSpecific       API Spec on pathType is documented  here  https   kubernetes io docs concepts services networking ingress  path types     When this option is enabled  the validation will happen on the Admission Webhook  So if any new ingress object contains characters other than alphanumeric characters  and                  in the  path  field  but is not using  pathType  value as  ImplementationSpecific   then the ingress object will be denied admission     The cluster admin should establish validation rules using mechanisms like   Open Policy Agent    to validate that only authorized users can use ImplementationSpecific pathType and that only the authorized characters can be used   The configmap value is here  https   kubernetes github io ingress nginx user guide nginx configuration configmap  strict validate path type     A complete example of an Openpolicyagent gatekeeper rule is available  here  https   kubernetes github io ingress nginx examples openpolicyagent      If you have any issues or concerns  please do one of the following      Open a GitHub issue     Comment in our Dev Slack Channel     Open a thread in our Google Group  ingress nginx dev kubernetes io      Why is chunking not working since controller v1 10      If your code is setting the HTTP header   Transfer Encoding  chunked   and the controller log messages show an error about duplicate header  it is because of this change  http   hg nginx org nginx rev 2bf7792c262e     More details are available in this issue  https   github com kubernetes ingress nginx issues 11162


ingress nginx TLS Secrets warning Anytime we reference a TLS secret we mean a PEM encoded X 509 RSA 2048 secret You can generate a self signed certificate and private key with TLS HTTPS Ensure that the certificate order is leaf intermediate root otherwise the controller will not be able to import the certificate and you ll see this error in the logs

Answer:
# TLS/HTTPS

## TLS Secrets

Anytime we reference a TLS secret, we mean a PEM-encoded X.509, RSA (2048) secret.

!!! warning
    Ensure that the certificate order is leaf->intermediate->root, otherwise the controller will not be able to import the certificate, and you'll see this error in the logs ```W1012 09:15:45.920000       6 backend_ssl.go:46] Error obtaining X.509 certificate: unexpected error creating SSL Cert: certificate and private key does not have a matching public key: tls: private key does not match public key```

You can generate a self-signed certificate and private key with:

```bash
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}" -addext "subjectAltName = DNS:${HOST}"
```

Then create the secret in the cluster via:

```bash
kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE}
```

The resulting secret will be of type `kubernetes.io/tls`.

## Host names

Ensure that the relevant [ingress rules specify a matching hostname](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls).

## Default SSL Certificate

NGINX provides the option to configure a server as a catch-all with
[server_name](https://nginx.org/en/docs/http/server_names.html)
for requests that do not match any of the configured server names.
This configuration works out-of-the-box for HTTP traffic.
For HTTPS, a certificate is naturally required.

For this reason the Ingress controller provides the flag `--default-ssl-certificate`.
The secret referred to by this flag contains the default certificate to be used when
accessing the catch-all server.
If this flag is not provided NGINX will use a self-signed certificate.

For instance, if you have a TLS secret `foo-tls` in the `default` namespace,
add `--default-ssl-certificate=default/foo-tls` in the `nginx-controller` deployment.

If the `tls:` section is not set, NGINX will provide the default certificate but will not force HTTPS redirect.

On the other hand, if the `tls:` section is set - even without specifying a `secretName` option - NGINX will force HTTPS redirect.

To force redirects for Ingresses that do not specify a TLS-block at all, take a look at `force-ssl-redirect` in [ConfigMap][ConfigMap].

## SSL Passthrough

The [`--enable-ssl-passthrough`](cli-arguments.md) flag enables the SSL Passthrough feature, which is disabled by
default. This is required to enable passthrough backends in Ingress objects.

!!! warning
    This feature is implemented by intercepting **all traffic** on the configured HTTPS port (default: 443) and handing
    it over to a local TCP proxy. This bypasses NGINX completely and introduces a non-negligible performance penalty.

SSL Passthrough leverages [SNI][SNI] and reads the virtual domain from the TLS negotiation, which requires compatible
clients. After a connection has been accepted by the TLS listener, it is handled by the controller itself and piped back
and forth between the backend and the client.

If there is no hostname matching the requested host name, the request is handed over to NGINX on the configured
passthrough proxy port (default: 442), which proxies the request to the default backend.

!!! note
    Unlike HTTP backends, traffic to Passthrough backends is sent to the *clusterIP* of the backing Service instead of
    individual Endpoints.

## HTTP Strict Transport Security

HTTP Strict Transport Security (HSTS) is an opt-in security enhancement specified
through the use of a special response header. Once a supported browser receives
this header that browser will prevent any communications from being sent over
HTTP to the specified domain and will instead send all communications over HTTPS.

HSTS is enabled by default.

To disable this behavior use `hsts: "false"` in the configuration [ConfigMap][ConfigMap].

## Server-side HTTPS enforcement through redirect

By default the controller redirects HTTP clients to the HTTPS port
443 using a 308 Permanent Redirect response if TLS is enabled for that Ingress.

This can be disabled globally using `ssl-redirect: "false"` in the NGINX [config map][ConfigMap],
or per-Ingress with the `nginx.ingress.kubernetes.io/ssl-redirect: "false"`
annotation in the particular resource.

!!! tip
    When using SSL offloading outside of cluster (e.g. AWS ELB) it may be useful to enforce a
    redirect to HTTPS even when there is no TLS certificate available.
    This can be achieved by using the `nginx.ingress.kubernetes.io/force-ssl-redirect: "true"`
    annotation in the particular resource.

## Automated Certificate Management with cert-manager

[cert-manager] automatically requests missing or expired certificates from a range of
[supported issuers][cert-manager-issuer-config] (including [Let's Encrypt]) by monitoring
ingress resources.

To set up cert-manager you should take a look at this [full example][full-cert-manager-example].

To enable it for an ingress resource you have to deploy cert-manager, configure a certificate
issuer update the manifest:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
  annotations:
    cert-manager.io/issuer: "letsencrypt-staging" # Replace this with a production issuer once you've tested it
    [..]
spec:
  tls:
    - hosts:
        - ingress-demo.example.com
      secretName: ingress-demo-tls
    [...]
```

## Default TLS Version and Ciphers

To provide the most secure baseline configuration possible,

ingress-nginx defaults to using TLS 1.2 and 1.3 only, with a [secure set of TLS ciphers][ssl-ciphers].

### Legacy TLS

The default configuration, though secure, does not support some older browsers and operating systems.

For instance, TLS 1.1+ is only enabled by default from Android 5.0 on. At the time of writing,
May 2018, [approximately 15% of Android devices](https://developer.android.com/about/dashboards/#Platform)
are not compatible with ingress-nginx's default configuration.

To change this default behavior, use a [ConfigMap][ConfigMap].

A sample ConfigMap fragment to allow these older clients to connect could look something like the following
(generated using the Mozilla SSL Configuration Generator)[mozilla-ssl-config-old]:

```
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
data:
  ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
  ssl-protocols: "TLSv1.2 TLSv1.3"
```

[Let's Encrypt]:https://letsencrypt.org
[ConfigMap]: ./nginx-configuration/configmap.md
[ssl-ciphers]: ./nginx-configuration/configmap.md#ssl-ciphers
[SNI]: https://en.wikipedia.org/wiki/Server_Name_Indication
[mozilla-ssl-config-old]: https://ssl-config.mozilla.org/#server=nginx&config=old
[cert-manager]: https://github.com/jetstack/cert-manager/
[full-cert-manager-example]:https://cert-manager.io/docs/tutorials/acme/nginx-ingress/
[cert-manager-issuer-config]:https://cert-manager.io/docs/configuration/

TLS HTTPS     TLS Secrets  Anytime we reference a TLS secret  we mean a PEM encoded X 509  RSA  2048  secret       warning     Ensure that the certificate order is leaf  intermediate  root  otherwise the controller will not be able to import the certificate  and you ll see this error in the logs    W1012 09 15 45 920000       6 backend ssl go 46  Error obtaining X 509 certificate  unexpected error creating SSL Cert  certificate and private key does not have a matching public key  tls  private key does not match public key     You can generate a self signed certificate and private key with      bash   openssl req  x509  nodes  days 365  newkey rsa 2048  keyout   KEY FILE   out   CERT FILE   subj   CN   HOST  O   HOST    addext  subjectAltName   DNS   HOST        Then create the secret in the cluster via      bash kubectl create secret tls   CERT NAME    key   KEY FILE    cert   CERT FILE       The resulting secret will be of type  kubernetes io tls       Host names  Ensure that the relevant  ingress rules specify a matching hostname  https   kubernetes io docs concepts services networking ingress  tls       Default SSL Certificate  NGINX provides the option to configure a server as a catch all with  server name  https   nginx org en docs http server names html  for requests that do not match any of the configured server names  This configuration works out of the box for HTTP traffic  For HTTPS  a certificate is naturally required   For this reason the Ingress controller provides the flag    default ssl certificate   The secret referred to by this flag contains the default certificate to be used when accessing the catch all server  If this flag is not provided NGINX will use a self signed certificate   For instance  if you have a TLS secret  foo tls  in the  default  namespace  add    default ssl certificate default foo tls  in the  nginx controller  deployment   If the  tls   section is not set  NGINX will provide the default certificate but will not force HTTPS redirect   On the other hand  if the  tls   section is set   even without specifying a  secretName  option   NGINX will force HTTPS redirect    To force redirects for Ingresses that do not specify a TLS block at all  take a look at  force ssl redirect  in  ConfigMap  ConfigMap       SSL Passthrough  The     enable ssl passthrough   cli arguments md  flag enables the SSL Passthrough feature  which is disabled by default  This is required to enable passthrough backends in Ingress objects       warning     This feature is implemented by intercepting   all traffic   on the configured HTTPS port  default  443  and handing     it over to a local TCP proxy  This bypasses NGINX completely and introduces a non negligible performance penalty   SSL Passthrough leverages  SNI  SNI  and reads the virtual domain from the TLS negotiation  which requires compatible clients  After a connection has been accepted by the TLS listener  it is handled by the controller itself and piped back and forth between the backend and the client   If there is no hostname matching the requested host name  the request is handed over to NGINX on the configured passthrough proxy port  default  442   which proxies the request to the default backend       note     Unlike HTTP backends  traffic to Passthrough backends is sent to the  clusterIP  of the backing Service instead of     individual Endpoints      HTTP Strict Transport Security  HTTP Strict Transport Security  HSTS  is an opt in security enhancement specified through the use of a special response header  Once a supported browser receives this header that browser will prevent any communications from being sent over HTTP to the specified domain and will instead send all communications over HTTPS   HSTS is enabled by default   To disable this behavior use  hsts   false   in the configuration  ConfigMap  ConfigMap       Server side HTTPS enforcement through redirect  By default the controller redirects HTTP clients to the HTTPS port 443 using a 308 Permanent Redirect response if TLS is enabled for that Ingress   This can be disabled globally using  ssl redirect   false   in the NGINX  config map  ConfigMap   or per Ingress with the  nginx ingress kubernetes io ssl redirect   false   annotation in the particular resource       tip     When using SSL offloading outside of cluster  e g  AWS ELB  it may be useful to enforce a     redirect to HTTPS even when there is no TLS certificate available      This can be achieved by using the  nginx ingress kubernetes io force ssl redirect   true       annotation in the particular resource      Automated Certificate Management with cert manager   cert manager  automatically requests missing or expired certificates from a range of   supported issuers  cert manager issuer config   including  Let s Encrypt   by monitoring  ingress resources   To set up cert manager you should take a look at this  full example  full cert manager example    To enable it for an ingress resource you have to deploy cert manager  configure a certificate  issuer update the manifest      yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  ingress demo   annotations      cert manager io issuer   letsencrypt staging    Replace this with a production issuer once you ve tested it          spec    tls        hosts            ingress demo example com       secretName  ingress demo tls                   Default TLS Version and Ciphers  To provide the most secure baseline configuration possible   ingress nginx defaults to using TLS 1 2 and 1 3 only  with a  secure set of TLS ciphers  ssl ciphers        Legacy TLS  The default configuration  though secure  does not support some older browsers and operating systems   For instance  TLS 1 1  is only enabled by default from Android 5 0 on  At the time of writing  May 2018   approximately 15  of Android devices  https   developer android com about dashboards  Platform  are not compatible with ingress nginx s default configuration   To change this default behavior  use a  ConfigMap  ConfigMap    A sample ConfigMap fragment to allow these older clients to connect could look something like the following  generated using the Mozilla SSL Configuration Generator  mozilla ssl config old        kind  ConfigMap apiVersion  v1 metadata    name  nginx config data    ssl ciphers   ECDHE ECDSA AES128 GCM SHA256 ECDHE RSA AES128 GCM SHA256 ECDHE ECDSA AES256 GCM SHA384 ECDHE RSA AES256 GCM SHA384 ECDHE ECDSA CHACHA20 POLY1305 ECDHE RSA CHACHA20 POLY1305 DHE RSA AES128 GCM SHA256 DHE RSA AES256 GCM SHA384 DHE RSA CHACHA20 POLY1305 ECDHE ECDSA AES128 SHA256 ECDHE RSA AES128 SHA256 ECDHE ECDSA AES128 SHA ECDHE RSA AES128 SHA ECDHE ECDSA AES256 SHA384 ECDHE RSA AES256 SHA384 ECDHE ECDSA AES256 SHA ECDHE RSA AES256 SHA DHE RSA AES128 SHA256 DHE RSA AES256 SHA256 AES128 GCM SHA256 AES256 GCM SHA384 AES128 SHA256 AES256 SHA256 AES128 SHA AES256 SHA DES CBC3 SHA    ssl protocols   TLSv1 2 TLSv1 3          Let s Encrypt  https   letsencrypt org  ConfigMap     nginx configuration configmap md  ssl ciphers     nginx configuration configmap md ssl ciphers  SNI   https   en wikipedia org wiki Server Name Indication  mozilla ssl config old   https   ssl config mozilla org  server nginx config old  cert manager   https   github com jetstack cert manager   full cert manager example  https   cert manager io docs tutorials acme nginx ingress   cert manager issuer config  https   cert manager io docs configuration


ingress nginx FAQ Migration to Kubernetes 1 22 and apiVersion Please read this If you are using Ingress objects in your cluster running Kubernetes older than v1 22 What is an IngressClass and why is it important for users of ingress nginx controller now and you plan to upgrade to Kubernetes v1 22 this page is relevant to you

Answer:
# FAQ - Migration to Kubernetes 1.22 and apiVersion `networking.k8s.io/v1`

If you are using Ingress objects in your cluster (running Kubernetes older than v1.22),
and you plan to upgrade to Kubernetes v1.22, this page is relevant to you.

- Please read this [official blog on deprecated Ingress API versions](https://kubernetes.io/blog/2021/07/26/update-with-ingress-nginx/)
- Please read this [official documentation on the IngressClass object](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class)

## What is an IngressClass and why is it important for users of ingress-nginx controller now?

IngressClass is a Kubernetes resource. See the description below.
It's important because until now, a default install of the ingress-nginx controller did not require a IngressClass object.
From version 1.0.0 of the ingress-nginx controller, an IngressClass object is required.

On clusters with more than one instance of the ingress-nginx controller, all instances of the controllers must be aware of which Ingress objects they serve.
The `ingressClassName` field of an Ingress is the way to let the controller know about that.

```console
kubectl explain ingressclass
```

```
KIND:     IngressClass
VERSION:  networking.k8s.io/v1
DESCRIPTION:
     IngressClass represents the class of the Ingress, referenced by the Ingress
     Spec. The `ingressclass.kubernetes.io/is-default-class` annotation can be
     used to indicate that an IngressClass should be considered default. When a
     single IngressClass resource has this annotation set to true, new Ingress
     resources without a class specified will be assigned this default class.
FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
   metadata     <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   spec <Object>
     Spec is the desired state of the IngressClass. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status`
```

## What has caused this change in behavior?

There are 2 primary reasons.

### Reason 1

Until K8s version 1.21, it was possible to create an Ingress resource using deprecated versions of the Ingress API, such as:

- `extensions/v1beta1`
- `networking.k8s.io/v1beta1`
  You would get a message about deprecation, but the Ingress resource would get created.

From K8s version 1.22 onwards, you can **only** access the Ingress API via the stable, `networking.k8s.io/v1` API.
The reason is explained in the [official blog on deprecated ingress API versions](https://kubernetes.io/blog/2021/07/26/update-with-ingress-nginx/).

### Reason #2

If you are already using the ingress-nginx controller and then upgrade to Kubernetes 1.22,
there are several scenarios where your existing Ingress objects will not work how you expect.

Read this FAQ to check which scenario matches your use case.

## What is the `ingressClassName` field?

`ingressClassName` is a field in the spec of an Ingress object.

```shell
kubectl explain ingress.spec.ingressClassName
```

```console
KIND:     Ingress
VERSION:  networking.k8s.io/v1
FIELD:    ingressClassName <string>
DESCRIPTION:
     IngressClassName is the name of the IngressClass cluster resource. The
     associated IngressClass defines which controller will implement the
     resource. This replaces the deprecated `kubernetes.io/ingress.class`
     annotation. For backwards compatibility, when that annotation is set, it
     must be given precedence over this field. The controller may emit a warning
     if the field and annotation have different values. Implementations of this
     API should ignore Ingresses without a class specified. An IngressClass
     resource may be marked as default, which can be used to set a default value
     for this field. For more information, refer to the IngressClass
     documentation.
```

The `.spec.ingressClassName` behavior has precedence over the deprecated `kubernetes.io/ingress.class` annotation.

## I have only one ingress controller in my cluster. What should I do?

If a single instance of the ingress-nginx controller is the sole Ingress controller running in your cluster,
you should add the annotation "ingressclass.kubernetes.io/is-default-class" in your IngressClass,
so any new Ingress objects will have this one as default IngressClass.

When using Helm, you can enable this annotation by setting `.controller.ingressClassResource.default: true` in your Helm chart installation's values file.

If you have any old Ingress objects remaining without an IngressClass set, you can do one or more of the following to make the ingress-nginx controller aware of the old objects:

- You can manually set the [`.spec.ingressClassName`](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) field in the manifest of your own Ingress resources.
- You can re-create them after setting the `ingressclass.kubernetes.io/is-default-class` annotation to `true` on the IngressClass
- Alternatively you can make the ingress-nginx controller watch Ingress objects without the ingressClassName field set by starting your ingress-nginx with the flag [--watch-ingress-without-class=true](#what-is-the-flag-watch-ingress-without-class).
  When using Helm, you can configure your Helm chart installation's values file with `.controller.watchIngressWithoutClass: true`.

We recommend that you create the IngressClass as shown below:

```
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  labels:
    app.kubernetes.io/component: controller
  name: nginx
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: k8s.io/ingress-nginx
```

and add the value `spec.ingressClassName=nginx` in your Ingress objects.

## I have many ingress objects in my cluster. What should I do?

If you have a lot of ingress objects without ingressClass configuration,
you can run the ingress controller with the flag `--watch-ingress-without-class=true`.

### What is the flag `--watch-ingress-without-class`?

It's a flag that is passed, as an argument, to the `nginx-ingress-controller` executable.
In the configuration, it looks like this:

```yaml
# ...
args:
  - /nginx-ingress-controller
  - --watch-ingress-without-class=true
  - --controller-class=k8s.io/ingress-nginx
  # ...
# ...
```

## I have more than one controller in my cluster, and I'm already using the annotation

No problem. This should still keep working, but we highly recommend you to test!
Even though `kubernetes.io/ingress.class` is deprecated, the ingress-nginx controller still understands that annotation.
If you want to follow good practice, you should consider migrating to use IngressClass and `.spec.ingressClassName`.

## I have more than one controller running in my cluster, and I want to use the new API

In this scenario, you need to create multiple IngressClasses (see the example above).

Be aware that IngressClass works in a very specific way: you will need to change the `.spec.controller` value in your IngressClass and configure the controller to expect the exact same value.

Let's see an example, supposing that you have three IngressClasses:

- IngressClass `ingress-nginx-one`, with `.spec.controller` equal to `example.com/ingress-nginx1`
- IngressClass `ingress-nginx-two`, with `.spec.controller` equal to `example.com/ingress-nginx2`
- IngressClass `ingress-nginx-three`, with `.spec.controller` equal to `example.com/ingress-nginx1`

For private use, you can also use a controller name that doesn't contain a `/`, e.g. `ingress-nginx1`.

When deploying your ingress controllers, you will have to change the `--controller-class` field as follows:

- Ingress-Nginx A, configured to use controller class name `example.com/ingress-nginx1`
- Ingress-Nginx B, configured to use controller class name `example.com/ingress-nginx2`

When you create an Ingress object with its `ingressClassName` set to `ingress-nginx-two`,
only controllers looking for the `example.com/ingress-nginx2` controller class pay attention to the new object.

Given that Ingress-Nginx B is set up that way, it will serve that object, whereas Ingress-Nginx A ignores the new Ingress.

Bear in mind that if you start Ingress-Nginx B with the command line argument `--watch-ingress-without-class=true`, it will serve:

1. Ingresses without any `ingressClassName` set
2. Ingresses where the deprecated annotation (`kubernetes.io/ingress.class`) matches the value set in the command line argument `--ingress-class`
3. Ingresses that refer to any IngressClass that has the same `spec.controller` as configured in `--controller-class`
4. If you start Ingress-Nginx B with the command line argument `--watch-ingress-without-class=true` and you run Ingress-Nginx A with the command line argument `--watch-ingress-without-class=false` then this is a supported configuration.
   If you have two ingress-nginx controllers for the same cluster, both running with `--watch-ingress-without-class=true` then there is likely to be a conflict.

## Why am I seeing "ingress class annotation is not equal to the expected by Ingress Controller" in my controller logs?

It is highly likely that you will also see the name of the ingress resource in the same error message.
This error message has been observed on use the deprecated annotation (`kubernetes.io/ingress.class`) in an Ingress resource manifest.
It is recommended to use the `.spec.ingressClassName` field of the Ingress resource, to specify the name of the IngressClass of the Ingress you are defining.

FAQ   Migration to Kubernetes 1 22 and apiVersion  networking k8s io v1   If you are using Ingress objects in your cluster  running Kubernetes older than v1 22   and you plan to upgrade to Kubernetes v1 22  this page is relevant to you     Please read this  official blog on deprecated Ingress API versions  https   kubernetes io blog 2021 07 26 update with ingress nginx     Please read this  official documentation on the IngressClass object  https   kubernetes io docs concepts services networking ingress  ingress class      What is an IngressClass and why is it important for users of ingress nginx controller now   IngressClass is a Kubernetes resource  See the description below  It s important because until now  a default install of the ingress nginx controller did not require a IngressClass object  From version 1 0 0 of the ingress nginx controller  an IngressClass object is required   On clusters with more than one instance of the ingress nginx controller  all instances of the controllers must be aware of which Ingress objects they serve  The  ingressClassName  field of an Ingress is the way to let the controller know about that      console kubectl explain ingressclass          KIND      IngressClass VERSION   networking k8s io v1 DESCRIPTION       IngressClass represents the class of the Ingress  referenced by the Ingress      Spec  The  ingressclass kubernetes io is default class  annotation can be      used to indicate that an IngressClass should be considered default  When a      single IngressClass resource has this annotation set to true  new Ingress      resources without a class specified will be assigned this default class  FIELDS     apiVersion    string       APIVersion defines the versioned schema of this representation of an      object  Servers should convert recognized schemas to the latest internal      value  and may reject unrecognized values  More info       https   git k8s io community contributors devel sig architecture api conventions md resources    kind  string       Kind is a string value representing the REST resource this object      represents  Servers may infer this from the endpoint the client submits      requests to  Cannot be updated  In CamelCase  More info       https   git k8s io community contributors devel sig architecture api conventions md types kinds    metadata      Object       Standard object s metadata  More info       https   git k8s io community contributors devel sig architecture api conventions md metadata    spec  Object       Spec is the desired state of the IngressClass  More info       https   git k8s io community contributors devel sig architecture api conventions md spec and status          What has caused this change in behavior   There are 2 primary reasons       Reason 1  Until K8s version 1 21  it was possible to create an Ingress resource using deprecated versions of the Ingress API  such as      extensions v1beta1     networking k8s io v1beta1    You would get a message about deprecation  but the Ingress resource would get created   From K8s version 1 22 onwards  you can   only   access the Ingress API via the stable   networking k8s io v1  API  The reason is explained in the  official blog on deprecated ingress API versions  https   kubernetes io blog 2021 07 26 update with ingress nginx         Reason  2  If you are already using the ingress nginx controller and then upgrade to Kubernetes 1 22  there are several scenarios where your existing Ingress objects will not work how you expect   Read this FAQ to check which scenario matches your use case      What is the  ingressClassName  field    ingressClassName  is a field in the spec of an Ingress object      shell kubectl explain ingress spec ingressClassName         console KIND      Ingress VERSION   networking k8s io v1 FIELD     ingressClassName  string  DESCRIPTION       IngressClassName is the name of the IngressClass cluster resource  The      associated IngressClass defines which controller will implement the      resource  This replaces the deprecated  kubernetes io ingress class       annotation  For backwards compatibility  when that annotation is set  it      must be given precedence over this field  The controller may emit a warning      if the field and annotation have different values  Implementations of this      API should ignore Ingresses without a class specified  An IngressClass      resource may be marked as default  which can be used to set a default value      for this field  For more information  refer to the IngressClass      documentation       The   spec ingressClassName  behavior has precedence over the deprecated  kubernetes io ingress class  annotation      I have only one ingress controller in my cluster  What should I do   If a single instance of the ingress nginx controller is the sole Ingress controller running in your cluster  you should add the annotation  ingressclass kubernetes io is default class  in your IngressClass  so any new Ingress objects will have this one as default IngressClass   When using Helm  you can enable this annotation by setting   controller ingressClassResource default  true  in your Helm chart installation s values file   If you have any old Ingress objects remaining without an IngressClass set  you can do one or more of the following to make the ingress nginx controller aware of the old objects     You can manually set the    spec ingressClassName   https   kubernetes io docs reference kubernetes api service resources ingress v1  IngressSpec  field in the manifest of your own Ingress resources    You can re create them after setting the  ingressclass kubernetes io is default class  annotation to  true  on the IngressClass   Alternatively you can make the ingress nginx controller watch Ingress objects without the ingressClassName field set by starting your ingress nginx with the flag    watch ingress without class true   what is the flag watch ingress without class     When using Helm  you can configure your Helm chart installation s values file with   controller watchIngressWithoutClass  true    We recommend that you create the IngressClass as shown below           apiVersion  networking k8s io v1 kind  IngressClass metadata    labels      app kubernetes io component  controller   name  nginx   annotations      ingressclass kubernetes io is default class   true  spec    controller  k8s io ingress nginx      and add the value  spec ingressClassName nginx  in your Ingress objects      I have many ingress objects in my cluster  What should I do   If you have a lot of ingress objects without ingressClass configuration  you can run the ingress controller with the flag    watch ingress without class true        What is the flag    watch ingress without class    It s a flag that is passed  as an argument  to the  nginx ingress controller  executable  In the configuration  it looks like this      yaml       args       nginx ingress controller       watch ingress without class true       controller class k8s io ingress nginx                       I have more than one controller in my cluster  and I m already using the annotation  No problem  This should still keep working  but we highly recommend you to test  Even though  kubernetes io ingress class  is deprecated  the ingress nginx controller still understands that annotation  If you want to follow good practice  you should consider migrating to use IngressClass and   spec ingressClassName       I have more than one controller running in my cluster  and I want to use the new API  In this scenario  you need to create multiple IngressClasses  see the example above    Be aware that IngressClass works in a very specific way  you will need to change the   spec controller  value in your IngressClass and configure the controller to expect the exact same value   Let s see an example  supposing that you have three IngressClasses     IngressClass  ingress nginx one   with   spec controller  equal to  example com ingress nginx1    IngressClass  ingress nginx two   with   spec controller  equal to  example com ingress nginx2    IngressClass  ingress nginx three   with   spec controller  equal to  example com ingress nginx1   For private use  you can also use a controller name that doesn t contain a      e g   ingress nginx1    When deploying your ingress controllers  you will have to change the    controller class  field as follows     Ingress Nginx A  configured to use controller class name  example com ingress nginx1    Ingress Nginx B  configured to use controller class name  example com ingress nginx2   When you create an Ingress object with its  ingressClassName  set to  ingress nginx two   only controllers looking for the  example com ingress nginx2  controller class pay attention to the new object   Given that Ingress Nginx B is set up that way  it will serve that object  whereas Ingress Nginx A ignores the new Ingress   Bear in mind that if you start Ingress Nginx B with the command line argument    watch ingress without class true   it will serve   1  Ingresses without any  ingressClassName  set 2  Ingresses where the deprecated annotation   kubernetes io ingress class   matches the value set in the command line argument    ingress class  3  Ingresses that refer to any IngressClass that has the same  spec controller  as configured in    controller class  4  If you start Ingress Nginx B with the command line argument    watch ingress without class true  and you run Ingress Nginx A with the command line argument    watch ingress without class false  then this is a supported configuration     If you have two ingress nginx controllers for the same cluster  both running with    watch ingress without class true  then there is likely to be a conflict      Why am I seeing  ingress class annotation is not equal to the expected by Ingress Controller  in my controller logs   It is highly likely that you will also see the name of the ingress resource in the same error message  This error message has been observed on use the deprecated annotation   kubernetes io ingress class   in an Ingress resource manifest  It is recommended to use the   spec ingressClassName  field of the Ingress resource  to specify the name of the IngressClass of the Ingress you are defining


ingress nginx note important Regular Expression Support Please see the for Validation Of Ingress Path Matching Regular expressions is not supported in the field The wildcard character must appear by itself as the first DNS label and matches only a single label You cannot have a wildcard label by itself e g Host

Answer:
# Ingress Path Matching

## Regular Expression Support

!!! important
    Regular expressions is not supported in the `spec.rules.host` field. The wildcard character '\*' must appear by itself as the first DNS label and matches only a single label. You cannot have a wildcard label by itself (e.g. Host == "\*").

!!! note
    Please see the [FAQ](../faq.md#validation-of-path) for Validation Of __`path`__

The ingress controller supports **case insensitive** regular expressions in the `spec.rules.http.paths.path` field.
This can be enabled by setting the `nginx.ingress.kubernetes.io/use-regex` annotation to `true` (the default is false).

!!! hint
    Kubernetes only accept expressions that comply with the RE2 engine syntax. It is possible that valid expressions accepted by NGINX cannot be used with ingress-nginx, because the PCRE library (used in NGINX) supports a wider syntax than RE2.
    See the [RE2 Syntax](https://github.com/google/re2/wiki/Syntax) documentation for differences.

See the [description](./nginx-configuration/annotations.md#use-regex) of the `use-regex` annotation for more details.

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: test.com
    http:
      paths:
      - path: /foo/.*
        pathType: ImplementationSpecific
        backend:
          service:
            name: test
            port:
              number: 80
```

The preceding ingress definition would translate to the following location block within the NGINX configuration for the `test.com` server:

```txt
location ~* "^/foo/.*" {
  ...
}
```

## Path Priority

In NGINX, regular expressions follow a **first match** policy. In order to enable more accurate path matching, ingress-nginx first orders the paths by descending length before writing them to the NGINX template as location blocks.

**Please read the [warning](#warning) before using regular expressions in your ingress definitions.**

### Example

Let the following two ingress definitions be created:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress-1
spec:
  ingressClassName: nginx
  rules:
  - host: test.com
    http:
      paths:
      - path: /foo/bar
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /foo/bar/
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
```

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress-2
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - host: test.com
    http:
      paths:
      - path: /foo/bar/(.+)
        pathType: ImplementationSpecific
        backend:
          service:
            name: service3
            port:
              number: 80
```

The ingress controller would define the following location blocks, in order of descending length, within the NGINX template for the `test.com` server:

```txt
location ~* ^/foo/bar/.+ {
  ...
}

location ~* "^/foo/bar/" {
  ...
}

location ~* "^/foo/bar" {
  ...
}
```

The following request URI's would match the corresponding location blocks:

- `test.com/foo/bar/1` matches `~* ^/foo/bar/.+` and will go to service 3.
- `test.com/foo/bar/` matches `~* ^/foo/bar/` and will go to service 2.
- `test.com/foo/bar` matches `~* ^/foo/bar` and will go to service 1.

**IMPORTANT NOTES**:

- If the `use-regex` OR `rewrite-target` annotation is used on any Ingress for a given host, then the case insensitive regular expression [location modifier](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) will be enforced on ALL paths for a given host regardless of what Ingress they are defined on.

## Warning

The following example describes a case that may inflict unwanted path matching behavior.

This case is expected and a result of NGINX's a first match policy for paths that use the regular expression [location modifier](https://nginx.org/en/docs/http/ngx_http_core_module.html#location). For more information about how a path is chosen, please read the following article: ["Understanding Nginx Server and Location Block Selection Algorithms"](https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms).

### Example

Let the following ingress be defined:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress-3
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: test.com
    http:
      paths:
      - path: /foo/bar/bar
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80
      - path: /foo/bar/[A-Z0-9]{3}
        pathType: ImplementationSpecific
        backend:
          service:
            name: test
            port:
              number: 80
```

The ingress controller would define the following location blocks (in this order) within the NGINX template for the `test.com` server:

```txt
location ~* "^/foo/bar/[A-Z0-9]{3}" {
  ...
}

location ~* "^/foo/bar/bar" {
  ...
}
```

A request to `test.com/foo/bar/bar` would match the `^/foo/bar/[A-Z0-9]{3}` location block instead of the longest EXACT matching path.

Ingress Path Matching     Regular Expression Support      important     Regular expressions is not supported in the  spec rules host  field  The wildcard character      must appear by itself as the first DNS label and matches only a single label  You cannot have a wildcard label by itself  e g  Host                note     Please see the  FAQ     faq md validation of path  for Validation Of    path     The ingress controller supports   case insensitive   regular expressions in the  spec rules http paths path  field  This can be enabled by setting the  nginx ingress kubernetes io use regex  annotation to  true   the default is false        hint     Kubernetes only accept expressions that comply with the RE2 engine syntax  It is possible that valid expressions accepted by NGINX cannot be used with ingress nginx  because the PCRE library  used in NGINX  supports a wider syntax than RE2      See the  RE2 Syntax  https   github com google re2 wiki Syntax  documentation for differences   See the  description    nginx configuration annotations md use regex  of the  use regex  annotation for more details      yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  test ingress   annotations      nginx ingress kubernetes io use regex   true  spec    ingressClassName  nginx   rules      host  test com     http        paths          path   foo            pathType  ImplementationSpecific         backend            service              name  test             port                number  80      The preceding ingress definition would translate to the following location block within the NGINX configuration for the  test com  server      txt location       foo                       Path Priority  In NGINX  regular expressions follow a   first match   policy  In order to enable more accurate path matching  ingress nginx first orders the paths by descending length before writing them to the NGINX template as location blocks     Please read the  warning   warning  before using regular expressions in your ingress definitions         Example  Let the following two ingress definitions be created      yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  test ingress 1 spec    ingressClassName  nginx   rules      host  test com     http        paths          path   foo bar         pathType  Prefix         backend            service              name  service1             port                number  80         path   foo bar          pathType  Prefix         backend            service              name  service2             port                number  80         yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  test ingress 2   annotations      nginx ingress kubernetes io rewrite target    1 spec    ingressClassName  nginx   rules      host  test com     http        paths          path   foo bar              pathType  ImplementationSpecific         backend            service              name  service3             port                 number  80      The ingress controller would define the following location blocks  in order of descending length  within the NGINX template for the  test com  server      txt location      foo bar               location       foo bar              location       foo bar                 The following request URI s would match the corresponding location blocks      test com foo bar 1  matches       foo bar     and will go to service 3     test com foo bar   matches       foo bar   and will go to service 2     test com foo bar  matches       foo bar  and will go to service 1     IMPORTANT NOTES       If the  use regex  OR  rewrite target  annotation is used on any Ingress for a given host  then the case insensitive regular expression  location modifier  https   nginx org en docs http ngx http core module html location  will be enforced on ALL paths for a given host regardless of what Ingress they are defined on      Warning  The following example describes a case that may inflict unwanted path matching behavior   This case is expected and a result of NGINX s a first match policy for paths that use the regular expression  location modifier  https   nginx org en docs http ngx http core module html location   For more information about how a path is chosen  please read the following article    Understanding Nginx Server and Location Block Selection Algorithms   https   www digitalocean com community tutorials understanding nginx server and location block selection algorithms        Example  Let the following ingress be defined      yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  test ingress 3   annotations      nginx ingress kubernetes io use regex   true  spec    ingressClassName  nginx   rules      host  test com     http        paths          path   foo bar bar         pathType  Prefix         backend            service              name  test             port                 number  80         path   foo bar  A Z0 9  3          pathType  ImplementationSpecific         backend            service              name  test             port                 number  80      The ingress controller would define the following location blocks  in this order  within the NGINX template for the  test com  server      txt location       foo bar  A Z0 9  3              location       foo bar bar                 A request to  test com foo bar bar  would match the    foo bar  A Z0 9  3   location block instead of the longest EXACT matching path


ingress nginx The ingress nginx ingress controller can be used to directly expose servers Enabling FastCGI in your Ingress only requires setting the backend protocol annotation to and with a couple more annotations you can customize the way ingress nginx handles the communication with your FastCGI server For most practical use cases php applications are a good example PHP is not HTML so a FastCGI server like php fpm processes a index php script for the response to a request See a working example below FastCGI is a for interfacing interactive programs with a It s aim is to reduce the overhead related to interfacing between web server and CGI programs allowing a server to handle more web page requests per unit of time mdash Wikipedia Exposing FastCGI Servers

Answer:
# Exposing FastCGI Servers

> **FastCGI** is a [binary protocol](https://en.wikipedia.org/wiki/Binary_protocol "Binary protocol") for interfacing interactive programs with a [web server](https://en.wikipedia.org/wiki/Web_server "Web server"). [...] (It's) aim is to reduce the overhead related to interfacing between web server and CGI programs, allowing a server to handle more web page requests per unit of time.
>
> — Wikipedia

The _ingress-nginx_ ingress controller can be used to directly expose [FastCGI](https://en.wikipedia.org/wiki/FastCGI) servers.  Enabling FastCGI in your Ingress only requires setting the _backend-protocol_ annotation to `FCGI`, and with a couple more annotations you can customize the way _ingress-nginx_ handles the communication with your FastCGI _server_.

For most practical use-cases, php applications are a good example. PHP is not HTML so a FastCGI server like php-fpm processes a index.php script for the response to a request. See a working example below.

This [post in a FactCGI feature issue](https://github.com/kubernetes/ingress-nginx/issues/8207#issuecomment-2161405468) describes a test for the FastCGI feature. The same test is described below here.

## Example Objects to expose a FastCGI server pod

### The FasctCGI server pod

The _Pod_ object example below exposes port `9000`, which is the conventional FastCGI port.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: example-app
  labels:
    app: example-app
spec:
  containers:
  - name: example-app
    image: php:fpm-alpine
    ports:
    - containerPort: 9000
      name: fastcgi
```

- For this example to work, a HTML response should be received from the FastCGI server being exposed
- A HTTP request to the FastCGI server pod should be sent
- The response should be generated by a php script as that is what we are demonstrating here

The image we are using here `php:fpm-alpine` does not ship with a ready to use php script inside it. So we need to provide the image with a simple php-script for this example to work.

- Use `kubectl exec` to get into the example-app pod
- You will land at the path `/var/www/html`
- Create a simple php script there at the path /var/www/html called index.php
- Make the index.php file look like this

```
<!DOCTYPE html>
<html>
    <head>
        <title>PHP Test</title>
    </head>
    <body>
        <?php echo '<p>FastCGI Test Worked!</p>'; ?>
    </body>
</html>
```

- Save and exit from the shell in the pod
- If you delete the pod, then you will have to recreate the file as this method is not persistent

### The FastCGI service

The _Service_ object example below matches port `9000` from the _Pod_ object above.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example-app
  ports:
  - port: 9000
    targetPort: 9000
    name: fastcgi
```

### The configMap object and the ingress object

The _Ingress_ and _ConfigMap_ objects below demonstrate the supported _FastCGI_ specific annotations.

!!! Important
    NGINX actually has 50 [FastCGI directives](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#directives)
    All of the nginx directives have not been exposed in the ingress yet

### The ConfigMap object

This configMap object is required to set the parameters of [FastCGI directives](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#directives)

!!! Attention
    - The _ConfigMap_ **must** be created before creating the ingress object

- The _Ingress Controller_ needs to find the configMap when the _Ingress_ object with the FastCGI annotations is created
- So create the configMap before the ingress
- If the configMap is created after the ingress is created, then you will need to restart the _Ingress Controller_ pods.

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: example-cm
data:
  SCRIPT_FILENAME: "/var/www/html/index.php"

```

### The ingress object

- Do not create the ingress shown below until you have created the configMap seen above.
- You can see that this ingress matches the service `example-service`, and the port named `fastcgi` from above.

```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
    nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
    nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-cm"
  name: example-app
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              name: fastcgi
```

## Send a request to the exposed FastCGI server

You will have to look at the external-ip of the ingress or you have to send the HTTP request to the ClusterIP address of the ingress-nginx controller pod.

```
% curl 172.19.0.2 -H "Host: app.example.com" -vik
*   Trying 172.19.0.2:80...
* Connected to 172.19.0.2 (172.19.0.2) port 80
> GET / HTTP/1.1
> Host: app.example.com
> User-Agent: curl/8.6.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Wed, 12 Jun 2024 07:11:59 GMT
Date: Wed, 12 Jun 2024 07:11:59 GMT
< Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
< Connection: keep-alive
Connection: keep-alive
< X-Powered-By: PHP/8.3.8
X-Powered-By: PHP/8.3.8

<
<!DOCTYPE html>
<html>
    <head>
        <title>PHP Test</title>
    </head>
    <body>
        <p>FastCGI Test Worked</p>    </body>
</html>

```

## FastCGI Ingress Annotations

To enable FastCGI, the `nginx.ingress.kubernetes.io/backend-protocol` annotation needs to be set to `FCGI`, which overrides the default `HTTP` value.

> `nginx.ingress.kubernetes.io/backend-protocol: "FCGI"`

**This enables the _FastCGI_ mode for all paths defined in the _Ingress_ object**

### The `nginx.ingress.kubernetes.io/fastcgi-index` Annotation

To specify an index file, the `fastcgi-index` annotation value can optionally be set.  In the example below, the value is set to `index.php`.  This annotation corresponds to [the _NGINX_ `fastcgi_index` directive](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_index).

> `nginx.ingress.kubernetes.io/fastcgi-index: "index.php"`

### The `nginx.ingress.kubernetes.io/fastcgi-params-configmap` Annotation

To specify [_NGINX_ `fastcgi_param` directives](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_param), the `fastcgi-params-configmap` annotation is used, which in turn must lead to a _ConfigMap_ object containing the _NGINX_ `fastcgi_param` directives as key/values.

> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-configmap"`

And the _ConfigMap_ object to specify the `SCRIPT_FILENAME` and `HTTP_PROXY`  _NGINX's_ `fastcgi_param` directives will look like the following:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: example-configmap
data:
  SCRIPT_FILENAME: "/example/index.php"
  HTTP_PROXY: ""
```

Using the _namespace/_ prefix is also supported, for example:

> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-namespace/example-configmap"`

Exposing FastCGI Servers      FastCGI   is a  binary protocol  https   en wikipedia org wiki Binary protocol  Binary protocol   for interfacing interactive programs with a  web server  https   en wikipedia org wiki Web server  Web server           It s  aim is to reduce the overhead related to interfacing between web server and CGI programs  allowing a server to handle more web page requests per unit of time       mdash  Wikipedia  The  ingress nginx  ingress controller can be used to directly expose  FastCGI  https   en wikipedia org wiki FastCGI  servers   Enabling FastCGI in your Ingress only requires setting the  backend protocol  annotation to  FCGI   and with a couple more annotations you can customize the way  ingress nginx  handles the communication with your FastCGI  server    For most practical use cases  php applications are a good example  PHP is not HTML so a FastCGI server like php fpm processes a index php script for the response to a request  See a working example below   This  post in a FactCGI feature issue  https   github com kubernetes ingress nginx issues 8207 issuecomment 2161405468  describes a test for the FastCGI feature  The same test is described below here      Example Objects to expose a FastCGI server pod      The FasctCGI server pod  The  Pod  object example below exposes port  9000   which is the conventional FastCGI port      yaml apiVersion  v1 kind  Pod metadata    name  example app   labels      app  example app spec    containers      name  example app     image  php fpm alpine     ports        containerPort  9000       name  fastcgi        For this example to work  a HTML response should be received from the FastCGI server being exposed   A HTTP request to the FastCGI server pod should be sent   The response should be generated by a php script as that is what we are demonstrating here  The image we are using here  php fpm alpine  does not ship with a ready to use php script inside it  So we need to provide the image with a simple php script for this example to work     Use  kubectl exec  to get into the example app pod   You will land at the path   var www html    Create a simple php script there at the path  var www html called index php   Make the index php file look like this        DOCTYPE html   html       head           title PHP Test  title        head       body            php echo   p FastCGI Test Worked   p             body    html         Save and exit from the shell in the pod   If you delete the pod  then you will have to recreate the file as this method is not persistent      The FastCGI service  The  Service  object example below matches port  9000  from the  Pod  object above      yaml apiVersion  v1 kind  Service metadata    name  example service spec    selector      app  example app   ports      port  9000     targetPort  9000     name  fastcgi          The configMap object and the ingress object  The  Ingress  and  ConfigMap  objects below demonstrate the supported  FastCGI  specific annotations       Important     NGINX actually has 50  FastCGI directives  https   nginx org en docs http ngx http fastcgi module html directives      All of the nginx directives have not been exposed in the ingress yet      The ConfigMap object  This configMap object is required to set the parameters of  FastCGI directives  https   nginx org en docs http ngx http fastcgi module html directives       Attention       The  ConfigMap    must   be created before creating the ingress object    The  Ingress Controller  needs to find the configMap when the  Ingress  object with the FastCGI annotations is created   So create the configMap before the ingress   If the configMap is created after the ingress is created  then you will need to restart the  Ingress Controller  pods      yaml apiVersion  v1 kind  ConfigMap metadata    name  example cm data    SCRIPT FILENAME    var www html index php            The ingress object    Do not create the ingress shown below until you have created the configMap seen above    You can see that this ingress matches the service  example service   and the port named  fastcgi  from above       apiVersion  networking k8s io v1 kind  Ingress metadata    annotations      nginx ingress kubernetes io backend protocol   FCGI      nginx ingress kubernetes io fastcgi index   index php      nginx ingress kubernetes io fastcgi params configmap   example cm    name  example app spec    ingressClassName  nginx   rules      host  app example com     http        paths          path            pathType  Prefix         backend            service              name  example service             port                name  fastcgi         Send a request to the exposed FastCGI server  You will have to look at the external ip of the ingress or you have to send the HTTP request to the ClusterIP address of the ingress nginx controller pod         curl 172 19 0 2  H  Host  app example com   vik     Trying 172 19 0 2 80      Connected to 172 19 0 2  172 19 0 2  port 80   GET   HTTP 1 1   Host  app example com   User Agent  curl 8 6 0   Accept           HTTP 1 1 200 OK HTTP 1 1 200 OK   Date  Wed  12 Jun 2024 07 11 59 GMT Date  Wed  12 Jun 2024 07 11 59 GMT   Content Type  text html  charset UTF 8 Content Type  text html  charset UTF 8   Transfer Encoding  chunked Transfer Encoding  chunked   Connection  keep alive Connection  keep alive   X Powered By  PHP 8 3 8 X Powered By  PHP 8 3 8       DOCTYPE html   html       head           title PHP Test  title        head       body           p FastCGI Test Worked  p       body    html           FastCGI Ingress Annotations  To enable FastCGI  the  nginx ingress kubernetes io backend protocol  annotation needs to be set to  FCGI   which overrides the default  HTTP  value      nginx ingress kubernetes io backend protocol   FCGI      This enables the  FastCGI  mode for all paths defined in the  Ingress  object        The  nginx ingress kubernetes io fastcgi index  Annotation  To specify an index file  the  fastcgi index  annotation value can optionally be set   In the example below  the value is set to  index php    This annotation corresponds to  the  NGINX   fastcgi index  directive  https   nginx org en docs http ngx http fastcgi module html fastcgi index       nginx ingress kubernetes io fastcgi index   index php        The  nginx ingress kubernetes io fastcgi params configmap  Annotation  To specify   NGINX   fastcgi param  directives  https   nginx org en docs http ngx http fastcgi module html fastcgi param   the  fastcgi params configmap  annotation is used  which in turn must lead to a  ConfigMap  object containing the  NGINX   fastcgi param  directives as key values      nginx ingress kubernetes io fastcgi params configmap   example configmap    And the  ConfigMap  object to specify the  SCRIPT FILENAME  and  HTTP PROXY    NGINX s   fastcgi param  directives will look like the following      yaml apiVersion  v1 kind  ConfigMap metadata    name  example configmap data    SCRIPT FILENAME    example index php    HTTP PROXY          Using the  namespace   prefix is also supported  for example      nginx ingress kubernetes io fastcgi params configmap   example namespace example configmap


ingress nginx Using IngressClasses Multiple Ingress controllers To fix this problem use The annotation is not being preferred or suggested to use as it can be deprecated in the future Better to use the field But when user has deployed with then the ingress class resource field is not used By default deploying multiple Ingress controllers e g will result in all controllers simultaneously racing to update Ingress status fields in confusing ways

Answer:
# Multiple Ingress controllers

By default, deploying multiple Ingress controllers (e.g., `ingress-nginx` & `gce`) will result in all controllers simultaneously racing to update Ingress status fields in confusing ways.

To fix this problem, use [IngressClasses](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class). The `kubernetes.io/ingress.class` annotation is not being preferred or suggested to use as it can be deprecated in the future. Better to use the field `ingress.spec.ingressClassName`.
But, when user has deployed with `scope.enabled`, then the ingress class resource field is not used.

## Using IngressClasses

If all ingress controllers respect IngressClasses (e.g. multiple instances of ingress-nginx v1.0), you can deploy two Ingress controllers by granting them control over two different IngressClasses, then selecting one of the two IngressClasses with `ingressClassName`.

First, ensure the `--controller-class=` and `--ingress-class` are set to something different on each ingress controller, If your additional ingress controller is to be installed in a namespace, where there is/are one/more-than-one ingress-nginx-controller(s) already installed, then you need to specify a different unique `--election-id` for the new instance of the controller.

```yaml
# ingress-nginx Deployment/Statefulset
spec:
  template:
     spec:
       containers:
         - name: ingress-nginx-internal-controller
           args:
             - /nginx-ingress-controller
             - '--election-id=ingress-controller-leader'
             - '--controller-class=k8s.io/internal-ingress-nginx'
             - '--ingress-class=k8s.io/internal-nginx'
            ...
```

Then use the same value in the IngressClass:

```yaml
# ingress-nginx IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: internal-nginx
spec:
  controller: k8s.io/internal-ingress-nginx
  ...
```

And refer to that IngressClass in your Ingress:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  ingressClassName: internal-nginx
  ...
```

or if installing with Helm:

```yaml
controller:
  electionID: ingress-controller-leader
  ingressClass: internal-nginx  # default: nginx
  ingressClassResource:
    name: internal-nginx  # default: nginx
    enabled: true
    default: false
    controllerValue: "k8s.io/internal-ingress-nginx"  # default: k8s.io/ingress-nginx
```

!!! important

    When running multiple ingress-nginx controllers, it will only process an unset class annotation if one of the controllers uses the default
    `--controller-class` value (see `IsValid` method in `internal/ingress/annotations/class/main.go`), otherwise the class annotation becomes required.

    If `--controller-class` is set to the default value of `k8s.io/ingress-nginx`, the controller will monitor Ingresses with no class annotation *and* Ingresses with annotation class set to `nginx`. Use a non-default value for `--controller-class`, to ensure that the controller only satisfied the specific class of Ingresses.

## Using the kubernetes.io/ingress.class annotation (in deprecation)

If you're running multiple ingress controllers where one or more do not support IngressClasses, you must specify the annotation `kubernetes.io/ingress.class: "nginx"` in all ingresses that you would like ingress-nginx to claim.

For instance,

```yaml
metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "gce"
```

will target the GCE controller, forcing the Ingress-NGINX controller to ignore it, while an annotation like:

```yaml
metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "nginx"
```

will target the Ingress-NGINX controller, forcing the GCE controller to ignore it.

You can change the value "nginx" to something else by setting the `--ingress-class` flag:

```yaml
spec:
  template:
     spec:
       containers:
         - name: ingress-nginx-internal-controller
           args:
             - /nginx-ingress-controller
             - --ingress-class=internal-nginx
```

then setting the corresponding `kubernetes.io/ingress.class: "internal-nginx"` annotation on your Ingresses.

To reiterate, setting the annotation to any value which does not match a valid ingress class will force the Ingress-Nginx Controller to ignore your Ingress.
If you are only running a single Ingress-Nginx Controller, this can be achieved by setting the annotation to any value except "nginx" or an empty string.

Do this if you wish to use one of the other Ingress controllers at the same time as the NGINX controller.

Multiple Ingress controllers  By default  deploying multiple Ingress controllers  e g    ingress nginx     gce   will result in all controllers simultaneously racing to update Ingress status fields in confusing ways   To fix this problem  use  IngressClasses  https   kubernetes io docs concepts services networking ingress  ingress class   The  kubernetes io ingress class  annotation is not being preferred or suggested to use as it can be deprecated in the future  Better to use the field  ingress spec ingressClassName   But  when user has deployed with  scope enabled   then the ingress class resource field is not used       Using IngressClasses  If all ingress controllers respect IngressClasses  e g  multiple instances of ingress nginx v1 0   you can deploy two Ingress controllers by granting them control over two different IngressClasses  then selecting one of the two IngressClasses with  ingressClassName    First  ensure the    controller class   and    ingress class  are set to something different on each ingress controller  If your additional ingress controller is to be installed in a namespace  where there is are one more than one ingress nginx controller s  already installed  then you need to specify a different unique    election id  for the new instance of the controller      yaml   ingress nginx Deployment Statefulset spec    template       spec         containers             name  ingress nginx internal controller            args                  nginx ingress controller                   election id ingress controller leader                    controller class k8s io internal ingress nginx                    ingress class k8s io internal nginx                       Then use the same value in the IngressClass      yaml   ingress nginx IngressClass apiVersion  networking k8s io v1 kind  IngressClass metadata    name  internal nginx spec    controller  k8s io internal ingress nginx            And refer to that IngressClass in your Ingress      yaml apiVersion  networking k8s io v1 kind  Ingress metadata    name  my ingress spec    ingressClassName  internal nginx            or if installing with Helm      yaml controller    electionID  ingress controller leader   ingressClass  internal nginx    default  nginx   ingressClassResource      name  internal nginx    default  nginx     enabled  true     default  false     controllerValue   k8s io internal ingress nginx     default  k8s io ingress nginx          important      When running multiple ingress nginx controllers  it will only process an unset class annotation if one of the controllers uses the default        controller class  value  see  IsValid  method in  internal ingress annotations class main go    otherwise the class annotation becomes required       If    controller class  is set to the default value of  k8s io ingress nginx   the controller will monitor Ingresses with no class annotation  and  Ingresses with annotation class set to  nginx   Use a non default value for    controller class   to ensure that the controller only satisfied the specific class of Ingresses      Using the kubernetes io ingress class annotation  in deprecation   If you re running multiple ingress controllers where one or more do not support IngressClasses  you must specify the annotation  kubernetes io ingress class   nginx   in all ingresses that you would like ingress nginx to claim    For instance      yaml metadata    name  foo   annotations      kubernetes io ingress class   gce       will target the GCE controller  forcing the Ingress NGINX controller to ignore it  while an annotation like      yaml metadata    name  foo   annotations      kubernetes io ingress class   nginx       will target the Ingress NGINX controller  forcing the GCE controller to ignore it   You can change the value  nginx  to something else by setting the    ingress class  flag      yaml spec    template       spec         containers             name  ingress nginx internal controller            args                  nginx ingress controller                  ingress class internal nginx      then setting the corresponding  kubernetes io ingress class   internal nginx   annotation on your Ingresses   To reiterate  setting the annotation to any value which does not match a valid ingress class will force the Ingress Nginx Controller to ignore your Ingress  If you are only running a single Ingress Nginx Controller  this can be achieved by setting the annotation to any value except  nginx  or an empty string   Do this if you wish to use one of the other Ingress controllers at the same time as the NGINX controller