Building NGINX Ingress Controller with NGINX App Protect WAF

This document explains how to build a F5 NGINX Ingress Controller image with F5 NGINX App Protect WAF from source code.

Pre-built image alternatives
If you’d rather not build your own NGINX Ingress Controller image, see the pre-built image options at the end of this guide.

Before you start

  • To use NGINX App Protect WAF with NGINX Ingress Controller, you must have NGINX Plus.

Prepare the environment

Get your system ready for building and pushing the NGINX Ingress Controller image with NGINX App Protect WAF.

  1. Sign in to your private registry. Replace <my-docker-registry> with the path to your own private registry.

    docker login <my-docker-registry>
    
  2. Clone the NGINX Ingress Controller repository:

    git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.5.0
    cd kubernetes-ingress
    

Build the image

Follow these steps to build the NGINX Controller Image with NGINX App Protect WAF.

  1. Place your NGINX Plus license files (nginx-repo.crt and nginx-repo.key) in the project’s root folder. To verify they’re in place, run:

    ls nginx-repo.*
    

    You should see:

    nginx-repo.crt  nginx-repo.key
    
  2. Build the image. Replace <makefile target> with your chosen build option and <my-docker-registry> with your private registry’s path. Refer to the Makefile targets table below for the list of build options.

    make <makefile target> PREFIX=<my-docker-registry>/nginx-plus-ingress TARGET=download
    

    For example, to build a Debian-based image with NGINX Plus and NGINX App Protect DoS, run:

    make debian-image-dos-plus PREFIX=<my-docker-registry>/nginx-plus-ingress TARGET=download
    

    What to expect: The image is built and tagged with a version number, which is derived from the VERSION variable in the Makefile. This version number is used for tracking and deployment purposes.

Note:
In the event a patch of NGINX Plus is released, make sure to rebuild your image to get the latest version. If your system is caching the Docker layers and not updating the packages, add DOCKER_BUILD_OPTIONS="--pull --no-cache" to the make command.

Makefile targets

Makefile Target Description Compatible Systems
debian-image-nap-plus Builds a Debian-based image with NGINX Plus and the NGINX App Protect WAF module. Debian
debian-image-nap-dos-plus Builds a Debian-based image with NGINX Plus, NGINX App Protect WAF, and NGINX App Protect DoS Debian
ubi-image-nap-plus Builds a UBI-based image with NGINX Plus and the NGINX App Protect WAF module. OpenShift
ubi-image-nap-dos-plus Builds a UBNI-based image with NGINX Plus, NGINX App Protect WAF, and NGINX App Protect DoS. OpenShift

See Also:
For the complete list of Makefile targets and customizable variables, see the Building NGINX Ingress Controller guide.

If you intend to use external references in NGINX App Protect WAF policies, you may want to provide a custom CA certificate to authenticate with the hosting server.

To do so, place the *.crt file in the build folder and uncomment the lines following this comment: #Uncomment the lines below if you want to install a custom CA certificate

Warning:
External references are deprecated in NGINX Ingress Controller and will not be supported in future releases.

Push the image to your private registry

Once you’ve successfully built the NGINX Ingress Controller image with NGINX App Protect WAF, the next step is to upload it to your private Docker registry. This makes the image available for deployment to your Kubernetes cluster.

To upload the image, run the following command. If you’re using a custom tag, add TAG=your-tag to the end of the command. Replace <my-docker-registry> with your private registry’s path.

make push PREFIX=<my-docker-registry>/nginx-plus-ingress

Set up role-based access control (RBAC)

Admin access required
To complete these steps you need admin access to your cluster. Refer to to your Kubernetes platform’s documentation to set up admin access. For Google Kubernetes Engine (GKE), you can refer to their Role-Based Access Control guide.
  1. Create a namespace and a service account:

    kubectl apply -f deployments/common/ns-and-sa.yaml
    
  2. Create a cluster role and binding for the service account:

    kubectl apply -f deployments/rbac/rbac.yaml
    

If you’re planning to use NGINX App Protect or NGINX App Protect DoS, additional roles and bindings are needed.

  1. (NGINX App Protect only) Create the App Protect role and binding:

    kubectl apply -f deployments/rbac/ap-rbac.yaml
    
  2. (NGINX App Protect DoS only) Create the App Protect DoS role and binding:

    kubectl apply -f deployments/rbac/apdos-rbac.yaml
    

Create common resources

In this section, you’ll create resources that most NGINX Ingress Controller installations require:

  1. (Optional) Create a secret for the default NGINX server’s TLS certificate and key. Complete this step only if you’re using the default server TLS secret command-line argument. If you’re not, feel free to skip this step.

    By default, the server returns a 404 Not Found page for all requests when no ingress rules are set up. Although we provide a self-signed certificate and key for testing purposes, we recommend using your own certificate.

    kubectl apply -f examples/shared-examples/default-server-secret/default-server-secret.yaml
    
  2. Create a ConfigMap to customize your NGINX settings:

    kubectl apply -f deployments/common/nginx-config.yaml
    
  3. Create an IngressClass resource. NGINX Ingress Controller won’t start without an IngressClass resource.

    kubectl apply -f deployments/common/ingress-class.yaml
    

    If you want to make this NGINX Ingress Controller instance your cluster’s default, uncomment the ingressclass.kubernetes.io/is-default-class annotation. This action will auto-assign IngressClass to new ingresses that don’t specify an ingressClassName.


Create core custom resources

To make sure your NGINX Ingress Controller pods reach the Ready state, you’ll need to create custom resource definitions (CRDs) for various components.

Alternatively, you can disable this requirement by setting the -enable-custom-resources command-line argument to false.

There are two ways you can install the custom resource definitions:

  1. Using a URL to apply a single CRD yaml file, which we recommend.
  2. Applying your local copy of the CRD yaml files, which requires you to clone the repository.

This single YAML file creates CRDs for the following resources:

kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.3.2/deploy/crds.yaml

Note:
If you are installing the CRDs this way, ensure you have first cloned the repository.

These YAML files create CRDs for the following resources:

kubectl apply -f config/crd/bases/k8s.nginx.org_virtualservers.yaml
kubectl apply -f config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f config/crd/bases/k8s.nginx.org_transportservers.yaml
kubectl apply -f config/crd/bases/k8s.nginx.org_policies.yaml
kubectl apply -f config/crd/bases/k8s.nginx.org_globalconfigurations.yaml

Create App Protect WAF custom resources

Note:
If you’re using NGINX Ingress Controller with the App Protect WAF module and policy bundles, you can skip this section. You will need to create and configure Persistent Volume and Persistent Volume Claim in your Kubernetes cluster.

This single YAML file creates CRDs for the following resources:

  • APPolicy
  • APLogConf
  • APUserSig
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.3.2/deploy/crds-nap-waf.yaml

Note:
If you are installing the CRDs this way, ensure you have first cloned the repository.

These YAML files create CRDs for the following resources:

  • APPolicy
  • APLogConf
  • APUserSig
kubectl apply -f config/crd/bases/appprotect.f5.com_appolicies.yaml
kubectl apply -f config/crd/bases/appprotect.f5.com_aplogconfs.yaml
kubectl apply -f config/crd/bases/appprotect.f5.com_apusersigs.yaml

Deploy NGINX Ingress Controller

You have two options for deploying NGINX Ingress Controller:

  • Deployment. Choose this method for the flexibility to dynamically change the number of NGINX Ingress Controller replicas.
  • DaemonSet. Choose this method if you want NGINX Ingress Controller to run on all nodes or a subset of nodes.

Before you start, update the command-line arguments for the NGINX Ingress Controller container in the relevant manifest file to meet your specific requirements.

Note:

If you’re using NGINX Ingress Controller with the AppProtect WAF module and policy bundles, you will need to modify the Deployment or DaemonSet file to include volumes and volume mounts.

NGINX Ingress Controller requires the volume mount path to be /etc/nginx/waf/bundles.

Add a volumes section to deployment template spec:

...
volumes:
- name: <volume_name>
persistentVolumeClaim:
    claimName: <claim_name>
...

Add volume mounts to the containers section:

...
volumeMounts:
- name: <volume_mount_name>
    mountPath: /etc/nginx/waf/bundles
...

Using a Deployment

For additional context on managing containers using Kubernetes Deployments, refer to the official Kubernetes Deployments documentation.

When you deploy NGINX Ingress Controller as a Deployment, Kubernetes automatically sets up a single NGINX Ingress Controller pod.

  • For NGINX, run:

    kubectl apply -f deployments/deployment/nginx-ingress.yaml
    
  • For NGINX Plus, run:

    kubectl apply -f deployments/deployment/nginx-plus-ingress.yaml
    

    Update the nginx-plus-ingress.yaml file to include your chosen image from the F5 Container registry or your custom container image.

Using a DaemonSet

For additional context on managing containers using Kubernetes DaemonSets, refer to the official Kubernetes DaemonSets documentation.

When you deploy NGINX Ingress Controller as a DaemonSet, Kubernetes creates an Ingress Controller pod on every node in the cluster.

  • For NGINX, run:

    kubectl apply -f deployments/daemon-set/nginx-ingress.yaml
    
  • For NGINX Plus, run:

    kubectl apply -f deployments/daemon-set/nginx-plus-ingress.yaml
    

    Update the nginx-plus-ingress.yaml file to include your chosen image from the F5 Container registry or your custom container image.


Enable NGINX App Protect WAF module

To enable the NGINX App Protect DoS Module:


Confirm NGINX Ingress Controller is running

To confirm the NGINX Ingress Controller pods are operational, run:

kubectl get pods --namespace=nginx-ingress

For more information, see the Configuration guide and the NGINX Ingress Controller with App Protect example resources on GitHub for VirtualServer resources and [for Ingress resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.0/examples/ingress-resources/app-protect-waf" >}}).


Alternatives to building your own image

If you prefer not to build your own NGINX Ingress Controller image, you can use pre-built images. Here are your options: