Nginx CORS Configuration
Configure CORS headers in Nginx using add_header directives, map blocks for multiple origins, and proper OPTIONS handling. Production-ready snippets included.
Detailed Explanation
Nginx CORS — Production Configuration
Nginx is commonly used as a reverse proxy in front of application servers. Adding CORS headers at the Nginx layer means your application code does not need to handle CORS at all.
Simple Configuration — Single Origin
server {
listen 443 ssl;
server_name api.example.com;
location /api/ {
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Max-Age 3600 always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Vary Origin always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend;
}
}
Multiple Origins with map
map $http_origin $cors_origin {
default "";
"https://app.example.com" "$http_origin";
"https://admin.example.com" "$http_origin";
"https://staging.example.com" "$http_origin";
}
server {
location /api/ {
if ($cors_origin != "") {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Vary Origin always;
}
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Max-Age 3600 always;
return 204;
}
proxy_pass http://backend;
}
}
The always Parameter
The always parameter ensures headers are added even for error responses (4xx, 5xx). Without it, Nginx only adds custom headers to 2xx and 3xx responses, which means CORS errors during 401/403 responses will not include the correct headers — making debugging much harder.
Common Mistakes
- Missing
always— Headers not sent on error responses. - Duplicate headers — If both Nginx and the backend set CORS headers, the browser sees duplicate values and may reject them. Handle CORS in one layer only.
ifdirective limitations — Nginx'sifis evaluated in the rewrite phase. Complex conditionals should usemapinstead.
Use Case
An operations engineer deploying a microservices architecture behind Nginx needs to add CORS headers at the reverse proxy layer so that individual backend services do not need to implement CORS logic.