How to deploy static websites to AWS S3 and CloudFront
Deploying static websites for progressive web apps, landing pages and countless other use cases.
Yev Krupetsky
September 1 2020 · 5 min read
SHARE ON

Background
We often see the need for static websites to serve various requirements, such as a web application, an admin interface for a service, a landing page and countless other cases where all that's required is pre-built HTML pages with CSS and JavaScript.
In this post, we'll take a look at one of Altostra's templates that can help you deploy static websites quickly.
What we are building
We are building a simple static website that consists of three resources:
- S3 Bucket
- CloudFront CDN
- Domain Name
These resources come included and configured in a template, so most of the work will be setting up the website content.
Setup
We begin by creating a new project from the static-website
template. Using the alto templates command, we can see which templates are available to us, then using the alto init --template static-website we initialize a new project from that template:
$ mkdir static-website
$ cd static-website
$ alto templates
✔ Getting project templates
Available templates:
* static-website
* ...
$ alto init --template static-website
✔ Getting template 'static-website'
✔ Initializing project
$ npm init -y; echo node_modules > .gitignore
$ git init
$ git add -A .
$ git commit -m "Initial"
Architecture
There's nothing special we need to do with the project's architecture, it comes pre-defined in the template with the Domain Name, CDN and Bucket resources.
Open the project in VSCode to see the architecture design:
$ code .

Configuration
We need to configure the resources to fit our project's requirements, starting with the bucket:

The Files Location points to the public directory in the project where the content files are located. When we upload the content files later, this will be the source directory. The access level of the bucket is set to public-read because this is a publicly accessible website.
Next, the CDN configuration:

We enable the TLS options to make our site more secure, and that's it for the CDN.
And finally, the Domain Name configuration:

We configure the domain name and certificate to be parameters that we can supply during deployment, allowing us to use separate development and production values. These parameters will get their values from the environment they are deployed to.
Website Content
Now that we have the infrastructure ready, it's time to add the content. For this post's brevity, we'll use the default sample page that comes with the template. It consists of an index.html
and style.css
files.

Deploy
To deploy our website, we need to execute several steps using the Altostra CLI:
- Publish a new Deployment Image of the project to your Altostra repository.
- Create a deployment (or "instance") of your project in an environment - the Demo environment in our case.
- Build the website (if required) and upload the website content to the deployment.
We begin by pushing a new project image tagged as v1.0:
$ alto push v1.0
✔ Validating tag name 'v1.0'
✔ Checking user credentials
✔ Loading project
✔ Validating project file integrity
✔ Loading project
✔ Getting build repository
✔ Updating project file
✔ Validating image availability
✔ Packing files
✔ Getting repository information
✔ Uploading project parts
Next, we create a deployment (the "instance") named main from the image v1.0 to the Demo environment. The environment specifies the cloud account, region, configuration and policies that apply the deployment - we will explore environments and how to use them in future posts.
$ alto deploy main:v1.0 --new Demo
Checking user credentials
✔ Processing request
✔ Deploying project
Deployment status of deployment main:
┌─────────┬─────────────────┬─────────────────────────┬────────┬─────────────┐
│ (index) │ User │ Date │ Image │ Status │
├─────────┼─────────────────┼─────────────────────────┼────────┼─────────────┤
│ 0 │ 'Yev Krupetsky' │ '8/29/2020, 1:14:23 PM' │ 'v1.0' │ 'Deploying' │
└─────────┴─────────────────┴─────────────────────────┴────────┴─────────────┘
When the deployment process completes, the infrastructure is ready to receive the content files. It will take some time for the deployment to complete because we use the CDN resource. The AWS CloudFront service, which the CDN resource maps to, can take up to 30 minutes to become ready, so be patient.
To complete the process, use your DNS service provider to create a CNAME
record
for the name you provide to the Domain Name resource. It should point to the
value you get from the alto domains
command.
Upload Content
Now that the infrastructure is ready, we use the sync
command to upload the content:
$ alto sync main --all --public
✔ Checking user credentials
✔ Loading project
✔ Validating buckets
✔ Getting repository information
✔ Syncing files to site-files
The sync
command above uploads content files to all the buckets in the main
deployment that we've created earlier. It also makes the files publicly accessible. Uploaded files are always private by default for security.
Update Content
To update the content files, run the alto sync
command again, followed by the alto invalidate
command, to clear the CDN cache.
Test
Now that we have the infrastructure and the content up and running, we can test
our deployment. Use the alto domains
command to obtain the domain address:
$ alto domains main
✔ Checking user credentials
✔ Loading project
✔ Getting project domain names
site-cdn: d348wbakg23jzg.cloudfront.net

Conclusion
In this post, we saw how to deploy a static website in just a few minutes (if we ignore the long time it takes for the CloudFront distribution to become available).
It's important to distinguish updates to the project architecture from updates to its content.
We use the alto push
and alto deploy
commands to update the project's architecture, which includes resources, permissions, and configuration.
We use the alto sync
and alto invalidate
commands to upload the project's content. When uploading content, there's no need to modify the underlying infrastructure.