Serverless Containers with Next.js, AWS Fargate, and AWS Amplify : apex ('naked') domain
Tags: nextjs, containers, javascript, react
Published: 2021-04-30 17:40:47

UPDATE : you may wish to consider to switch to the continuous deployment with the [out of the box SSR support](https://docs.aws.amazon.com/amplify/latest/userguide/server-side-rendering-amplify.html)

#Getting Started

You are about to finish the awesome [tutorial by Nader Dabit](https://dev.to/dabit3/serverless-containers-with-next-js-aws-fargate-and-aws-amplify-17fe) and you are having an issue with apex ('naked') domain. Me too! That is why we are here :)

To make things real I've got a free domain at [freenom](https://freenom.com) as you must have a valid domain in order to complete the tutorial.

So here is my domain : nextjsonfargate.tk.
You may take a look at an [article](https://aws.amazon.com/blogs/networking-and-content-delivery/solving-dns-zone-apex-challenges-with-third-party-dns-providers-using-aws/) describing challenges with apex domains and why you should be using www over apex. The situation is the following : I have just completed the tutorial, the website is available at www.nextjsonfargate.tk 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/je3dvdmn4wlfp70ojxes.png)
and I wish to add a redirect from an apex domain nextjsonfargate.tk to www.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xbisuc0ll8v5bzopww1.png)

Read it all through as optimal solution differs for a new project (tweak it in cloud formation) and an ad-hoc asap fix for a running project.

#Route53
[Route53](https://console.aws.amazon.com/route53)
The error above tells us to check DNS config, so here it is : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmzudhwju35kikkhhdlw.JPG)

Let's add an A record from apex domain to www :
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tr6mewlxso8h0d9kc7jz.JPG)

And here is the config after the change : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7i5cw75larphkbn18mh.JPG)

Let's try, when accessing via https :
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t4kt9yrftutyfjb21fd.png)

it looks like we need to tweak the certificate, and see how it works for http : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i4e9ar4m0ypznyv0r1gu.png)

Alright! This is something ;)
Let's jump to Certificate config.

#Certificate
[ACM](https://console.aws.amazon.com/acm)
No surprise we are having an ERR_SSL_PROTOCOL_ERROR : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oaqica1b1oxrnznh9tfk.JPG)

Let's check the details : 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjj9wehql0e0fy22osbd.JPG)

The certificate is being used by Elastic Load Balancer and Cloud Front.
Let's create a new certificate for both apex and all subdomains : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kw2pleymnyqemlur17d1.JPG)
Following the validation : 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgfvn479cjz4vjc5glgq.JPG)
Alright, let's add the new certificate to the Elastic Load Balancer Listeners and Cloud Front Distribution : 

#Elastic Load Balancer
[EC2 -> Load balancers](https://console.aws.amazon.com/ec2/)
Here I check on my ELB, navigate to tab Listeners and click on edit rules : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/li8l056qqxxnpj3m7ynt.JPG)

Let's add a new rule before: to redirect from apex to www. I could have modified the existing rule instead = that would result in availability of the website on both urls, I wish it to be constantly redirected to www : 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npg6uk2sahsodnalwgei.JPG)

And here is the configuration :
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nrzlae3nqlu09so9hvo3.JPG)



![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7nx0fqamx0400xbhcra.JPG)


After adding the certificate and changing the default : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nsg17dukmecrxbe2u6i.JPG)

#Cloud Front
[Cloud Front](https://console.aws.amazon.com/cloudfront) : 


I'm changing the certificate and adding the apex domain to Alternate Domain Names : 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yw45tlodc5jyvav03ecs.JPG)

#Intermediate results
Alright, we are set : it works :)
Both http and https : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hnitkp4n8ngozvxl2crg.png)

As a proof of concept I'll tweak the load balancer rules : 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbp1ypyyahbptg3e2406.JPG)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crzs4b5poh0ficy6n22n.png)

We thus have intermediate results : in order to make it work ad-hoc I have done the following : 
- added a new alias in Route 53 hosted zone from apex domain to www
- created a new certificate with both apex domain and all sub-domains included
- added certificate to elastic load balancer listener
- added rule for apex domain in elastic load balancer listener rules
- added certificate to cloud front distribution
- added apex domain to cloud front distribution alternate domain names

When you pull and try to publish it works with few warnings : 
```
UPDATE_FAILED               Distribution                                                           AWS::CloudFront::Distribution Fri Apr 30 2021 19:46:12 GMT+0200 (Central European Summer Time) Resource handler returned message: "Invalid request provided: The request failed because it didn't meet the preconditions in one or more request-header fields. (Service: CloudFront, Status Code: 412, Request ID: 7ed28dc9-f634-416d-99fd-9c57486763e2, Extended Request ID: null)" (RequestToken: c0c59ec1-0ef7-ed42-d13c-8be0f51e7220, HandlerErrorCode: InvalidRequest)
UPDATE_ROLLBACK_IN_PROGRESS amplify-nextonfargate-dev-195353-hostingElasticContainer-1D105I0FYAIAR AWS::CloudFormation::Stack    Fri Apr 30 2021 19:46:14 GMT+0200 (Central European Summer Time) The following resource(s) failed to update: [Distribution].                                                                                                                                                                                                                                                                                                                 
⠹ Updating resources in the cloud. This may take a few minutes...

UPDATE_FAILED               hostingElasticContainer          AWS::CloudFormation::Stack Fri Apr 30 2021 19:46:19 GMT+0200 (Central European Summer Time) Embedded stack arn:aws:cloudformation:us-east-1:<account>:stack/amplify-nextonfargate-dev-195353-hostingElasticContainer-1D105I0FYAIAR/e7835650-a989-11eb-9592-0e4dccb471bf was not successfully updated. Currently in UPDATE_ROLLBACK_IN_PROGRESS with reason: The following resource(s) failed to update: [Distribution]. 
UPDATE_ROLLBACK_IN_PROGRESS amplify-nextonfargate-dev-195353 AWS::CloudFormation::Stack Fri Apr 30 2021 19:46:19 GMT+0200 (Central European Summer Time) The following resource(s) failed to update: [hostingElasticContainer].    
```

The jedi way is to configure all of the above in the cloud formation!
Well, I've removed hosting and started from scratch, tweaked the cloud formation stack and tried to push : it got overridden and all my tweaks were gone.
Let's see if I manage to digest the my tweaks to cloud formation...

Alright, it actually works better if I leave the previous certificate in the load balancer listener list, then on each publish I need to change the certificate in Cloud Front and that's it.

That's really good, as we have both enhanced user experience and deployment experience, a bit of maintenance overhead.

Until I find a way to digest an apex domain to a certificate in cloud formation or a certificate to the stack...
Let's enjoy this Frankenstein solution!


#Credits
If I have saved you from deadlines burnout you may express your gratitude here : https://www.buymeacoffee.com/hexfloor