http://localhost:8080. If that’s the next thing on your to-do list, because it certainly is what I do on every new project, then maybe the following post will help you get started more quickly with JAMstack deployment.
This post describes the steps needed to host your shiny new web app on three very different providers with continuous deployment and transport layer security enabled out of the box. Everything described in this post can be found in the linked Git repository.
Please note that in order to be able to replicate all of the described steps in this post, you are going to need the following:
- a domain hosted on a provider which allows custom CNAME records
- an active account for the particular service provider
There are definitely more service providers out there which offer the required functionality and although their offerings vary, the integration into an existing project and the end results aren’t so different from the ones depicted here.
Scenario and application
I’ve prepared a very simple html page (to be found here) which mostly displays static content but does execute two remote requests to a predefined API. I opted to use this simple approach and not go for a full-blown modern SPA framework, because the concepts involved in deploying and serving the html+js are the same and no extra building or packing is required.
The implementation details of said remote API are not relevant right now, the information they provide is a third-party call to a geo IP database and a predefined explanation about a given cloud service/provider.
The end results looks like this, when hosted locally:
So now that we have the static page sources, there is nothing stopping us from deploying this monster of a page and making it available on the internet.
Let’s take a look at the “ready-to-use” providers as they are generally easy to set up and deploy. They also provide many extra features like an already available CDN network and valid modern TLS enabled out of the box.
Netlify is a static website hosting provider that redefines developer experience and ease of deployment. They have many advanced features like linked auth providers, worker lambda functions, automated artifact building, SSL, DNS management, basic auth support and many more. For this primer, their free plan suffices, so that’s what I’m going to be using.
After registering and opting for a free plan, one needs to link the project sources to Netlify.
Because of the fact that my project is hosted on GitHub, I just go to “Create new site” and select GitHub as the desired provider and grant Netlify access to the correct repository.
I am going to be building from the master branch, so let’s just leave the options as they are.
And that’s it. The site is instantly live and available under a unique Netlify subdomain – something like
https://amaizing-flying-horse.netlify.com. The cool thing about linking your repository to Netlify is that any commits on it instantly result in a redeploy.
If you would like to use your domain name, you have the option of using Netlify as a DNS hosting provider or create a redirect. I’m going to create a CNAME redirect. For this to work, you have to add a custom domain to your site via the Netlify admin console.
Lastly, create a CNAME DNS entry on your domain with your DNS hosting provider and point it to the unique Netlify URL:
CNAME jamon-netlify YOUR-NETLIFY-PAGE-NAME.netlify.com
Your deployed site should now be available under
https://jamon-netlify.YOUR-DOMAIN.TLD (for our demo it’s https://jamon-netlify.codentric.rocks) and we wrote exactly 0 lines of configuration code to set everything up.
GitHub Pages has been around as long as GitHub itself and provides a hosting service for static web pages for registered users. It is not as feature-rich and flexible as some of the other services described here, but is quick to setup and baked into GitHub. If you are already hosting your project on GitHub, it is essentially a no-brainer, because all of the file changes are instantly deployed/live.
To set everything up, you need to go to the settings page of the repository you are willing to host and select the Git branch where your web site code resides. In the case of our demo, it will be master again.
As advertised, the site is instantly published and available online under
https://GITHUB_USER.github.io/GITHUB_PROJECT/ which translates to
https://totev.github.io/jamon/ for the project described here.
If, again, you rather opt out for your own domain, GitHub Pages lets you do this also. First you must provide your custom domain name.
Then create a CNAME DNS entry on your domain with your DNS hosting provider and point it to your GitHub Pages URL:
CNAME jamon-github YOUR-GITHUB-USERNAME.github.io
As mentioned before, your deployed site should now be available under
https://jamon-github.YOUR-DOMAIN.TLD (for our demo it’s https://jamon-github.codentric.rocks) – no further steps needed.
AWS S3 / CloudFront
If you haven’t been living under a rock for the past decade, then you should already be aware of AWS and its multiple services. Because of the fact that there are so many services, there are so many ways to host a static site on AWS. I’m going to focus on the simplest one I know – using S3 buckets.
Let’s start by creating a shiny new S3 bucket:
Then set up its permissions to allow public read access:
Add a public read policy:
The policy that grants everyone read access to the bucket’s content is:
Now let’s add the content to the bucket:
All that is left now is enabling the static website hosting feature of the bucket:
Now the content of the S3 bucket is live and can be accessed under
http://YOUR-S3-BUCKETNAME.s3-website.AWS-REGION.amazonaws.com/ (in this case it’s http://jamon-aws.codecentric.rocks.s3-website.eu-central-1.amazonaws.com/)
Before celebrating the successful deployment, there are two things missing: continuous development and custom DNS support. As with everything in AWS, there are many ways to accomplish this and they are probably all correct if they work for you. For the purpose of this demo/blog post, I’ve chosen to employ AWS CodePipeline in combination with CloudFront.
Setting up CodePipeline for this project is easy, because no actual building is required. The “code” is being checked out of the GitHub repository and pushed into the previously configured S3 bucket ultimately replacing its contents.
So let’s create a continuous delivery pipeline:
Add GitHub as source and choose web hooks as a trigger method:
Skip the build stage as the simple demo project requires no building:
Configure the actual deployment. We want to use our previously created S3 bucket for this. Remember to select the extraction option as code pipeline zips the artifacts by default.
This should do it and our code should get automatically deployed on every repository update. Let’s check if everything is working by triggering a build via a commit in the repository:
For providing TLS, CDN support, as well as allowing custom domain support, I’m going to be using AWS’ content delivery network – CloudFront. Prior to setting up CloudFront, we must import our SSL certificate into the AWS Certificate Manager in the *us-east-1* region (yes, even if everything else is in a different region).
After this, the overview page in the AWS console should look something like this:
Now we are going to configure the distribution so that the S3 content is only available via CloudFront, which will disable access to the previously exposed S3 bucket URL. This is needed so that we can have a HTTP-HTTPS redirection, a valid SSL certificate for the CloudFront part, the ability to use our own subdomain and to be able to fully harness the AWS content delivery network located around the globe.
Let’s start by creating a new CloudFront distribution and choose the web delivery method:
Set up the distribution by filling out the origin domain name (the one exposed via the static website hosting option of the S3 bucket). Select said S3 bucket as origin and opt for adding the new policy to it so that the appropriate permissions are added automatically. Also, configure a HTTP redirect from HTTP to HTTPS so that our site is only available over HTTPS.
Remember that policy, which we added on the S3 bucket before? Well, we don’t need it anymore, so it’s safe to delete it. This only leaves the freshly generated one from CloudFront:
For the distribution settings, fill out the desired CNAME and select the previously added certificate. Don’t forget to select a recent security policy.
Finally, we need to create a CNAME DNS entry with your DNS hosting provider and point it to the AWS CloudFrount URL:
CNAME jamon-aws YOUR-CLOUDFRONT-DISTRIBUTION-ID.cloudfront.net
After all of the configuration work is done, the deployed site should be available under
https://jamon-aws.YOUR-DOMAIN.TLD (for our demo it’s https://jamon-aws.codentric.rocks).
I really like working with JAMstack-based applications which offer rich and powerful user experience and live in the browser. The fact that there are so many ways to deploy them and make them generally available with ease puts a smile on my face every time. Unfortunately, I still often find myself writing complex Nginx configuration files and planning load balancing strategies.
Hopefully this post on JAMstack deployment made you at least consider giving a JAMstack-dedicated provider a chance.
If you are interested in a hosting provider not covered here, write me a comment and I’ll happily include it in a follow-up piece.
Sources, links and generally useful information