Don’t do this.
You’re still here? Cool, let’s continue. For complicated reasons involving a legacy on-premises application I had a static site on AWS that I needed to route to with an Nginx reverse proxy. The application architecture included several locations, each of which was proxied to a different port on an on-premises server. The landing page, and only the landing page (and its assets), are on Cloudfront. For historical reasons, I needed to have this entire collection under a single DNS name.
Location, location …
The first step was modifying the Nginx proxy to have a separate location for the root landing page and its assets, while leaving everything else untouched. Serverfault came to the rescue on this one:
1 | location = / { |
Per the Nginx documentation, using the equals operator (=
) in a location block specifies an exact match.
SNI
That configuration was my first attempt and it didn’t work:
1 | 2022/11/29 15:43:41 [error] 7701#7701: *29249 SSL_do_handshake() failed (SSL: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol) while SSL handshaking to upstream, client: xxx.xxx.xxx.xxx, server: example.net, request: "GET / HTTP/1.1", upstream: "https://xxx.xxx.xxx.xxx:443/", host: "example.net" |
The main issue here is that we’re passing a request back to Cloudfront and not indicating which domain it’s for. Cloudfront uses Server Name Indication (SNI) so we have to help it out a little. I went through several guides and bits of documentation before I ran across a blog post from Dave Long that put it all together. This is my final configuration on the Nginx side:
1 | location = / { |
Cloudfront
The Cloudfront piece was straightforward. Since we’re doing TLS with a custom domain, I ensured that the TLS certificate had that name added and that the name was added as an additional domain name.