Repository: nginx/kubernetes-ingress

Issue:
Allow `StartupProbe` to be configured via helm
**Is your feature request related to a problem? Please describe.**

User would like to configured their backend application with a health check before the pod starts

Problem definition:
- Bad config ingress is applied to a running Nginx Ingress Pod.
- Bad could be just a snippet that is not correct, even just missing a semi-column ( see attached example )
- Ingress Pod continues working.
- Ingress Pod fails is restarted or replaced
- No configuration is being loaded but the readiness probes is successful

**Describe the solution you'd like**
I would like to be able to configure a StartupProbe for the Ingress Controller. I need to be confident that the `/etc/nginx/conf.d/` directory was created successfully upon pod restart

**Describe alternatives you've considered**
Right now, we create dummy ingress that listens on a different port ( in our example 9999 ) and always responds with 200 OK and have pointed the readiness probe to this port.
Since this dummy ingress is part of the conf.d it will fail also when the configuration is loaded at startup and therefor the probs will fail.


Discussion:
@github-actions: Hi @shaun-nx thanks for reporting! 

 Be sure to check out the [docs](https://docs.nginx.com/nginx-ingress-controller) and the [Contributing Guidelines](https://github.com/nginx/kubernetes-ingress/blob/main/CONTRIBUTING.md) while you wait for a human to take a look at this :slightly_smiling_face:

 Cheers!

Solution patch:
diff --git a/charts/nginx-ingress/templates/controller-daemonset.yaml b/charts/nginx-ingress/templates/controller-daemonset.yaml
index 653ef4eb9..17e8729cb 100644
--- a/charts/nginx-ingress/templates/controller-daemonset.yaml
+++ b/charts/nginx-ingress/templates/controller-daemonset.yaml
@@ -86,6 +86,12 @@ spec:
 {{- if .Values.controller.readyStatus.enable }}
         - name: readiness-port
           containerPort: {{ .Values.controller.readyStatus.port }}
+{{- end }}
+{{- if .Values.controller.startupStatus.enable }}
+        - name: startup-port
+          containerPort: {{ .Values.controller.startupStatus.port }}
+{{- end }}
+{{- if .Values.controller.readyStatus.enable }}
         readinessProbe:
           httpGet:
             path: /nginx-ready
@@ -93,6 +99,17 @@ spec:
           periodSeconds: 1
           initialDelaySeconds: {{ .Values.controller.readyStatus.initialDelaySeconds }}
 {{- end }}
+{{- if .Values.controller.startupStatus.enable }}
+        startupProbe:
+          httpGet:
+            path: {{ .Values.controller.startupStatus.path }}
+            port: startup-port
+          initialDelaySeconds: {{ .Values.controller.startupStatus.initialDelaySeconds }}
+          periodSeconds: {{ .Values.controller.startupStatus.periodSeconds }}
+          timeoutSeconds: {{ .Values.controller.startupStatus.timeoutSeconds }}
+          successThreshold: {{ .Values.controller.startupStatus.successThreshold }}
+          failureThreshold: {{ .Values.controller.startupStatus.failureThreshold }}
+{{- end }}
 {{- if .Values.controller.securityContext }}
         securityContext:
 {{ toYaml .Values.controller.securityContext | indent 10 }}
diff --git a/charts/nginx-ingress/templates/controller-deployment.yaml b/charts/nginx-ingress/templates/controller-deployment.yaml
index 9f2c6bd1e..8d6077227 100644
--- a/charts/nginx-ingress/templates/controller-deployment.yaml
+++ b/charts/nginx-ingress/templates/controller-deployment.yaml
@@ -93,12 +93,29 @@ spec:
 {{- if .Values.controller.readyStatus.enable }}
         - name: readiness-port
           containerPort: {{ .Values.controller.readyStatus.port }}
+{{- end }}
+{{- if .Values.controller.startupStatus.enable }}
+        - name: startup-port
+          containerPort: {{ .Values.controller.startupStatus.port }}
+{{- end }}
+{{- if .Values.controller.readyStatus.enable }}
         readinessProbe:
           httpGet:
             path: /nginx-ready
             port: readiness-port
           periodSeconds: 1
           initialDelaySeconds: {{ .Values.controller.readyStatus.initialDelaySeconds }}
+{{- end }}
+{{- if .Values.controller.startupStatus.enable }}
+        startupProbe:
+          httpGet:
+            path: {{ .Values.controller.startupStatus.path }}
+            port: startup-port
+          initialDelaySeconds: {{ .Values.controller.startupStatus.initialDelaySeconds }}
+          periodSeconds: {{ .Values.controller.startupStatus.periodSeconds }}
+          timeoutSeconds: {{ .Values.controller.startupStatus.timeoutSeconds }}
+          successThreshold: {{ .Values.controller.startupStatus.successThreshold }}
+          failureThreshold: {{ .Values.controller.startupStatus.failureThreshold }}
 {{- end }}
         resources:
 {{ toYaml .Values.controller.resources | indent 10 }}
diff --git a/charts/nginx-ingress/values.schema.json b/charts/nginx-ingress/values.schema.json
index bbb6658e0..3cd6fe976 100644
--- a/charts/nginx-ingress/values.schema.json
+++ b/charts/nginx-ingress/values.schema.json
@@ -1758,6 +1758,98 @@
             }
           ]
         },
+        "startupStatus": {
+          "type": "object",
+          "default": {},
+          "title": "The startupStatus",
+          "required": [],
+          "properties": {
+            "enable": {
+              "type": "boolean",
+              "default": false,
+              "title": "Enable the startup probe",
+              "examples": [
+                true
+              ]
+            },
+            "port": {
+              "type": "integer",
+              "default": 0,
+              "title": "The port for the startup probe",
+              "examples": [
+                9999
+              ]
+            },
+            "path": {
+              "type": "string",
+              "default": "",
+              "title": "The path for the startup probe",
+              "examples": [
+                "/"
+              ]
+            },
+            "initialDelaySeconds": {
+              "type": "integer",
+              "default": 0,
+              "title": "Initial delay seconds for the startup probe",
+              "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.Probe/properties/initialDelaySeconds"
+            },
+            "periodSeconds": {
+              "type": "integer",
+              "default": 0,
+              "title": "Period seconds for the startup probe",
+              "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.Probe/properties/periodSeconds"
+            },
+            "timeoutSeconds": {
+              "type": "integer",
+              "default": 0,
+              "title": "Timeout seconds for the startup probe",
+              "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.Probe/properties/timeoutSeconds"
+            },
+            "successThreshold": {
+              "type": "integer",
+              "default": 0,
+              "title": "Success threshold for the startup probe",
+              "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.Probe/properties/successThreshold"
+            },
+            "failureThreshold": {
+              "type": "integer",
+              "default": 0,
+              "title": "Failure threshold for the startup probe",
+              "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.33.1/_definitions.json#/definitions/io.k8s.api.core.v1.Probe/properties/failureThreshold"
+            }
+          },
+          "allOf": [
+            {
+              "if": {
+                "properties": {
+                  "enable": {
+                    "const": true
+                  }
+                }
+              },
+              "then": {
+                "required": [
+                  "enable",
+                  "port",
+                  "path"
+                ]
+              }
+            }
+          ],
+          "examples": [
+            {
+              "enable": true,
+              "port": 9999,
+              "path": "/",
+              "initialDelaySeconds": 5,
+              "periodSeconds": 1,
+              "timeoutSeconds": 1,
+              "successThreshold": 1,
+              "failureThreshold": 30
+            }
+          ]
+        },
         "enableLatencyMetrics": {
           "type": "boolean",
           "default": false,
diff --git a/charts/nginx-ingress/values.yaml b/charts/nginx-ingress/values.yaml
index 5557e20b8..e62b5fa59 100644
--- a/charts/nginx-ingress/values.yaml
+++ b/charts/nginx-ingress/values.yaml
@@ -566,6 +566,32 @@ controller:
     ## The number of seconds after the Ingress Controller pod has started before readiness probes are initiated.
     initialDelaySeconds: 0
 
+  startupStatus:
+
+    ## Enable the startup probe.
+    enable: false
+
+    # ## Set the port where the startup endpoint is exposed. This is a required value if startupStatus.enable is true.
+    # port: 9999
+
+    # ## path to the startup endpoint. This is a required value if startupStatus.enable is true.
+    # path: /
+
+    # ## The number of seconds after the Ingress Controller pod has started before startup probes are initiated.
+    # initialDelaySeconds: 5
+
+    # ## The number of seconds between each startup probe.
+    # periodSeconds: 1
+
+    # ## The number of seconds after which the startup probe times out.
+    # timeoutSeconds: 1
+
+    # ## The number of seconds after which the startup probe is considered successful.
+    # successThreshold: 1
+
+    # ## The number of seconds after which the startup probe is considered failed.
+    # failureThreshold: 30
+
   ## Enable collection of latency metrics for upstreams. Requires prometheus.create.
   enableLatencyMetrics: false
 
diff --git a/examples/ingress-resources/startup-probe/README.md b/examples/ingress-resources/startup-probe/README.md
new file mode 100644
index 000000000..a747b4407
--- /dev/null
+++ b/examples/ingress-resources/startup-probe/README.md
@@ -0,0 +1,66 @@
+# Startup Probe Configuration for NGINX Ingress Controller
+
+This example demonstrates how to configure Kubernetes startup probes for the NGINX Ingress Controller using a dedicated endpoint that always returns HTTP 200.
+
+## Configuration
+
+### 1. Deploy the Always-200 Ingress
+
+Apply the startup probe Ingress resource that creates a dedicated endpoint:
+
+```shell
+kubectl apply -f startup-probe-ingress.yaml
+```
+
+This Ingress uses `nginx.org/server-snippets` to:
+
+- Listen on port 9999 (dedicated startup probe port)
+- Always return HTTP 200 with "ok" response
+
+### 2. Helm Chart Configuration
+
+Configure the startup probe in your Helm values:
+
+```yaml
+controller:
+  enableSnippets: true  # Enable custom NGINX configuration snippets
+  startupStatus:
+    enable: true
+    port: 9999
+    path: /
+    initialDelaySeconds: 5
+    periodSeconds: 1
+    timeoutSeconds: 1
+    successThreshold: 1
+    failureThreshold: 30
+```
+
+If enable is set to true then port and path are required.
+
+### 3. Install/Upgrade the Helm Chart
+
+Deploy or upgrade your NGINX Ingress Controller with startup probe enabled:
+
+```shell
+helm upgrade --install nginx-ingress nginx-stable/nginx-ingress \
+  --set controller.enableSnippets=true \
+  --set controller.startupStatus.enable=true \
+  --set controller.startupStatus.port=9999 \
+  --set controller.startupStatus.path=/ 
+```
+
+## Verification
+
+Check that the startup probe is working:
+
+```shell
+# Check pod status
+kubectl logs -n <namespace> <pod-name>
+>> "GET / HTTP/1.1" 200 2 "-" "kube-probe/1.33" "-"
+```
+
+```shell
+# Check startup probe endpoint (from within the pod)
+kubectl exec -it <pod-name> -n <namespace> -- curl http://localhost:9999/
+>>ok%
+```
diff --git a/examples/ingress-resources/startup-probe/startup-probe-ingress.yaml b/examples/ingress-resources/startup-probe/startup-probe-ingress.yaml
new file mode 100644
index 000000000..fbffb055b
--- /dev/null
+++ b/examples/ingress-resources/startup-probe/startup-probe-ingress.yaml
@@ -0,0 +1,21 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: always-200-ingress
+  annotations:
+    nginx.org/server-snippets: |
+      listen 9999;
+      return 200 'ok';
+spec:
+  ingressClassName: nginx
+  rules:
+    - http:
+        paths:
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: dummy-service
+                port:
+                  number: 80
+      host: example.com



Test patch:
diff --git a/charts/tests/__snapshots__/helmunit_test.snap b/charts/tests/__snapshots__/helmunit_test.snap
index 979f247d6..b822b8e24 100755
--- a/charts/tests/__snapshots__/helmunit_test.snap
+++ b/charts/tests/__snapshots__/helmunit_test.snap
@@ -9530,3 +9530,457 @@ metadata:
     app.kubernetes.io/version: "5.2.0"
     app.kubernetes.io/managed-by: Helm
 ---
+
+[TestHelmNICTemplate/startupStatusValid - 1]
+/-/-/-/
+# Source: nginx-ingress/templates/controller-serviceaccount.yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: startupstatus-nginx-ingress
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+/-/-/-/
+# Source: nginx-ingress/templates/controller-configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: startupstatus-nginx-ingress
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+data:
+  {}
+/-/-/-/
+# Source: nginx-ingress/templates/controller-leader-election-configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: startupstatus-nginx-ingress-leader-election
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+/-/-/-/
+# Source: nginx-ingress/templates/clusterrole.yaml
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: startupstatus-nginx-ingress
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - configmaps
+  - namespaces
+  - pods
+  - secrets
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - ""
+  resources:
+  - events
+  verbs:
+  - create
+  - patch
+  - list
+- apiGroups:
+  - ""
+  resources:
+  - services
+  verbs:
+  - get
+  - list
+  - watch
+  - create
+  - update
+  - patch
+  - delete
+- apiGroups:
+  - coordination.k8s.io
+  resources:
+  - leases
+  verbs:
+  - list
+  - watch
+- apiGroups:
+  - discovery.k8s.io
+  resources:
+  - endpointslices
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - networking.k8s.io
+  resources:
+  - ingresses
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - list
+- apiGroups:
+  - "apps"
+  resources:
+  - replicasets
+  - daemonsets
+  verbs:
+  - get
+- apiGroups:
+  - networking.k8s.io
+  resources:
+  - ingressclasses
+  verbs:
+  - get
+  - list
+- apiGroups:
+  - networking.k8s.io
+  resources:
+  - ingresses/status
+  verbs:
+  - update
+- apiGroups:
+  - k8s.nginx.org
+  resources:
+  - virtualservers
+  - virtualserverroutes
+  - globalconfigurations
+  - transportservers
+  - policies
+  verbs:
+  - list
+  - watch
+  - get
+- apiGroups:
+  - k8s.nginx.org
+  resources:
+  - virtualservers/status
+  - virtualserverroutes/status
+  - policies/status
+  - transportservers/status
+  verbs:
+  - update
+/-/-/-/
+# Source: nginx-ingress/templates/clusterrolebinding.yaml
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: startupstatus-nginx-ingress
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+subjects:
+- kind: ServiceAccount
+  name: startupstatus-nginx-ingress
+  namespace: default
+roleRef:
+  kind: ClusterRole
+  name: startupstatus-nginx-ingress
+  apiGroup: rbac.authorization.k8s.io
+/-/-/-/
+# Source: nginx-ingress/templates/controller-role.yaml
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: startupstatus-nginx-ingress
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+  namespace: default
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - configmaps
+  - pods
+  - secrets
+  - services
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+    - ""
+  resources:
+    - namespaces
+  verbs:
+    - get
+- apiGroups:
+  - ""
+  resources:
+  - pods
+  verbs:
+  - update
+- apiGroups:
+  - ""
+  resources:
+  - events
+  verbs:
+  - create
+  - patch
+  - list
+- apiGroups:
+  - coordination.k8s.io
+  resources:
+  - leases
+  resourceNames:
+  - startupstatus-nginx-ingress-leader-election
+  verbs:
+  - get
+  - update
+- apiGroups:
+  - coordination.k8s.io
+  resources:
+  - leases
+  verbs:
+  - create
+/-/-/-/
+# Source: nginx-ingress/templates/controller-rolebinding.yaml
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: startupstatus-nginx-ingress
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+  namespace: default
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: startupstatus-nginx-ingress
+subjects:
+- kind: ServiceAccount
+  name: startupstatus-nginx-ingress
+  namespace: default
+/-/-/-/
+# Source: nginx-ingress/templates/controller-service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+  name: startupstatus-nginx-ingress-controller
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+spec:
+  externalTrafficPolicy: Local
+  type: LoadBalancer
+  ports:
+  - port: 80
+    targetPort: 80
+    protocol: TCP
+    name: http
+    nodePort: 
+  - port: 443
+    targetPort: 443
+    protocol: TCP
+    name: https
+    nodePort: 
+  selector:
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+/-/-/-/
+# Source: nginx-ingress/templates/controller-deployment.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: startupstatus-nginx-ingress-controller
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: nginx-ingress
+      app.kubernetes.io/instance: startupstatus
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: nginx-ingress
+        app.kubernetes.io/instance: startupstatus
+      annotations:
+        prometheus.io/scrape: "true"
+        prometheus.io/port: "9113"
+        prometheus.io/scheme: "http"
+    spec:      
+      volumes: []
+      serviceAccountName: startupstatus-nginx-ingress
+      automountServiceAccountToken: true
+      securityContext:
+        seccompProfile:
+          type: RuntimeDefault
+      terminationGracePeriodSeconds: 30
+      hostNetwork: false
+      dnsPolicy: ClusterFirst
+      containers:
+      - image: nginx/nginx-ingress:5.2.0
+        name: nginx-ingress
+        imagePullPolicy: "IfNotPresent"
+        ports:
+        - name: http
+          containerPort: 80
+          protocol: TCP
+        - name: https
+          containerPort: 443
+          protocol: TCP
+        - name: prometheus
+          containerPort: 9113
+        - name: readiness-port
+          containerPort: 8081
+        - name: startup-port
+          containerPort: 9999
+        readinessProbe:
+          httpGet:
+            path: /nginx-ready
+            port: readiness-port
+          periodSeconds: 1
+          initialDelaySeconds: 0
+        startupProbe:
+          httpGet:
+            path: /
+            port: startup-port
+          initialDelaySeconds: 7
+          periodSeconds: 2
+          timeoutSeconds: 3
+          successThreshold: 1
+          failureThreshold: 5
+        resources:
+          requests:
+            cpu: 100m
+            memory: 128Mi
+        securityContext:
+          allowPrivilegeEscalation: false
+          readOnlyRootFilesystem: false
+          runAsUser: 101 #nginx
+          runAsNonRoot: true
+          capabilities:
+            drop:
+            - ALL
+            add:
+            - NET_BIND_SERVICE        
+        volumeMounts: []
+        env:
+        - name: POD_NAMESPACE
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.namespace
+        - name: POD_NAME
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.name
+        args:
+          
+          - -nginx-plus=false
+          - -nginx-reload-timeout=60000
+          - -enable-app-protect=false
+          - -enable-app-protect-dos=false
+          - -nginx-configmaps=$(POD_NAMESPACE)/startupstatus-nginx-ingress
+          - -ingress-class=nginx
+          - -health-status=false
+          - -health-status-uri=/nginx-health
+          - -nginx-debug=false
+          - -log-level=info
+          - -log-format=glog
+          - -nginx-status=true
+          - -nginx-status-port=8080
+          - -nginx-status-allow-cidrs=127.0.0.1
+          - -report-ingress-status
+          - -external-service=startupstatus-nginx-ingress-controller
+          - -enable-leader-election=true
+          - -leader-election-lock-name=startupstatus-nginx-ingress-leader-election
+          - -enable-prometheus-metrics=true
+          - -prometheus-metrics-listen-port=9113
+          - -prometheus-tls-secret=
+          - -enable-service-insight=false
+          - -service-insight-listen-port=9114
+          - -service-insight-tls-secret=
+          - -enable-custom-resources=true
+          - -enable-snippets=false
+          - -disable-ipv6=false
+          - -enable-tls-passthrough=false
+          - -enable-cert-manager=false
+          - -enable-oidc=false
+          - -enable-external-dns=false
+          - -default-http-listener-port=80
+          - -default-https-listener-port=443
+          - -ready-status=true
+          - -ready-status-port=8081
+          - -enable-latency-metrics=false
+          - -ssl-dynamic-reload=true
+          - -enable-telemetry-reporting=true
+          - -weight-changes-dynamic-reload=false
+/-/-/-/
+# Source: nginx-ingress/templates/controller-ingress-class.yaml
+apiVersion: networking.k8s.io/v1
+kind: IngressClass
+metadata:
+  name: nginx
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+spec:
+  controller: nginx.org/ingress-controller
+/-/-/-/
+# Source: nginx-ingress/templates/controller-configmap.yaml
+/-/-/-/
+/-/-/-/
+# Source: nginx-ingress/templates/controller-lease.yaml
+apiVersion: coordination.k8s.io/v1
+kind: Lease
+metadata:
+  name: startupstatus-nginx-ingress-leader-election
+  namespace: default
+  labels:
+    helm.sh/chart: nginx-ingress-2.3.0
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/instance: startupstatus
+    app.kubernetes.io/version: "5.2.0"
+    app.kubernetes.io/managed-by: Helm
+---
diff --git a/charts/tests/helmunit_test.go b/charts/tests/helmunit_test.go
index 208c7a6fe..94a802998 100644
--- a/charts/tests/helmunit_test.go
+++ b/charts/tests/helmunit_test.go
@@ -5,6 +5,7 @@ package test
 import (
 	"os"
 	"path/filepath"
+	"strings"
 	"testing"
 
 	"github.com/gkampitakis/go-snaps/snaps"
@@ -130,6 +131,11 @@ func TestHelmNICTemplate(t *testing.T) {
 			releaseName: "app-protect-waf-agentv2",
 			namespace:   "default",
 		},
+		"startupStatusValid": {
+			valuesFile:  "testdata/startupstatus-valid.yaml",
+			releaseName: "startupstatus",
+			namespace:   "default",
+		},
 	}
 
 	// Path to the helm chart we will test
@@ -155,3 +161,51 @@ func TestHelmNICTemplate(t *testing.T) {
 		})
 	}
 }
+
+// Test for negative cases where helm template rendering should fail
+func TestHelmNICTemplateNegative(t *testing.T) {
+	t.Parallel()
+
+	negativeTests := map[string]struct {
+		valuesFile       string
+		releaseName      string
+		namespace        string
+		expectedErrorMsg string
+	}{
+		"startupStatusInvalid": {
+			valuesFile:       "testdata/startupstatus-invalid.yaml",
+			releaseName:      "startupstatus-invalid",
+			namespace:        "default",
+			expectedErrorMsg: "port is required",
+		},
+	}
+
+	// Path to the helm chart we will test
+	helmChartPath, err := filepath.Abs("../nginx-ingress")
+	if err != nil {
+		t.Fatal("Failed to open helm chart path ../nginx-ingress")
+	}
+
+	for testName, tc := range negativeTests {
+		t.Run(testName, func(t *testing.T) {
+			options := &helm.Options{
+				KubectlOptions: k8s.NewKubectlOptions("", "", tc.namespace),
+			}
+
+			if tc.valuesFile != "" {
+				options.ValuesFiles = []string{tc.valuesFile}
+			}
+			_, err := helm.RenderTemplateE(t, options, helmChartPath, tc.releaseName, make([]string, 0))
+
+			if err == nil {
+				t.Fatalf("Expected helm template to fail for invalid configuration, but it succeeded")
+			}
+
+			if tc.expectedErrorMsg != "" && !strings.Contains(err.Error(), tc.expectedErrorMsg) {
+				t.Fatalf("Expected error to contain '%s', but got: %s", tc.expectedErrorMsg, err.Error())
+			}
+
+			t.Logf("Expected failure occurred: %s", err.Error())
+		})
+	}
+}
diff --git a/charts/tests/testdata/startupstatus-invalid.yaml b/charts/tests/testdata/startupstatus-invalid.yaml
new file mode 100644
index 000000000..d3902b462
--- /dev/null
+++ b/charts/tests/testdata/startupstatus-invalid.yaml
@@ -0,0 +1,4 @@
+controller:
+  startupStatus:
+    enable: true
+    # All other required values missing
diff --git a/charts/tests/testdata/startupstatus-valid.yaml b/charts/tests/testdata/startupstatus-valid.yaml
new file mode 100644
index 000000000..59c2a6dc2
--- /dev/null
+++ b/charts/tests/testdata/startupstatus-valid.yaml
@@ -0,0 +1,10 @@
+controller:
+  startupStatus:
+    enable: true
+    port: 9999
+    path: "/"
+    initialDelaySeconds: 7
+    periodSeconds: 2
+    timeoutSeconds: 3
+    successThreshold: 1
+    failureThreshold: 5