Configure NGINX Ingress globally via the nginx-configuration ConfigMap, or per Ingress via annotations.
See the NGINX Ingress ConfigMap documentation and the NGINX Ingress annotations documentation.
ConfigMap
The nginx-configuration ConfigMap sets global defaults for all Ingresses managed by the NGINX Ingress controller.
Edit the ConfigMap
kubectl edit cm -n kube-system nginx-configuration
Default configuration
The following ConfigMap shows ACK defaults. Unlisted fields inherit upstream ingress-nginx defaults.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: <namespace> # Default: kube-system
labels:
app: ingress-nginx
data:
log-format-upstream: '$remote_addr - [$remote_addr] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id $host [$proxy_alternative_upstream_name]'
proxy-body-size: 20m
proxy-connect-timeout: "10"
max-worker-connections: "65536"
enable-underscores-in-headers: "true"
reuse-port: "true"
worker-cpu-affinity: "auto"
server-tokens: "false"
ssl-redirect: "false"
allow-backend-server-header: "true"
ignore-invalid-headers: "true"
generate-request-id: "true"
upstream-keepalive-timeout: "900"
Field descriptions
| Field | Default | Description |
|---|---|---|
log-format-upstream |
(see above) | Log format for upstream requests. If you change this field, also update the kube-system/k8s-nginx-ingress AliyunLogConfig and the log collection format in Simple Log Service (SLS). See Diagnose NGINX Ingress controller access logs in Simple Log Service. |
proxy-body-size |
20m |
Maximum size of the client request body. Maps to client_max_body_size. |
proxy-connect-timeout |
10 |
Timeout (seconds) for establishing a connection with a proxy server. Maximum: 75. For gRPC, also set grpc_connect_timeout. See proxy_connect_timeout. |
max-worker-connections |
65536 |
Maximum simultaneous connections per worker process. Set to 0 to use the max-worker-open-files value instead. |
enable-underscores-in-headers |
true |
Whether to allow underscores (_) in request header names. |
reuse-port |
true |
Creates a separate listening socket per worker using SO_REUSEPORT, distributing incoming connections across workers. |
worker-cpu-affinity |
auto |
Binds each worker process to an available CPU core. Useful for high-performance workloads. |
server-tokens |
false |
When true, includes the NGINX version in the Server response header and error pages. Set to false to suppress version disclosure. |
ssl-redirect |
false |
When true, globally redirects HTTP to HTTPS (301) for all servers with a TLS certificate. |
allow-backend-server-header |
true |
When true, passes the Server header from the backend instead of a generic NGINX string. |
ignore-invalid-headers |
true |
Whether to ignore invalid header fields in requests. |
generate-request-id |
true |
When true, generates a random X-Request-ID value for requests that do not already include this header. |
upstream-keepalive-timeout |
900 (ACK) / 60 (open source) |
Idle timeout (seconds) for keep-alive connections to upstream servers. Maps to the NGINX keepalive_timeout directive. |
Annotations
Add annotations to individual Ingress resources to override or extend global ConfigMap settings.
See the NGINX Ingress annotations documentation.
Load balancing
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/load-balance |
round_robin | ewma |
Load balancing algorithm for backend services. round_robin (default) suits most workloads. ewma (Peak Exponential Weighted Moving Average) is better for latency-sensitive applications. |
nginx.ingress.kubernetes.io/upstream-hash-by |
string | Enables consistent hashing. The value is the hash key variable. Examples: $request_uri, $request_uri$host, ${request_uri}-text-value. Adding or removing nodes only migrates a subset of routes. |
Example: consistent hashing by request URI
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-test
namespace: default
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <your-service-name>
port:
number: <your-service-port>
For Kubernetes clusters earlier than 1.22, useapiVersion: networking.k8s.io/v1beta1and theserviceName/servicePortfields underbackend.
Cookie affinity
| Annotation | Type | Default | Description |
|---|---|---|---|
nginx.ingress.kubernetes.io/affinity |
cookie |
— | Affinity type. Only cookie is supported. |
nginx.ingress.kubernetes.io/affinity-mode |
balanced | persistent |
balanced |
balanced distributes requests across instances. persistent always routes a client to the same backend instance, ensuring session consistency. |
nginx.ingress.kubernetes.io/session-cookie-name |
string | — | Cookie name used as the hash key for session routing. |
nginx.ingress.kubernetes.io/session-cookie-path |
string | / |
Path attribute set on the session cookie. Does not support regular expressions when nginx.ingress.kubernetes.io/use-regex is true. |
nginx.ingress.kubernetes.io/session-cookie-max-age |
integer (seconds) | — | Max-Age attribute of the session cookie (seconds). |
nginx.ingress.kubernetes.io/session-cookie-expires |
integer (seconds) | — | Cookie lifetime (seconds). Sets the Expires attribute. |
Example: cookie-based session affinity
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
ingressClassName: nginx
rules:
- host: stickyingress.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: http-svc
port:
number: 80
Redirects
| Annotation | Type | Default | Description |
|---|---|---|---|
nginx.ingress.kubernetes.io/ssl-redirect |
"true" | "false" |
— | Redirects HTTP to HTTPS for this Ingress when it has a TLS certificate. See HTTP-to-HTTPS redirect. |
nginx.ingress.kubernetes.io/force-ssl-redirect |
"true" | "false" |
"false" |
Forces HTTP-to-HTTPS redirect even without a TLS certificate. |
nginx.ingress.kubernetes.io/permanent-redirect |
URL | — | Destination URL for a permanent redirect. Must include a scheme (http:// or https://). |
nginx.ingress.kubernetes.io/permanent-redirect-code |
integer | 301 |
HTTP status code for the permanent redirect. |
nginx.ingress.kubernetes.io/temporal-redirect |
URL | — | Destination URL for a temporary redirect. Must include a scheme (http:// or https://). |
nginx.ingress.kubernetes.io/app-root |
path | — | Redirects requests to / to the specified application root path. |
Example: permanent redirect from `foo.com` to `bar.com`
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/permanent-redirect: "https://bar.com"
spec:
ingressClassName: nginx
rules:
- host: foo.com
http:
paths:
- path: "/"
pathType: ImplementationSpecific
backend:
service:
name: httpbin
port:
number: 8000
Rewrites
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/rewrite-target |
string | Destination path for the rewrite. Supports capture groups. See Configure URL redirection. |
nginx.ingress.kubernetes.io/upstream-vhost |
string | Rewrites the Host header sent to the upstream service. |
Example: rewrite the `Host` header to `test.com` for requests to `example.com/test`
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "test.com"
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /test
pathType: ImplementationSpecific
backend:
service:
name: demo-service
port:
number: 80
Throttling
Limit request rates and concurrent connections per client IP to protect backend services from traffic spikes.
| Annotation | Type | Default | Description |
|---|---|---|---|
nginx.ingress.kubernetes.io/limit-connections |
integer | — | Maximum concurrent connections per IP. Excess requests receive 503. |
nginx.ingress.kubernetes.io/limit-rate |
integer (KB) | — | Maximum data transmitted per connection per second (KB). Set to 0 to disable. Requires proxy buffering to be enabled. |
nginx.ingress.kubernetes.io/limit-rps |
integer | — | Maximum requests per second per IP address. Requests exceeding the burst limit (rate × limit-burst-multiplier) return a limit-req-status-code error (503 by default). |
nginx.ingress.kubernetes.io/limit-rpm |
integer | — | Maximum requests per minute per IP address. Same burst behavior as limit-rps. |
nginx.ingress.kubernetes.io/limit-burst-multiplier |
integer | 5 |
Burst rate limit multiplier. |
nginx.ingress.kubernetes.io/limit-whitelist |
CIDR list | — | Comma-separated CIDR blocks excluded from throttling. |
Example: rate limiting with an IP whitelist
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/limit-rate: "100K"
nginx.ingress.kubernetes.io/limit-rps: "1"
nginx.ingress.kubernetes.io/limit-rpm: "30"
nginx.ingress.kubernetes.io/limit-whitelist: "10.1.10.100"
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-svc
port:
number: 80
Fallback
Route traffic to a backup service when the primary backend is unavailable.
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/default-backend |
string | Fallback service when no backend nodes are available. Configure globally via the Add-ons page in the ACK console. |
nginx.ingress.kubernetes.io/custom-http-errors |
HTTP status codes | Works with default-backend. NGINX forwards requests to the fallback service when the backend returns a listed status code. The path is rewritten to /. Overrides the global custom-http-errors ConfigMap setting. |
Canary releases
Implement canary releases and blue-green deployments. See Use the NGINX Ingress controller to implement canary releases and blue-green deployments.
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/canary |
"true" | "false" |
Specifies whether to enable canary releases. |
nginx.ingress.kubernetes.io/canary-by-header |
string | Header key for traffic splitting. |
nginx.ingress.kubernetes.io/canary-by-header-value |
string | Exact-match value for the header key. Routes matching requests to the canary. |
nginx.ingress.kubernetes.io/canary-by-header-pattern |
regex | Regular expression match for the header value. |
nginx.ingress.kubernetes.io/canary-by-cookie |
string | Cookie key used for traffic splitting. |
nginx.ingress.kubernetes.io/canary-weight |
integer | Percentage of traffic routed to the canary (0–canary-weight-total). |
nginx.ingress.kubernetes.io/canary-weight-total |
integer | Weight denominator for canary-weight. |
Timeout
Global timeout settings
Edit the nginx-configuration ConfigMap to set timeouts globally:
kubectl edit cm -n kube-system nginx-configuration
| Field | Default | Description |
|---|---|---|
proxy-connect-timeout |
5s |
Proxy connection timeout. Maximum: 75s. |
proxy-read-timeout |
60s |
Timeout between consecutive proxy reads (not total response time). |
proxy-send-timeout |
60s |
Timeout between consecutive proxy writes (not total transmission time). |
proxy-stream-next-upstream-timeout |
600s |
Maximum time to pass a connection to the next upstream server. Set to 0 for no limit. |
proxy-stream-timeout |
600s |
Idle timeout on client or proxy connections. Closes if no data is transferred. |
upstream-keepalive-timeout |
900s (ACK) / 60s (open source) |
Idle timeout for keep-alive connections to upstream servers. |
worker-shutdown-timeout |
240s |
Graceful shutdown timeout. |
proxy-protocol-header-timeout |
5s |
Timeout for receiving the PROXY protocol header. Prevents TLS passthrough handlers from blocking on broken connections. |
ssl-session-timeout |
10m |
SSL session cache lifetime. Each entry uses approximately 0.25 MB. |
client-body-timeout |
60s |
Timeout for reading the client request body. |
client-header-timeout |
60s |
Timeout for reading the client request headers. |
Per-Ingress timeout settings
Override global timeouts for specific Ingresses with these annotations:
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/proxy-connect-timeout |
Proxy connection timeout. |
nginx.ingress.kubernetes.io/proxy-send-timeout |
Proxy send timeout. |
nginx.ingress.kubernetes.io/proxy-read-timeout |
Proxy read timeout. |
nginx.ingress.kubernetes.io/proxy-request-buffering |
Request buffering mode. on: buffer the full request before forwarding (HTTP/1.1 chunked requests are always buffered). off: stream request data directly; no retry on transmission errors. |
CORS
Enable cross-origin resource sharing (CORS) for browser requests. See Configure CORS on NGINX Ingresses.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/enable-cors |
Enables CORS for this Ingress. |
nginx.ingress.kubernetes.io/cors-allow-origin |
Allowed origins for CORS requests. |
nginx.ingress.kubernetes.io/cors-allow-methods |
Allowed request methods, including GET, POST, and PUT. |
nginx.ingress.kubernetes.io/cors-allow-headers |
Allowed request headers. |
nginx.ingress.kubernetes.io/cors-expose-headers |
Response headers exposed to the browser. |
nginx.ingress.kubernetes.io/cors-allow-credentials |
Whether to allow credentials (cookies, authorization headers) in CORS requests. |
nginx.ingress.kubernetes.io/cors-max-age |
CORS preflight cache duration (seconds). |
Retry policies
| Annotation | Default | Description |
|---|---|---|
nginx.ingress.kubernetes.io/proxy-next-upstream-tries |
3 |
Retry count when conditions are met. |
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout |
— | Timeout (seconds) for the entire retry sequence. No default (unlimited). |
nginx.ingress.kubernetes.io/proxy-next-upstream |
— | Retry conditions. Separate multiple values with spaces. Valid values: error (connection failure), timeout (timeout), invalid_response (invalid status code), http_500, http_502, http_503, http_504, http_403, http_404, http_429, off (disable retries). |
IP address-based access control
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/whitelist-source-range |
CIDR list | IP allowlist. Only listed IP addresses or CIDR blocks are allowed. Comma-separated. |
nginx.ingress.kubernetes.io/denylist-source-range |
CIDR list | IP blocklist. Listed IP addresses or CIDR blocks are denied. Comma-separated. |
Example: allow only a specific IP address
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/whitelist-source-range: "10.1.10.2"
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-svc
port:
number: 80
To apply globally, set whitelist-source-range in the nginx-configuration ConfigMap.
Traffic mirroring
Duplicate production requests to a shadow environment for testing without affecting live traffic. See Use an Ingress controller to mirror network traffic.
| Annotation | Type | Description |
|---|---|---|
nginx.ingress.kubernetes.io/mirror-target |
URL | Mirror destination. Accepts a Service IP address or external URL. Use $request_uri to append the original request URI. Example: https://test.env.com/$request_uri. |
nginx.ingress.kubernetes.io/mirror-request-body |
"true" | "false" |
Whether to mirror the request body. |
nginx.ingress.kubernetes.io/mirror-host |
string | Host header sent with mirrored requests. |
Security protection
Configure TLS encryption between clients and the NGINX Ingress controller, and between the controller and backend services. See NGINX Ingress controller encryption.
Client-to-gateway encryption
| Annotation | Scope | Description |
|---|---|---|
nginx.ingress.kubernetes.io/ssl-cipher |
Domain | TLS cipher suites (comma-separated). Takes effect only for TLS 1.0–1.2 handshakes. Default cipher suites: ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-SHA, ECDHE-RSA-AES128-SHA, AES128-GCM-SHA256, AES128-SHA, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-SHA, ECDHE-RSA-AES256-SHA, AES256-GCM-SHA384, AES256-SHA. |
nginx.ingress.kubernetes.io/auth-tls-secret |
Domain | CA certificate Secret for verifying client certificates in mTLS. Must include a ca.crt file with the complete CA chain. |
Gateway-to-backend encryption
| Annotation | Scope | Description |
|---|---|---|
nginx.ingress.kubernetes.io/proxy-ssl-secret |
Service | Client certificate Secret presented to backends. Must be PEM format with tls.crt (client certificate), tls.key (private key), and ca.crt (trusted CA certificate). Specify as "namespace/secretName". |
nginx.ingress.kubernetes.io/proxy-ssl-name |
Service | Server Name Indication (SNI) value for the TLS handshake with the backend. |
nginx.ingress.kubernetes.io/proxy-ssl-server-name |
Service | Enables or disables SNI for the TLS handshake with the backend. |
Security authentication
Restrict access with Basic Authentication. Only authenticated requests reach backend services.
| Annotation | Scope | Description |
|---|---|---|
nginx.ingress.kubernetes.io/auth-type |
Ingress | Authentication type. Set to basic. |
nginx.ingress.kubernetes.io/auth-secret |
Ingress | Credential Secret name. Format: namespace/secretName. |
nginx.ingress.kubernetes.io/auth-secret-type |
Ingress | Format of the Secret data. auth-file: the auth key has newline-separated username:password entries. auth-map: keys are usernames, values are passwords. |
nginx.ingress.kubernetes.io/auth-realm |
Ingress | Authentication realm shown to the client when prompting for credentials. |
Set up Basic Authentication
-
Generate a password file with
htpasswd:htpasswd -c auth jokerVerify the file:
cat auth # Expected output: joker:$apr1$R.G4krs/$hh0mX8xe4A3lYKMjvlVs1/ -
Create a Secret from the password file:
kubectl create secret generic basic-auth --from-file=auth -
Add the annotations to your Ingress:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth spec: ingressClassName: nginx rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: backend-svc port: number: 80