Matching a Homepage (or "/" or "/index.html" ) with Nginx Location Blocks
I have been doing a lot of experimenting with my website lately. Recently, I was trying to configure some special rules for my website's homepage. In Nginx, I wanted to match requests for the homepage only. When I looked in the access log, requests for https://www.tollmanz.com are registered as /. The excerpted headers for the request looks like:
authority: www.tollmanz.com
method: GET
path: /
scheme: httpsGiven that the path for the homepage is simply /, I added the location to my configuration. A heavily excerpted configuration looked something like:
server {
listen 443 ssl;
server_name www.tollmanz.com;
root /path/to/tollmanz.com/;
# Match homepage
location = / {}
# Match assets
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2|woff|ttf)$ {}
# All other files
location / {}
}I set up three locations: homepage, assets, and all other files. Nginx docs are very clear that location = / {} would match / over location / {} because it is more specific and should therefore take precedence; however, that absolutely did not work with any amount of trying.
After a ton of searching, I finally stumbled upon the index directive docs. In an aside at the end of the page, it mentions:
It should be noted that using an index file causes an internal redirect, and the request can be processed in a different location... a "
/" request will actually be processed in the second location as "/index.html".
By default, the index directive is set to display the index.html file. Since my site is a Jekyll site, all of the pages are index.html files within a specific directory. When I thought I needed to match /, I actually needed to match /index.html. Since Nginx by default will look for an index.html file inside of a directory request, I had to update my location to specifically match /index.html, even though the logs only suggest that I'm trying to match /. I needed to update my config to:
server {
listen 443 ssl;
server_name www.tollmanz.com;
root /path/to/tollmanz.com/;
# Match homepage
location = /index.html {}
# Match assets
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2|woff|ttf)$ {}
# All other files
location / {}
}This configuration makes a lot of sense in the end, but it was terribly confusing to work out. I really hope this note-to-self saves someone time in the future.