In this post, we take a look at how to apply custom Nginx configuration directives when you’re using the NGINX Gateway Fabric.

What’s the NGINX Gateway Fabric?

The NGINX Gateway Fabric is an implementation of the Kubernetes Gateway API.

What’s the Gateway API?

The Gateway API is an evolution of the Ingress API; it aims to provide a flexible mechanism for managing north/south network traffic (that is, traffic entering or exiting your Kubernetes cluster), with additional work to support east/west traffic (traffic between pods in your cluster).

What’s this about custom configuration?

I’ve deployed a local development cluster, and I wanted to be able to push images into an image registry hosted on the cluster. This requires (a) running a registry, which is easy, and (b) somehow exposing that registry outside the cluster, which is also easy unless you decide to make it more complex.

In this case, I decided that rather than running an Ingress provider I was going to start familiarizing myself with the Gateway API, so I deployed NGINX Gateway Fabric. My first attempt at pushing an image into the registry looked like this:

$ podman push --tls-verify=false example registry.apps.cluster1.house/example:latest
Getting image source signatures
Copying blob b9fe5313d237 done   |
Copying blob cc2447e1835a done   |
Copying blob cb8b0886acfb done   |
Copying blob c4219a5645ea [===>----------------------------------] 9.3MiB / 80.2MiB | 372.7 MiB/s
Copying blob c6e5c62d1726 done   |
Copying blob 9ee7eb11f876 done   |
Copying blob f064c46326cb done   |
Copying blob 9c45ffa2a02a done   |
Copying blob 9a6c9897f309 done   |
Copying blob 27a0dbb2828e done   |
Error: writing blob: uploading layer chunked: StatusCode: 413, <html>
<head><title>413 Request Entity Too Large<...

Nginx, by default, restricts the maximum size of a request body to 1m, which is to say, 1 megabyte. You can increase (or remove) this limit by setting the client_max_body_size parameter…but how do you do this in the context of a managed deployment like the NGINX Gateway Fabric?

Via the API?

As of this writing, there is no mechanism to apply custom configuration options via the API (although there is ongoing work to provide this, see issue #1258).

What about dropping a config file into conf.d?

My first thought was that I could mount a custom configuration file into /etc/nginx/conf.d, along the lines of:

...
containers:
  - name: nginx
    volumeMounts:
      - name: nginx-extra-conf
        mountPath: /etc/nginx/conf.d/client_max_body_size.conf
        subPath: client_max_body_size
...
volumes:
  - name: nginx-extra-conf
    configMap:
      name: nginx-extra-conf

…but this fails because the Nginx controller explicitly cleans out that directory on startup and is unhappy if it is unable to delete a file.

Replacing nginx.conf

Right now, the solution is to replace /etc/nginx/nginx.conf. This is a relatively simple operation using kustomize to apply a patch to the deployment manifests.

Grab the original configuration

First, we need to retrieve the original nginx.conf:

mkdir configs
podman run --rm --entrypoint cat \
  ghcr.io/nginxinc/nginx-gateway-fabric/nginx:1.0.0 /etc/nginx/nginx.conf > configs/nginx.conf

Modify configs/nginx.conf as necessary; in my case, I added the following line to the http section:

client_max_body_size 0;

Patch the deployment

We can deploy the stock NGINX Gateway Fabric with a kustomization.yaml file like this:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  nginxGatewayVersion: v1.0.0

resources:
- https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.0.0/crds.yaml
- https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.0.0/nginx-gateway.yaml
- https://raw.githubusercontent.com/nginxinc/nginx-gateway-fabric/v1.0.0/deploy/manifests/service/nodeport.yaml

To patch the Deployment resource, we extend the kustomization.yaml with the following patch:

patches:
  - patch: |
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-gateway
        namespace: nginx-gateway
      spec:
        template:
          spec:
            containers:
              - name: nginx
                volumeMounts:
                  - mountPath: /etc/nginx/nginx.conf
                    name: nginx-conf-override
                    subPath: nginx.conf
            volumes:
              - name: nginx-conf-override
                configMap:
                  name: nginx-conf-override

And then we add a confdigMapGenerator to generate the nginx-conf-override ConfigMap:

configMapGenerator:
  - name: nginx-conf-override
    namespace: nginx-gateway
    options:
      disableNameSuffixHash: true
    files:
      - configs/nginx.conf

Now when we deploy from this directory…

kubectl apply -k . --server-side

…the deployment includes our patched nginx.conf and we are able to successfully push images into the cluster registry.


I’ve included the complete kustomization.yaml alongside this post.