When managing multiple subdomains pointing to different directories under a main domain, manually creating Nginx configurations for each subdomain becomes tedious. The ideal solution involves:
- Automatic routing of *.example.com to corresponding /public_html/* directories
- Eliminating the need for separate server blocks per subdomain
- Maintaining clean URL structures without redirects
Here's the complete wildcard configuration that handles dynamic subdomains:
server {
listen 80;
server_name ~^(?<subdomain>.+)\.example\.com$;
root /var/www/public_html/$subdomain;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP handling (adjust as needed)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# Additional security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
}
For this to work properly, you'll need:
*.example.com. IN A 192.0.2.1
Replace 192.0.2.1 with your actual server IP. This wildcard DNS record ensures all undefined subdomains resolve to your server.
The filesystem should mirror your URL structure:
/var/www/
└── public_html/
├── x/ # x.example.com
│ └── index.html
├── y/ # y.example.com
│ └── index.php
└── assets/ # Shared resources
For production environments, consider these enhancements:
# Cache control for static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
add_header Cache-Control "public";
}
# Block access to hidden files
location ~ /\. {
deny all;
}
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
After making changes, always validate and reload:
sudo nginx -t
sudo systemctl reload nginx
Create test subdomains instantly by simply making directories:
mkdir -p /var/www/public_html/newsub
echo "Hello from newsub!" > /var/www/public_html/newsub/index.html
When setting up a web server with multiple subdomains, manually configuring each vhost becomes tedious. The ideal solution automatically routes *.example.com
requests to corresponding directories under public_html
without individual configurations.
Here's the complete wildcard vhost configuration for Nginx:
server {
listen 80;
server_name ~^(?<subdomain>[^.]+)\.example\.com$;
root /var/www/public_html/$subdomain;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
# PHP handling (optional)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
}
For this to work, you need:
- A wildcard DNS A record pointing
*.example.com
to your server IP - Proper directory permissions (www-data or nginx user must have read access)
The physical directory structure should mirror:
/var/www/public_html/
├── subdomain1/
│ ├── index.html
├── subdomain2/
│ ├── index.php
└── newsub/
└── assets/
For enhanced functionality:
# Log separation
access_log /var/log/nginx/$subdomain-access.log;
error_log /var/log/nginx/$subdomain-error.log;
# SSL wildcard certificate
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
If subdomains aren't working:
- Verify DNS propagation with
dig +short x.example.com
- Check Nginx syntax:
sudo nginx -t
- Ensure directory exists and has correct permissions
- Review error logs:
tail -f /var/log/nginx/error.log
For high-traffic implementations:
# Add to server block
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;