- Published on
NGINX add_header
The add_header directive in NGINX is used to add HTTP response headers to responses sent to clients.
🔹 Basic Syntax
add_header name value [always];
- name → Header name (e.g.,
X-Frame-Options) - value → Header value
- always (optional) → Ensures header is added even on non-2xx responses
🔹 Example 1: Add Security Headers
server {
listen 80;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
}
🔹 Example 2: Add CORS Header
location /api/ {
add_header Access-Control-Allow-Origin "*";
}
🔹 Important: Behavior Without always
By default, add_header only applies to successful responses:
- 200
- 201
- 204
- 206
- 301
- 302
- 303
- 304
- 307
- 308
If your backend returns a 401, 403, or 500, the header will NOT be added unless you use always.
Example:
add_header X-Test "value" always;
This is especially important for:
- CORS headers (for 401/403 errors)
- Security headers
- Custom debugging headers
🔹 Example 3: Add Header for All Responses (Recommended for CORS)
location / {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
}
🔹 Inheritance Behavior (Very Important)
NGINX does NOT merge add_header directives automatically.
If you define add_header in a location block, it overrides headers defined in server or http.
Example:
server {
add_header X-Global "1";
location /api {
add_header X-API "2"; # X-Global will NOT be included here
}
}
To keep both, you must repeat them:
location /api {
add_header X-Global "1";
add_header X-API "2";
}
🔹 Common AWS / GCP Use Case
If you're using:
- AWS ALB + NGINX
- GCP Load Balancer + NGINX
- API Gateway behind NGINX
- Cloud Armor in front
You often need:
add_header Access-Control-Allow-Origin "*" always;
Otherwise, browsers will block 401/403 responses.
🔹 Debugging Tip
To verify headers:
curl -I https://example.com
Or for error responses:
curl -I -X OPTIONS https://example.com/api