When working with Nginx configurations, a common requirement is to specify different index files for different directory levels. In this case, we need:
/index.htmlas the default index file for the root directory/foo/bar.htmlas the index file for the /foo subdirectory
The initial configuration has several issues:
location /foo {
root /usr/share/nginx/mysite/public/foo;
index bar.html;
}
The main problems are:
- The
rootdirective is incorrectly specified with the full path - Missing proper handling of trailing slashes and URI variations
- Potential conflicts with other location blocks
Here's the proper way to implement this:
server {
listen 80;
server_name domain.tld;
# Root location
location / {
root /usr/share/nginx/mysite/public;
index index.html;
# HTTPS redirect (if needed)
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
}
# Subdirectory location with custom index
location ^~ /foo {
root /usr/share/nginx/mysite/public;
index bar.html;
# Handle both /foo and /foo/ requests
rewrite ^/foo/?$ /foo/bar.html last;
# Handle requests with any path after /foo/
try_files $uri $uri/ /foo/bar.html;
}
# Static assets caching
location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
root /usr/share/nginx/mysite/public;
expires 30d;
add_header Cache-Control "public";
}
}
- Use
^~prefix for location to prioritize this block over regex matches - Keep the
rootdirective consistent with parent location - Use
try_filesfor flexible URI handling - The
rewriterule ensures both/fooand/foo/work
After making changes:
sudo nginx -t
sudo systemctl reload nginx
For more complex scenarios, consider using alias:
location /foo {
alias /usr/share/nginx/mysite/public/foo;
index bar.html;
try_files $uri $uri/ /foo/bar.html;
}
When working with Nginx configurations, a common requirement is to specify different index files for root and subdirectories. The default behavior of using index.html everywhere might not suit all project structures.
Consider this typical scenario:
server {
root /var/www/html;
index index.html; # Default for all locations
}
This forces all directories to use index.html, which doesn't work when you need:
/index.htmlfor root/foo/bar.htmlfor a subdirectory
The correct approach uses separate location blocks with proper root directives:
server {
listen 80;
server_name example.com;
# Root location
location / {
root /usr/share/nginx/mysite/public;
index index.html;
}
# Subdirectory location
location /foo {
root /usr/share/nginx/mysite/public;
index bar.html;
}
}
1. The root directive in the subdirectory location should point to the parent directory, not the subdirectory itself.
2. Nginx automatically appends the URI to the root path when searching for files.
Problem: Requests to /foo don't serve bar.html as expected.
Solution: Ensure the location block matches all variations:
location ~ ^/foo(/|$|/.*) {
root /usr/share/nginx/mysite/public;
index bar.html;
try_files $uri $uri/ /foo/bar.html;
}
For complete URL handling, add this rewrite rule:
rewrite ^/foo$ /foo/ permanent;
Here's a complete production-ready configuration:
server {
listen 80;
server_name domain.tld;
location / {
root /usr/share/nginx/mysite/public;
index index.html;
add_header Cache-Control "public max-age=600";
}
location /foo {
root /usr/share/nginx/mysite/public;
index bar.html;
try_files $uri $uri/ /foo/bar.html;
add_header Cache-Control "public max-age=3600";
}
# Static assets
location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
expires 30d;
add_header Cache-Control "public";
}
}
Always validate your Nginx config before applying changes:
nginx -t
Then reload the configuration:
nginx -s reload