When implementing HTTPS redirection for wildcard subdomains (*.example.com) in Nginx, many developers encounter an unexpected behavior where the asterisk symbol gets URL-encoded in the redirect destination (e.g., https://%2A.example.com). This occurs because Nginx processes the wildcard character literally during rewrite operations.
The solution involves using Nginx's $host
variable instead of $server_name
to preserve the actual requested subdomain:
server {
listen 80;
server_name ~^(.*)\.example\.com$;
return 301 https://$host$request_uri;
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
1. The regex pattern ~^(.*)\.example\.com$
matches any subdomain while capturing the dynamic part
2. $host
automatically contains the original requested hostname
3. HTTP status code 301 ensures permanent redirect for SEO benefits
4. The separate block for the apex domain maintains clean URL handling
For environments requiring additional security headers:
server {
listen 443 ssl http2;
server_name ~^(.*)\.example\.com$;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# Your regular configuration...
}
After implementing, verify with:
curl -I http://test.example.com
curl -I http://dev.example.com
curl -I http://example.com
All should return 301 redirects to their HTTPS counterparts without URL encoding artifacts.
When setting up HTTPS redirection for wildcard subdomains (*.mydomain.com) in Nginx, many developers encounter an issue where the redirect improperly includes the wildcard character (%2A) in the destination URL. This happens because Nginx processes the wildcard literally when using the $server_name
variable.
Here's the correct way to handle wildcard subdomain redirects in Nginx:
server {
listen 80;
server_name ~^(.*)\.mydomain\.com$;
# Capture the subdomain and use it in redirect
return 301 https://$1.mydomain.com$request_uri;
}
server {
listen 80;
server_name mydomain.com;
# Redirect base domain
return 301 https://mydomain.com$request_uri;
}
The solution uses regular expression capture groups in the server_name directive:
~^(.*)\.mydomain\.com$
- Matches any subdomain and captures it in $1$1
- Contains the captured subdomain (without the wildcard character)return 301
- More efficient than rewrite for simple redirects
For a production environment with both wildcard and specific subdomains:
# HTTP to HTTPS redirect for all subdomains
server {
listen 80;
server_name ~^(.*)\.example\.com$ example.com;
if ($host ~* ^(.*)\.example\.com$) {
return 301 https://$1.example.com$request_uri;
}
return 301 https://example.com$request_uri;
}
# HTTPS server configuration
server {
listen 443 ssl;
server_name ~^(.*)\.example\.com$ example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# Rest of your SSL configuration...
}
Using regular expressions in server_name directives has a slight performance impact. For high-traffic sites, consider:
- Using separate server blocks for frequently accessed subdomains
- Implementing caching for the redirect rules
- Testing with
nginx -t
after configuration changes
If redirects aren't working as expected:
- Verify your DNS wildcard record (*.domain.com) points to the server
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- Test with curl:
curl -I http://test.example.com
- Ensure your SSL certificate includes both the wildcard and base domain