When working with Nginx configurations, a common requirement is to specify different index files for different directory levels. In this case, we need:
/index.html
as the default index file for the root directory/foo/bar.html
as 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
root
directive 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
root
directive consistent with parent location - Use
try_files
for flexible URI handling - The
rewrite
rule ensures both/foo
and/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.html
for root/foo/bar.html
for 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