While the Nginx documentation suggests server_name matching occurs in simple declaration order, the reality is more nuanced. The actual resolution follows this priority:
- Exact match (domain.com)
- Longest wildcard prefix (*.sub.domain.com)
- Longest wildcard suffix (sub.*.com)
- First regex match (in order of appearance)
- Default server (either the first defined or marked with
default_server
)
In your case with:
server {
listen 80;
server_name domain.com *.domain.com;
}
server {
listen 80;
server_name sub.domain.com *.sub.domain.com;
}
A request for www.sub.domain.com
matches the second server block because:
- No exact match exists
- The wildcard
*.sub.domain.com
is more specific than*.domain.com
- Nginx always prefers the most specific wildcard match
Consider these test cases:
# Case 1: Basic wildcard precedence
server {
listen 80;
server_name *.example.com;
return 200 "Generic handler";
}
server {
listen 80;
server_name api.example.com;
return 200 "API handler";
}
# Request to api.example.com will hit the second server
And for regex patterns:
# Case 2: Regex matching
server {
listen 80;
server_name ~^(www\.)?(?<subdomain>.+)\.example\.com$;
return 200 "Regex caught: $subdomain";
}
# Request to test.example.com returns "Regex caught: test"
Developers often encounter these issues:
- Assuming declaration order matters for wildcards (it doesn't)
- Not realizing
*.domain.com
doesn't matchdomain.com
itself - Overlooking that regex matches have lower priority than exact/wildcard matches
For maintainable configurations:
# 1. Always have a default catch-all
server {
listen 80 default_server;
server_name _;
return 444; # Close connection
}
# 2. Order more specific matches first
server {
listen 80;
server_name api.staging.example.com;
}
# 3. Use variables for complex patterns
map $host $backend {
~*.dev.example.com backend_dev;
~*.staging.example.com backend_stage;
default backend_prod;
}
Remember that while documentation provides general guidelines, actual implementation may have these subtle differences that only become apparent through testing edge cases.
Many developers encounter confusion when configuring multiple server
blocks in Nginx with wildcard domains. The official documentation suggests that Nginx processes server blocks in order, but practical testing often shows different behavior.
Contrary to initial expectations, Nginx doesn't simply match the first wildcard pattern it encounters. Instead, it uses a more sophisticated resolution order:
- Exact name matches (e.g.,
sub.domain.com
) - Longest wildcard prefix (e.g.,
*.sub.domain.com
beats*.domain.com
) - Longest wildcard suffix
- First regex match (in configuration order)
- Default server (either first defined or marked with
default_server
)
Consider this configuration:
server {
listen 80;
server_name domain.com *.domain.com;
# Configuration A
}
server {
listen 80;
server_name sub.domain.com *.sub.domain.com;
# Configuration B
}
A request for www.sub.domain.com
will match Configuration B
because:
- It's not an exact match for either
*.sub.domain.com
is a more specific wildcard than*.domain.com
To verify this behavior, you can use:
curl -I -H "Host: www.sub.domain.com" http://your-server-ip
Check the response headers to see which server block handled the request.
When working with multiple wildcard domains:
- Place more specific patterns first
- Use
default_server
explicitly when needed - Test with various subdomain combinations
- Consider using regex patterns for complex cases
For complete control, you can use regex patterns:
server {
listen 80;
server_name ~^(www\.)?sub\.domain\.com$;
# Configuration
}
This ensures only specific subdomains match exactly as intended.