F5 NGINX Ingress Controller
The DataDome Nginx module is compatible with F5 NGINX Ingress Controller.
Follow the steps below to integrate into your kubernetes infrastructure.
Prerequisites
- Existing
nginx-ingressdeployment kubectlaccess to your Kubernetes cluster- Container registry where you can push images (Docker Hub, ECR, GCR, ACR, etc.)
- The server-side key available in your DataDome dashboard
Overview
The deployment process involves:
- Building and pushing the custom F5 NGINX Ingress controller image with DataDome module to a registry
- Creating Kubernetes resources (Secret, ConfigMap)
- Updating the existing deployment to use the new image
Implementation
Step 1: Build and Push the Custom Image
Change
NGINX_INGRESS_VERSIONvariable to the desired image version.Change
REGISTRYto a registry where Kubernetes cluster can pull.
export NGINX_INGRESS_VERSION="5.3.2-alpine"
export REGISTRY="your-registry.com"
# Build the image (replace with your registry and version)
docker build --build-arg NGINX_INGRESS_VERSION=${NGINX_INGRESS_VERSION} -f Dockerfile -t ${REGISTRY}/nginx-ingress-datadome:${NGINX_INGRESS_VERSION} .
# Push to your container registry
docker push ${REGISTRY}/nginx-ingress-datadome:${NGINX_INGRESS_VERSION}ARG NGINX_INGRESS_VERSION=${NGINX_INGRESS_VERSION:-5.3.2-alpine}
ARG DATADOME_VERSION=${DATADOME_VERSION:-latest}
# STAGE1: Build DataDome module
FROM nginx/nginx-ingress:${NGINX_INGRESS_VERSION} AS module-builder
# Repeat ARGs definition to retain value
ARG NGINX_INGRESS_VERSION
ARG DATADOME_VERSION
# Make ENV variables from ARGs
ENV NGINX_INGRESS_VERSION=${NGINX_INGRESS_VERSION} \
DATADOME_VERSION=${DATADOME_VERSION}
# Make default user root to be able to install packages.
USER root
RUN set -x && \
nginx_version=$(nginx -v 2>&1 | awk '{print $3}' | sed -e 's|nginx/||') && \
curl -SsL http://nginx.org/download/nginx-${nginx_version}.tar.gz -o /tmp/nginx-${nginx_version}.tar.gz && \
curl -SsL https://package.datadome.co/linux/DataDome-Nginx-${DATADOME_VERSION}.tgz -o /tmp/datadome-nginx.tar.gz && \
mkdir -p /tmp/src/ && \
tar xzf /tmp/nginx-${nginx_version}.tar.gz -C /tmp/src && \
tar xzf /tmp/datadome-nginx.tar.gz -C /tmp/src && \
apk update && \
apk add --no-cache --virtual builddeps \
gcc \
make \
zlib-dev \
musl-dev \
pcre-dev \
openssl-dev \
&& \
DATADOME_DIR="DataDome-NginxDome-*" && \
if ls -d /tmp/src/${DATADOME_DIR} 1> /dev/null 2>&1; then \
echo "Old package structure pre AWS S3, it has the folder ${DATADOME_DIR}"; \
else \
echo "New package structure in AWS S3, it does not have the folder ${DATADOME_DIR}" ; \
DATADOME_DIR=""; \
fi && \
cd /tmp/src/${DATADOME_DIR} && \
sed -i 's/{ ngx_string("RequestModuleName"), ngx_string("Nginx")}/{ ngx_string("RequestModuleName"), ngx_string("nginxingress\/${nginx_version}")}/g' ngx_http_data_dome_shield_module.c && \
cd /tmp/src/nginx-${nginx_version} && \
nginx_flags=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') && \
echo $nginx_flags && \
./configure --with-compat --add-dynamic-module=../${DATADOME_DIR} && \
make modules &&\
cd ../ && \
make -C nginx-${nginx_version} -f objs/Makefile modules && \
mkdir -p /datadome-nginx-modules && \
cp nginx-${nginx_version}/objs/ngx_http_data_dome_*.so /datadome-nginx-modules/ && \
chown nginx:nginx /datadome-nginx-modules/* && \
chmod 755 /datadome-nginx-modules/* && \
apk del --no-cache builddeps && \
rm -rf /tmp/* \
/var/cache/apk/* \
/var/tmp/*
# revert to original user to drop privileges
USER nginx
# STAGE2: Final image
FROM nginx/nginx-ingress:${NGINX_INGRESS_VERSION}
ARG NGINX_INGRESS_VERSION
ARG DATADOME_VERSION
USER root
COPY --from=module-builder /datadome-nginx-modules /etc/nginx/modules
# check nginx configuration syntax
RUN nginx -t
# Switch back to nginx user
USER nginx
Step 2.1: Create the DataDome Secret
Create a file named datadome-secret.yaml:
Replace
DATADOME_SERVER_SIDE_KEYwith your API key from the DataDome dashboard.
apiVersion: v1
kind: Secret
metadata:
name: datadome-ingress-controller-secret
namespace: nginx-ingress # Match your ingress controller namespace
type: Opaque
stringData:
datadome-ingress-controller-secret: |
data_dome_shield_key "DATADOME_SERVER_SIDE_KEY";Apply the secret:
kubectl apply -f datadome-secret.yamlStep 2.2: Create the DataDome ConfigMap
Create a file named datadome-configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config # This must match your existing ConfigMap name
namespace: nginx-ingress
data:
# Load DataDome modules at NGINX startup
main-snippets: |
load_module /etc/nginx/modules/ngx_http_data_dome_auth_module.so;
load_module /etc/nginx/modules/ngx_http_data_dome_shield_module.so;
load_module /etc/nginx/modules/ngx_http_data_dome_upstream_dynamic_servers_module.so;
# Define DataDome API upstream and DNS resolver
http-snippets: |
resolver 8.8.8.8;
upstream datadome {
dd_server api.datadome.co:443;
keepalive 10;
}
# Enable DataDome protection at server level
server-snippets: |
data_dome_auth @datadome;
location = @datadome {
# Include the API key from the secret
include /etc/nginx/secrets/datadome-ingress-controller-secret;
proxy_pass https://datadome/validate-request/;
proxy_method POST;
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Content-Type "application/x-www-form-urlencoded";
proxy_set_header X-DataDome-X-Set-Cookie $data_dome_header_x_set_cookie;
proxy_set_body $data_dome_request_body;
proxy_ignore_client_abort on;
proxy_connect_timeout 150ms;
proxy_read_timeout 50ms;
proxy_next_upstream off;
}Apply the ConfigMap:
kubectl apply -f datadome-configmap.yamlNote: If you already have a nginx-config ConfigMap with custom settings, merge the DataDome snippets with your existing configuration instead of replacing it entirely.
Step 3: Update the Ingress Controller Deployment
This single command updates your existing NGINX Ingress Controller deployment with:
- The new DataDome-enabled image
- Snippets support enabled (
-enable-snippets=trueflag) - Secret volume mount (at
/etc/nginx/secrets/)
- Replace
${REGISTRY}/nginx-ingress-datadome:${NGINX_INGRESS_VERSION}with your image path from Step 1.- If different, adjust the deployment name (
nginx-ingress) and namespace (-n nginx-ingress).
kubectl patch deployment nginx-ingress -n nginx-ingress --type='json' -p='[
{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "${REGISTRY}/nginx-ingress-datadome:${NGINX_INGRESS_VERSION}"},
{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "-enable-snippets=true"},
{"op": "add", "path": "/spec/template/spec/volumes", "value": [
{"name": "datadome-secret", "secret": {"secretName": "datadome-ingress-controller-secret"}}
]},
{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts", "value": [
{"name": "datadome-secret", "mountPath": "/etc/nginx/secrets", "readOnly": true}
]}
]'Kubernetes will perform a rolling update, gradually replacing old pods with new ones to avoid downtime.
FAQ
How can I monitor the rollout?
To monitor the deployment rollout:
kubectl rollout status deployment/nginx-ingress -n nginx-ingressWait until you see: deployment "nginx-ingress" successfully rolled out
You can also check pod status:
kubectl get pods -n nginx-ingressHow can I rollback?
If something goes wrong, you can rollback to the previous deployment:
kubectl rollout undo deployment/nginx-ingress -n nginx-ingressThis restores the previous image, args, and volume configuration.
Updated about 4 hours ago
