Suppose you want to deploy multiple Gatsby.js sites using the following setup.

Then you have to configure NGINX like this:

server {
    listen                      127.0.1.10:443 ssl http2;
    server_name                 gatsby-site-00.mydomain.net;

    ssl                         on;
    ssl_certificate            /usr/local/etc/dehydrated/certs/gatsby-site-00.mydomain.net/fullchain.pem;
    ssl_certificate_key        /usr/local/etc/dehydrated/certs/gatsby-site-00.mydomain.net/privkey.pem;

    # Gatsby static pages

    location / {
        rewrite                 ^/(.*)$ /gatsby-site-00/$1 break;
        proxy_pass              http://127.0.1.20:80;
        proxy_redirect          http://127.0.1.20/gatsby-site-00/ https://gatsby-site-00.mydomain.net/;
    }

}

If you open the site https://gatsby-site-00.mydomain.net in a web browser and click on a link which points to the events page react-router will set the URL to https://gatsby-site-00.mydomain.net/events. Note the missing trailing slash (.../events instead of .../events/) ;-) Also remember that sites generated with Gatsby.js are single-page applications (SPAs).

The missing trailing slash in generated URLs with regard to Gatsby.js and react-router has also been discussed here.

Now suppose a user bookmarks the URL https://gatsby-site-00.mydomain.net/events. If the user wants to open this bookmark in a new browser window the Apache server will respond with a HTTP 301 (the Location header field has already been modified by NGINX):

zaunerc@2217PC12387:~/repos/keys$ curl -I https://gatsby-site-00.mydomain.net/events
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Wed, 20 Jun 2018 17:28:35 GMT
Content-Type: text/html; charset=iso-8859-1
Connection: keep-alive
Location: https://gatsby-site-00.mydomain.net/events/

zaunerc@2217PC12387:~/repos/keys$ 

Why? Because there exists no file named events. But there exists a directory named events. And to address a directory on a web server you should include a trailing slash.

And that’s why we have to include the proxy_redirect directive (docs). This sets the text that should be changed in the “Location” and “Refresh” header fields of a proxied server response.

By the way. Apache still delivers a default 301 status page which content is not modified by NGINX. But that doesn’t matter. Web browsers only use the information provided by the HTTP response headers:

zaunerc@2217PC12387:~/repos/keys$ curl https://gatsby-site-00.mydomain.net/events
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://127.0.1.20/gatsby-site-00/events/">here</a>.</p>
</body></html>
zaunerc@2217PC12387:~/repos/keys$