Fine‑tuning of NGINX-based Wallarm Ingress Controller¶
Learn fine-tuning options available for the self-hosted Wallarm Ingress controller to get the most out of the Wallarm solution.
Official documentation for NGINX Ingress Controller
The fine‑tuning of the Wallarm Ingress Controller is quite similar to that of the NGINX Ingress Controller described in the official documentation. When working with Wallarm, all options for setting up the original NGINX Ingress Controller are available.
Additional Settings for Helm Chart¶
The settings are defined in the values.yaml file. By default, the file looks as follows:
controller:
  wallarm:
    enabled: false
    apiHost: api.wallarm.com
    apiPort: 443
    apiSSL: true
    token: ""
    nodeGroup: defaultIngressGroup
    existingSecret:
      enabled: false
      secretKey: token
      secretName: wallarm-api-token
    postanalytics:
      kind: Deployment
      service:
        annotations: {}
      arena: "2.0"
      serviceAddress: "0.0.0.0:3313"
      serviceProtocol: "tcp4"
      livenessProbe:
        failureThreshold: 3
        initialDelaySeconds: 10
        periodSeconds: 10
        successThreshold: 1
        timeoutSeconds: 1
      tls:
        enabled: false
      #  certFile: "/root/test-tls-certs/server.crt"
      #  keyFile: "/root/test-tls-certs/server.key"
      #  caCertFile: "/root/test-tls-certs/ca.crt"
      #  mutualTLS:
      #    enabled: false
      #    clientCACertFile: "/root/test-tls-certs/ca.crt"
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    wallarm-appstructure:
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    wallarm-antibot:
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    metrics:
      port: 18080
      enabled: false
      service:
        annotations:
          prometheus.io/scrape: "true"
          prometheus.io/path: /wallarm-metrics
          prometheus.io/port: "18080"
        ## List of IP addresses at which the stats-exporter service is available
        ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips
        ##
        externalIPs: []
        loadBalancerIP: ""
        loadBalancerSourceRanges: []
        servicePort: 18080
        type: ClusterIP
    init:
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    wcliController:
      logLevel: warn
      commands:
        apispec:
          logLevel: INFO
        blkexp:
          logLevel: INFO
        botexp:
          logLevel: WARN
        cntexp:
          logLevel: ERROR
        cntsync:
          logLevel: INFO
        credstuff:
          logLevel: INFO
        envexp:
          logLevel: INFO
        ipfeed:
          logLevel: INFO
        iplist:
          logLevel: INFO
        jwtexp:
          logLevel: INFO
        metricsexp:
          logLevel: INFO
        mrksync:
          logLevel: INFO
        register:
          logLevel: INFO
        reqexp:
          logLevel: INFO
        syncnode:
          logLevel: INFO
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    wcliPostanalytics:
      logLevel: warn
      commands:
        apispec:
          logLevel: INFO
        blkexp:
          logLevel: INFO
        botexp:
          logLevel: WARN
        cntexp:
          logLevel: ERROR
        cntsync:
          logLevel: INFO
        credstuff:
          logLevel: INFO
        envexp:
          logLevel: INFO
        ipfeed:
          logLevel: INFO
        iplist:
          logLevel: INFO
        jwtexp:
          logLevel: INFO
        metricsexp:
          logLevel: INFO
        mrksync:
          logLevel: INFO
        register:
          logLevel: INFO
        reqexp:
          logLevel: INFO
        syncnode:
          logLevel: INFO
      resources: {}
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
    apiFirewall:
      enabled: true
      config:
        ...
      extraEnvs:
        - name: EXTRA_ENV_VAR_NAME
          value: EXTRA_ENV_VAR_VALUE
      metrics:
        enabled: false
        port: 9010
        endpointPath: /metrics
        host: ":9010"
        service:
          servicePort: 9010
        serviceMonitor:
          ## Enables creation of the ServiceMonitor resource
          enabled: false
          ## Extra labels used to match the Prometheus instance
          additionalLabels: {}
          # -- Annotations to be added to the ServiceMonitor
          annotations: {}
          ## The label to use to retrieve the job name from
          ## jobLabel: "app.kubernetes.io/name"
          namespace: ""
          namespaceSelector: {}
          ## Default: scrape .Release.Namespace or namespaceOverride only
          ## To scrape all, use the following:
          ## namespaceSelector:
          ##   any: true
          scrapeInterval: 30s
          # honorLabels: true
          targetLabels: []
          relabelings: []
          metricRelabelings: []
validation:
  enableCel: false
  forbidDangerousAnnotations: false
To change this setting, we recommend using the option --set of helm install (if installing the Ingress controller) or helm upgrade (if updating the installed Ingress controller parameters). For example:
A description of the main parameters you can set up is provided below. Other parameters come with default values and rarely need to be changed.
controller.wallarm.enabled¶
Allows you to enable or disable Wallarm functions.
Default value: false
controller.wallarm.apiHost¶
Wallarm API endpoint. Can be:
Default value: api.wallarm.com
controller.wallarm.token¶
A filtering node token value. It is required to access the Wallarm API.
The token can be one of these types:
-  API token (recommended) - Ideal if you need to dynamically add/remove node groups for UI organization or if you want to control token lifecycle for added security. To generate an API token: To generate an API token: - Go to Wallarm Console → Settings → API tokens in either the US Cloud or EU Cloud.
- Create an API token with the Node deployment/Deployment usage type.
- During node deployment, use the generated token and specify the group name using the controller.wallarm.nodeGroupparameter. You can add multiple nodes to one group using different API tokens.
 
-  Node token - Suitable when you already know the node groups that will be used. To generate a node token: 
The parameter is ignored if controller.wallarm.existingSecret.enabled: true.
Default value: not specified
controller.wallarm.nodeGroup¶
Starting from Helm chart version 4.6.8, this specifies the name of the group of filtering nodes you want to add newly deployed nodes to. Node grouping this way is available only when you create and connect nodes to the Cloud using an API token with the Node deployment/Deployment usage type (its value is passed in the controller.wallarm.token parameter).
Default value: defaultIngressGroup
controller.wallarm.existingSecret¶
Starting from the Helm chart version 4.4.1, you can use this configuration block to pull a Wallarm node token value from Kubernetes secrets. It is useful for environments with separate secret management (e.g. you use an external secrets operator).
To store the node token in K8s secrets and pull it to the Helm chart:
-  Create a Kubernetes secret with the Wallarm node token: kubectl -n <KUBERNETES_NAMESPACE> create secret generic wallarm-api-token --from-literal=token=<WALLARM_NODE_TOKEN>- <KUBERNETES_NAMESPACE>is the Kubernetes namespace you have created for the Helm release with Wallarm Ingress controller
- wallarm-api-tokenis the Kubernetes secret name
- <WALLARM_NODE_TOKEN>is the Wallarm node token value copied from the Wallarm Console UI
 If using some external secret operator, follow appropriate documentation to create a secret. 
-  Set the following configuration in values.yaml:
Default value: existingSecret.enabled: false that points to the Helm chart to get the Wallarm node token from controller.wallarm.token.
controller.wallarm.postanalytics.arena¶
Specifies the amount of memory allocated for postanalytics service. It is recommended to set up a value sufficient to store request data for the last 5-15 minutes.
Default value: 2.0
In the NGINX Node 5.x and earlier, the parameter has been named controller.wallarm.tarantool.arena. Renaming is required during upgrade.
controller.wallarm.postanalytics.serviceAddress¶
Specifies the address and port on which wstore accepts incoming connections.
Supported from the release 6.3.0 onwards.
Default value:
-  Node 6.6.0 and higher: 0.0.0.0:3313- listens on port 3313 on all IPv4 interfaces.
-  Prior versions: [::]:3313- listened on port 3313 on all IPv4 and IPv6 interfaces.
controller.wallarm.postanalytics.serviceProtocol¶
Specifies the protocol family that wstore uses for incoming connections.
Supported from the release 6.6.0 onwards.
Possible values:
-  tcp- dual-stack mode (listens on both IPv4 and IPv6)
-  tcp4- IPv4 only
-  tcp6- IPv6 only
Default value: "tcp4".
controller.wallarm.postanalytics.tls¶
Configures TLS and mutual TLS (mTLS) settings to allow secure connection to the postanalytics module (optional):
controller:
  wallarm:
    postanalytics:
      tls:
        enabled: false
      #  certFile: "/root/test-tls-certs/server.crt"
      #  keyFile: "/root/test-tls-certs/server.key"
      #  caCertFile: "/root/test-tls-certs/ca.crt"
      #  mutualTLS:
      #    enabled: false
      #    clientCACertFile: "/root/test-tls-certs/ca.crt"
Supported from the release 6.2.0 onwards.
| Parameter | Description | Required? | 
|---|---|---|
| enabled | Enables or disables SSL/TLS for the connection to the postanalytics module. By default, false(disabled). | Yes | 
| certFile | Specifies the path to the client certificate used by the the Filtering Node to authenticate itself when establishing an SSL/TLS connection to the postanalytics module. | Yes if mutualTLS.enabledistrue | 
| keyFile | Specifies the path to the private key corresponding to the client certificate provided via certFile. | Yes if mutualTLS.enabledistrue | 
| caCertFile | Specifies the path to a trusted Certificate Authority (CA) certificate used to validate the TLS certificate presented by the postanalytics module. | Yes if using a custom CA | 
| mutualTLS.enabled | Enables mutual TLS (mTLS), where both the Filtering Node and the postanalytics module verify each other's identity via certificates. By default, false(disabled). | No | 
| mutualTLS.clientCACertFile | Specifies the path to a trusted Certificate Authority (CA) certificate used to validate the TLS certificate presented by the Filtering Node. | Yes if using a custom CA | 
controller.wallarm.metrics.enabled¶
This switch toggles information and metrics collection. If Prometheus is installed in the Kubernetes cluster, no additional configuration is required.
Default value: false
controller.wallarm.apiFirewall¶
Controls the configuration of API Specification Enforcement, available starting from release 4.10. By default, it is enabled and configured as shown below. If you are using this feature, it is recommended to keep these values unchanged.
controller:
  wallarm:
    apiFirewall:
      ### Enable or disable API Firewall functionality (true|false)
      ###
      enabled: true
      readBufferSize: 8192
      writeBufferSize: 8192
      maxRequestBodySize: 4194304
      disableKeepalive: false
      maxConnectionsPerIp: 0
      maxRequestsPerConnection: 0
      config:
        mainPort: 18081
        healthPort: 18082
        specificationUpdatePeriod: 1m
        unknownParametersDetection: true
        #### TRACE|DEBUG|INFO|WARNING|ERROR
        logLevel: DEBUG
        ### TEXT|JSON
        logFormat: TEXT
      ...
Since node 5.1.0, the following is presented (see default values in the example above):
| Setting | Description | 
|---|---|
| readBufferSize | Per-connection buffer size for request reading. This also limits the maximum header size. Increase this buffer if your clients send multi-KB RequestURIs and/or multi-KB headers (for example, BIG cookies). | 
| writeBufferSize | Per-connection buffer size for response writing. | 
| maxRequestBodySize | Maximum request body size. The server rejects requests with bodies exceeding this limit. | 
| disableKeepalive | Disables the keep-alive connections. The server will close all the incoming connections after sending the first response to the client if this option is set to true. | 
| maxConnectionsPerIp | Maximum number of concurrent client connections allowed per IP. 0=unlimited. | 
| maxRequestsPerConnection | Maximum number of requests served per connection. The server closes the connection after the last request. The Connection: closeheader is added to the last response.0=unlimited. | 
controller.wallarm.apiFirewall.metrics¶
Starting from version 6.5.1, the API Specification Enforcement module can expose Prometheus-compatible metrics.
When enabled, metrics are available by default at http://<host>:9010/metrics.
| Setting | Description | 
|---|---|
| enabled | Enables Prometheus metrics for the API Specification Enforcement module. By default: false(disabled). | 
| port | Defines the port on which the API Specification Enforcement module exposes metrics. If you change this value, also update controller.wallarm.apiFirewall.metrics.service.servicePort.Default: 9010. | 
| endpointPath | Defines the HTTP path of the API Specification Enforcement metrics endpoint By default: metrics. | 
| host | IP address and port for binding the metrics server. By default: :9010(all interfaces on port 9010). | 
controller:
  wallarm:
    apiFirewall:
      metrics:
        enabled: false
        port: 9010
        endpointPath: /metrics
        host: ":9010"
        service:
          servicePort: 9010
controller.wallarm.apiFirewall.metrics.serviceMonitor¶
If you are using the Prometheus Operator (for example, as part of the kube-prometheus-stack), you can configure the chart to automatically create a ServiceMonitor resource for scraping API Specification Enforcement metrics.
The serviceMonitor configuration options are available starting from version 6.5.1.
Configuration options with default values:
controller:
  wallarm:
    apiFirewall:
      metrics:
        ...
        serviceMonitor:
          ## Enables creation of the ServiceMonitor resource
          enabled: false
          ## Extra labels used to match the Prometheus instance
          additionalLabels: {}
          # -- Annotations to be added to the ServiceMonitor
          annotations: {}
          ## The label to use to retrieve the job name from
          ## jobLabel: "app.kubernetes.io/name"
          namespace: ""
          namespaceSelector: {}
          ## Default: scrape .Release.Namespace or namespaceOverride only
          ## To scrape all, use the following:
          ## namespaceSelector:
          ##   any: true
          scrapeInterval: 30s
          # honorLabels: true
          targetLabels: []
          relabelings: []
          metricRelabelings: []
controller.wallarm.container_name.extraEnvs¶
Extra environment variables to be passed to the Docker containers utilized by the solution. Supported starting from the release 4.10.6.
The example below shows how to pass the https_proxy and no_proxy variables to Docker containers. This setup directs outgoing HTTPS traffic through a designated proxy, while local traffic bypasses it. Such configuration is crucial in environments where external communications, like those with the Wallarm API, must pass through a proxy for security reasons.
controller:
  wallarm:
    apiHost: api.wallarm.com
    enabled: "true"
    token:  <API_TOKEN>
    init:
      extraEnvs:
        - name: https_proxy
          value: https://1.1.1.1:3128
validation.enableCel¶
Enables validation of Ingress resources using Validating Admission Policies.
This feature requires:
-  Kubernetes v1.30 or above 
-  Wallarm Helm chart version 5.3.14+ (5.x series) or 6.0.2+ 
When set to true, the Helm chart deploys:
-  ValidatingAdmissionPolicy ingress-safety-netwhich defines the CEL rules for allIngressresources (networking.k8s.io/v1)
-  ValidatingAdmissionPolicyBinding ingress-safety-net-bindingwhich executes those rulescluster-widewith the actionDeny
The default rules catch common misconfigurations typically detected by nginx -t:
-  Forbidding wildcard hosts (e.g., *.example.com)
-  Ensuring all host values are unique within an Ingress 
-  Verifying that each HTTP path includes a service name and port 
-  Requiring that all paths start with /
-  Validating formats of common size/time/boolean annotations ( proxy-buffer-size,proxy-read-timeout,ssl-redirect)
Validation occurs during Ingress creation or update, rejecting misconfigured resources.
This mechanism replaces template testing, which is currently disabled in the upstream NGINX Ingress Controller due to CVE-2025-1974.
Default value: false
Customizing validation rules
You can extend or modify the default set of rules using Common Expression Language (CEL):
-  Download the Wallarm Helm chart of the required version. 
-  Modify the rules in the templates/ingress-safety-vap.yamlfile.
-  Deploy the chart from the modified directory according to the standard deployment instructions. 
validation.forbidDangerousAnnotations¶
Enables an additional CEL rule that blocks explicitly dangerous NGINX Ingress annotations server-snippet and configuration-snippet.
Allowing all snippet annotations widens the attack surface: any user with permissions to create or update Ingresses can introduce insecure or unstable behavior.
This feature requires:
-  Kubernetes v1.30 or above 
-  Wallarm Helm chart version 6.3.0+ 
-  validation.enableCelis set totrue
Behavior in Node 6.2.0-
In Node versions 6.2.0 and earlier, explicitly dangerous server-snippet and configuration-snippet are blocked by default when validation.enableCel is true.
Default value: false (blocking explicitly dangerous annotations server-snippet and configuration-snippet is disabled)
Global Controller Settings¶
Implemented via ConfigMap.
Besides the standard ones, the following additional parameters are supported:
Ingress Annotations¶
These annotations are used for setting up parameters for processing individual instances of Ingress.
Besides the standard ones, the following additional annotations are supported:
-  nginx.ingress.kubernetes.io/wallarm-mode, default: "off"
Applying annotation to the Ingress resource¶
To apply the settings to your Ingress, please use the following command:
kubectl annotate --overwrite ingress <YOUR_INGRESS_NAME> -n <YOUR_INGRESS_NAMESPACE> <ANNOTATION_NAME>=<VALUE>
-  <YOUR_INGRESS_NAME>is the name of your Ingress
-  <YOUR_INGRESS_NAMESPACE>is the namespace of your Ingress
-  <ANNOTATION_NAME>is the name of the annotation from the list above
-  <VALUE>is the value of the annotation from the list above
Annotation examples¶
Configuring the blocking page and error code¶
The annotation nginx.ingress.kubernetes.io/wallarm-block-page is used to configure the blocking page and error code returned in the response to the request blocked for the following reasons:
-  Request contains malicious payloads of the following types: input validation attacks, vpatch attacks, or attacks detected based on regular expressions. 
-  Request containing malicious payloads from the list above is originated from graylisted IP address and the node filters requests in the safe blocking mode. 
-  Request is originated from the denylisted IP address. 
For example, to return the default Wallarm blocking page and the error code 445 in the response to any blocked request:
kubectl annotate ingress <YOUR_INGRESS_NAME> -n <YOUR_INGRESS_NAMESPACE> nginx.ingress.kubernetes.io/wallarm-block-page="&/usr/share/nginx/html/wallarm_blocked.html response_code=445 type=attack,acl_ip,acl_source"
More details on the blocking page and error code configuration methods →
Managing libdetection mode¶
libdetection default mode
The default mode of the libdetection library is on (enabled).
You can control the libdetection mode using one of the options:
-  Applying the following nginx.ingress.kubernetes.io/server-snippetannotation to the Ingress resource:kubectl annotate --overwrite ingress <YOUR_INGRESS_NAME> -n <YOUR_INGRESS_NAMESPACE> nginx.ingress.kubernetes.io/server-snippet="wallarm_enable_libdetection off;"Available values of wallarm_enable_libdetectionareon/off.
-  Pass the parameter controller.config.server-snippetto the Helm chart:helm install --set controller.config.server-snippet='wallarm_enable_libdetection off;' <INGRESS_CONTROLLER_RELEASE_NAME> wallarm/wallarm-ingress -n <KUBERNETES_NAMESPACE>There are also other parameters required for correct Ingress controller installation. Please pass them in the --setoption too.Available values of wallarm_enable_libdetectionareon/off.