NGinx rewrite rules
Table of content
I use nginx
as a reverse-proxy for a side-project. It’s job is to sit between the user and the various back-end services. It’ll then serve the correct otherwise-inaccessible service depending on the URI or the port.
One of the hidden services is a minio
storage. I use it to host multiple static websites with dynamic names. So I need to craft the correct nginx
configuration to serve the right files depending on the requested URL.
There is a great deal of nginx
documentation and many stack overflow pages regarding its configuration. But they all consider the domain-name to be some sort or logical root. This is not the case in this article and a simple trick allowed me to keep the configuration generic in term of bucket’s name and navigation’s depth.
The problem
Let’s see the initial issue here.
My side-project is a web front-end for an otherwise CLI1 based SSG2. At creation time, each website gets a dynamically-generated UUID3. This UUID is used to create a minio
bucket in order to host the site’s static assets.
Once users are happy with their site’s content, they can hit the Generate
button and then the Visit
button. The first action will mix the database content and the static assets and generate the static website in a public
directory at the bucket’s root. The second action simply opens a new browser tab to domain.name/UUID/
.
So, the nginx
configuration must extract the UUID
part of the URI and redirect to minio
’s /UUID/public/index.html
file. But if the user navigates to domain.name/UUID/blog/
, nginx
should redirect to /UUID/public/blog/index.html
. Let’s dive deeper: domain.name/UUID/blog/article/
should serve /UUID/public/blog/article/index.html
. And see the invisible: pages load style sheets and static assets so domain.name/UUID/style.css
should serve /UUID/public/style.css
.
The solution
rewrite ^/([^/]+)/(.+)/$ /$1/public/$2/index.html break;
rewrite ^/([^/]+)/$ /$1/public/index.html break;
rewrite ^/([^/]+)/(.*)$ /$1/public/$2 break;
From bottom to top:
- If the URI ends without a
/
, serve the file under thepublic
directory. - If the URI ends with a
/
and has no path after the domain name, serve deindex.html
file. - Else, serve de
index.html
files under the trailing path with addedpublic
directory.
But why this post ?
It might seem a rather trivial problem to solve. So, why bother with a post ?
Well, simply because most if not all nginx
documentation assume no path between the domain name and the actual file to serve. As a result, there is no mention of the first part of the three regular expressions ^/([^/]+)/
. This is the magic part that allow one to separate the domain name $1
and the path $2
and make nginx
behave the way I wanted.
Command Line Interface
Static Site Generator
Universaly Unique Identifier