How to Configure Access-Control-Allow-Origin Header in NGINX for Cross-Domain Web Fonts


4 views

When loading web fonts from a subdomain to your main domain, browsers enforce Cross-Origin Resource Sharing (CORS) policies. NGINX needs explicit headers to permit this resource sharing. Here's how to solve it properly.

For most cases, adding these directives to your NGINX server block will work:

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type";
    expires 365d;
}

For better security, replace the wildcard (*) with specific domains:

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin "https://your-main-domain.com";
    add_header Access-Control-Allow-Methods "GET, OPTIONS";
    add_header Access-Control-Max-Age 3600;
    add_header Access-Control-Allow-Credentials "true";
    add_header Cache-Control "public";
    expires max;
}

For OPTIONS preflight requests, add this separate location block:

location / {
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Allow-Origin "https://your-main-domain.com";
        add_header Access-Control-Allow-Methods "GET, OPTIONS";
        add_header Access-Control-Allow-Headers "Content-Type";
        add_header Access-Control-Max-Age 3600;
        add_header Content-Type 'text/plain charset=UTF-8';
        add_header Content-Length 0;
        return 204;
    }
}

After making changes, always test with:

sudo nginx -t
sudo systemctl reload nginx

Then check headers using browser dev tools or curl:

curl -I https://your-subdomain.com/path/to/font.woff2

1. Multiple add_header directives: Only the last one takes effect unless you use the 'always' parameter
2. Cache poisoning: Always pair CORS headers with proper Cache-Control
3. Protocol mismatches: Ensure http/https consistency between domains

For complex setups with multiple allowed domains:

map $http_origin $cors_origin {
    default "";
    "~^https://(main\.domain\.com|sub\.domain\.com)$" $http_origin;
}

server {
    ...
    add_header Access-Control-Allow-Origin $cors_origin always;
    ...
}

When serving web fonts from a subdomain to your main domain, browsers enforce Cross-Origin Resource Sharing (CORS) policies. Without proper headers, you'll encounter errors like "Font from origin has been blocked by CORS policy".

Here's the minimal configuration to enable CORS for fonts in your NGINX server block:

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;
}

For better security, specify allowed domains instead of using wildcard (*):

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header 'Access-Control-Allow-Origin' 'https://yourmaindomain.com';
    add_header 'Access-Control-Allow-Methods' 'GET';
    add_header 'Access-Control-Max-Age' 86400;
}

To allow multiple domains, use a map directive:

map $http_origin $cors_origin {
    default "";
    "~^https://(domain1\.com|domain2\.com)$" $http_origin;
}

server {
    ...
    location ~* \.(eot|ttf|woff|woff2)$ {
        if ($cors_origin) {
            add_header 'Access-Control-Allow-Origin' $cors_origin;
            add_header 'Vary' 'Origin';
        }
    }
}

After making changes, test with:

curl -I https://yoursubdomain.com/fonts/yourfont.woff2

Look for the Access-Control-Allow-Origin header in the response.

Problem: Headers not appearing in response
Solution: Ensure your location block matches the font file paths exactly

Problem: Chrome still blocks fonts
Solution: Add the Vary header and clear browser cache

For optimal performance with CORS fonts:

  • Use WOFF2 format where possible
  • Set appropriate cache headers
  • Consider using a CDN for font delivery