Working with Headers
1. Adding Custom Headers
| Directive | Values | Description |
|---|---|---|
| add_header | name value [always] |
Adds a custom header to the response. The always parameter ensures it's added even for error responses. |
| add_header | name value [always] |
Example usage with always: |
Example: Adding a Custom Header
location / {
add_header X-Custom-Header "MyValue";
add_header X-Another-Header "AnotherValue" always;
}
Note: The
add_header directive is processed after the response body is generated, so it won't affect headers added by subrequests or internal redirects.
2. Removing Headers
| Directive | Description | Example |
|---|---|---|
| proxy_hide_header | Hides a header from the response sent to the client | proxy_hide_header X-Powered-By; |
| proxy_ignore_headers | Prevents Nginx from processing specified headers | proxy_ignore_headers X-Powered-By Set-Cookie; |
| add_header | Adds a header to the response, can be used with always to override |
add_header X-Frame-Options "DENY" always; |
Note: The
proxy_hide_header directive is often used to remove server-specific headers like X-Powered-By for security reasons.3. Setting Response Headers
| Directive | Description | Example |
|---|---|---|
| add_header | Adds a custom header to the response | add_header X-Custom-Header "value"; |
| add_header | Can include a replace parameter to replace existing headers |
add_header Cache-Control "no-cache" always; |
| expires | Sets the Expires header for static content |
expires 1d; |
Example: Adding a Custom Header
location /api/ {
add_header X-API-Version "1.0";
proxy_pass http://backend;
}
Example: Setting Cache Control
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
4. Using Always Parameter
| Directive | Parameters | Description |
|---|---|---|
| add_header | name, value, always |
Adds a header to the response. When always is specified, the header is added even if the response status code indicates an error (e.g., 404, 500). |
| proxy_hide_header | header, always |
Hides a header from the response. When always is specified, it hides the header even for error responses. |
| proxy_ignore_headers | header, always |
Specifies headers to ignore from the proxied server. When always is specified, it ignores headers even in error responses. |
Example: Using proxy_hide_header with always
location /api/ {
proxy_hide_header X-Internal-Header always;
}
5. Configuring CORS Headers
| Directive | Description | Values | Notes |
|---|---|---|---|
| add_header | Adds a custom header to the response | Access-Control-Allow-Origin * |
Used to configure CORS headers |
| add_header | Allows credentials in CORS requests | Access-Control-Allow-Credentials true |
Must be set to true to allow credentials |
| add_header | Specifies allowed headers in preflight requests | Access-Control-Allow-Headers "Content-Type, Authorization" |
Comma-separated list of allowed headers |
| add_header | Specifies allowed HTTP methods in preflight requests | Access-Control-Allow-Methods "GET, POST, PUT, DELETE" |
Comma-separated list of allowed methods |
| add_header | Sets the maximum age of preflight requests | Access-Control-Max-Age 86400 |
Time in seconds to cache preflight requests |
Example: Basic CORS Configuration
location /api/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
Example: CORS with Credentials
location /api/ {
add_header Access-Control-Allow-Origin https://example.com;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
6. Setting Security Headers
| Header | Value Example | Description |
|---|---|---|
| Content-Security-Policy | default-src 'self'; script-src 'self' https://apis.google.com; object-src 'none' |
Prevents cross-site scripting (XSS) and other code injection attacks by controlling resources that can be loaded. |
| X-Content-Type-Options | nosniff |
Prevents browsers from interpreting files as a different MIME type than what is declared in the Content-Type header. |
| X-Frame-Options | DENY |
Prevents the page from being displayed in a frame or iframe, protecting against clickjacking attacks. |
| X-XSS-Protection | 1; mode=block |
Enables the browser's built-in XSS filter to block reflected XSS attacks. |
| Strict-Transport-Security | max-age=31536000; includeSubDomains |
Enforces secure (HTTPS) connections to the server, preventing downgrade attacks. |
Example: Setting Security Headers in Nginx
server {
listen 443 ssl;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://apis.google.com; object-src 'none'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
root /var/www/html;
index index.html;
}
}
7. Adding Content Security Policy
| Directive | Description | Values | Notes |
|---|---|---|---|
| content_security_policy | Defines the Content Security Policy (CSP) header | default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' |
Must be a valid CSP policy string |
| content_security_policy_report_only | Enforces CSP in report-only mode | default-src 'self'; report-uri /csp-report |
Does not block resources, only reports violations |
Example: Setting CSP Header
server {
listen 80;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';";
}
Example: CSP Report Only Mode
server {
listen 80;
server_name example.com;
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report;";
}
8. Setting Referrer Policy
| Directive | Description | Values | Notes |
|---|---|---|---|
| referrer_policy | Controls the referrer information sent with requests | no-referrer, no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url |
Default is no-referrer-when-downgrade |
Example: Setting Referrer Policy
server {
listen 80;
server_name example.com;
location / {
referrer_policy strict-origin-when-cross-origin;
return 200 "Referrer Policy set";
}
}
9. Configuring Permissions Policy
| Directive | Description | Values | Notes |
|---|---|---|---|
| permissions_policy | Controls permissions for browser features | allow("geolocation") |
Define which features can be used |
| permissions_policy | Controls permissions for browser features | allow("camera") |
Define which features can be used |
Example: Setting Permissions Policy
server {
listen 80;
server_name example.com;
add_header Permissions-Policy "geolocation=(), camera=()";
location / {
root /var/www/html;
index index.html;
}
}
Note: The Permissions-Policy header allows fine-grained control over browser features like geolocation, camera, and microphone.
10. Using Header Variables
| Variable | Description | Example Value |
|---|---|---|
| $arg_<name> | Query string parameter value | 123 |
| $http_<header> | HTTP request header value | application/json |
| $sent_http_<header> | HTTP response header value | text/html |
| $cookie_<name> | Cookie value | session=abc123 |
| $request_time | Request processing time in seconds | 0.045 |
| $status | Response status code | 200 |
Example: Setting a Custom Header Based on a Query Parameter
location / {
add_header X-User-ID $arg_user_id;
}
Example: Using a Request Header to Modify Response
location / {
proxy_pass http://backend;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}
11. Proxying Request Headers
| Directive | Description | Default | Example |
|---|---|---|---|
| proxy_pass_request_headers | Controls whether request headers are passed to the proxied server. | on | proxy_pass_request_headers off; |
| proxy_set_header | Sets a header to be passed to the proxied server. | None | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
| proxy_hide_header | Hides a header from the response received from the proxied server. | None | proxy_hide_header X-Powered-By; |
Example: Setting Forwarded Headers
location / {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Note: The
X-Forwarded-For header is commonly used to identify the originating IP address of a client connecting through an HTTP proxy or load balancer.
12. Understanding Header Inheritance
| Header | Inheritance Scope | Description |
|---|---|---|
| Authorization | Internal | Not inherited across internal redirects; must be re-sent if needed. |
| Content-Type | Internal | Not inherited; must be explicitly set for each response. |
| Host | Internal | Inherited from the original request; can be overridden in proxy settings. |
| Referer | Internal | Inherited from the original request; can be stripped or modified by proxy settings. |
| User-Agent | Internal | Inherited from the original request; can be overridden or removed by proxy settings. |
| X-Forwarded-For | Internal | Not inherited; used to track client IP through proxies. |
| X-Real-IP | Internal | Not inherited; used to pass the real client IP through proxies. |
Note: Header inheritance behavior can vary depending on how Nginx is configured and whether it's handling internal redirects or proxying requests.