Create a serverless website on AWS with Serverless plugins

The Serverless Framework allows us to create serverless websites. These websites use the S3, CloudFront, Route 53, and Certificate Manager AWS services. We can set up all four on AWS using Serverless plugins.

What is a serverless website?

A serverless website is a website that runs without a server. It may seem impossible because every website needs a server. Object storage services (e.g., S3) allow serving HTML files and their supporting files. The browser just needs the HTML files, and it will fetch all the related files based on the HTML code. Think of simple HTML websites with dynamic code (e.g., PHP or Python).

What do I need to create a serverless website?

You will need static web page files (i.e., HTML, JavaScript, CSS, and image files). If the website correctly displays in a browser by double-clicking the file on your computer, it will work as a serverless website.

You will need an AWS account. You will need a credit card to sign up for AWS. AWS accounts are free, but you pay for any services that you use. Fortunately, serverless websites are very cheap. I host three serverless websites for $0.05 per month.

You will probably want a custom domain to have a readable website address. You can buy one on AWS or use a domain name provider. This post assumes you already have a custom domain.

You will need the Serverless Framework to follow along with the rest of this post. Use the Serverless docs to install and set up the Serverless Framework.

Setting up the domain with Route 53

Route 53 is the AWS service that deals with domain names and DNS records. We will need to set up a Route 53 hosted zone to create the domain name records required to route the custom domain name to the serverless website.

We will use a Serverless Framework plugin to create the hosted zone: the serverless-hosted-zone plugin.

To install it:

cd to-my-serverless-project
npm install --save-dev serverless-hosted-zone

To add it to the serverless.yml configuration file:

plugins:
  # add to the previous entries
  - serverless-hosted-zone

custom:
  # add to the previous entries
  # see the documentation for all the options
  hostedZone:
    name: customdomain.com. # Note the trailing dot

To create the hosted zone:

sls create-zone

Now we have a hosted zone in our AWS account for the customdomain.com domain name.

Setting up a certificate

The AWS Certificate Manager service allows us to create a free certificate. That way, we can use HTTPS for our serverless website (and make Google and our website visitors feel happy and safe).

We will use a Serverless Framework plugin to create the hosted zone: the serverless-certificate-creator
plugin.

To install it:

npm i --save-dev serverless-certificate-creator

To add it to the serverless.yml configuration file:

plugins:
  # add to the previous entries
  - serverless-certificate-creator

custom:
  # add to the previous entries
  # see the documentation for all the options
  customCertificate:
    certificateName: customdomain.com
    idempotencyToken: customdomaincom
    hostedZoneNames: customdomain.com. # Note the trailing dot

To create the certificate:

sls create-cert

The plugin creates the certificate and registers the DNS records in the hosted zone.

Creating the serverless website hosting

We will assume you already have the static HTML files you want to use for your serverless website. We will create an S3 bucket and a CloudFront distribution for our website. S3 is the object storage where we upload and serve our website files. CloudFront is a Content Delivery Network (CDN) to efficiently serve the website files. We will associate the certificate to the CloudFront distribution.

We will use a Serverless Framework plugin to create the S3 bucket and CloudFront distribution: the fullstack-serverless
plugin.

To install it:

npm install -g serverless

To add it to the serverless.yml configuration file:

plugins:
  # add to the previous entries
  - fullstack-serverless

custom:
  # add to the previous entries
  # see the documentation for all the options
  fullstack:
    domain: customdomain.com
    certificate: arn:aws:acm:us-east-1: # use the actual ARN
    bucketName: customdomain.com # the desired bucket name
    distributionFolder: my-website-files-dir # assumes it is in the  same directory
    indexDocument: index.html
    errorDocument: error.html
    singlePageApp: true
    compressWebContent: true

To deploy your static HTML website:

# no-generate-client option because only using static files
# omit if you are using a reactive framework (e.g., React, Vue, Nuxt, Next)
serverless client deploy --no-generate-client

Updating the domain name pointer

If you bought your domain name within AWS Route 53, there is nothing left to do. AWS created automatically created the customdomain.com. hosted zone for you and the plugin checked for it.

If you bought it somewhere else, you should update the DNS records with that provider and point it to the CloudFront distribution.

You may have noticed the plugin output a DNS name (e.g., abc1d2efghij4.cloudfront.net.), or you can go to the AWS console to get the CloudFront distribution DNS name. Go to your DNS provider and create an ALIAS record pointing to abc1d2efghij4.cloudfront.net. so anyone that visits https://customdomain.com will see your new serverless website.

Conclusion

With three Serverless Framework plugins, we created a serverless website to serve static HTML files. We can use this same approach to serve a Single Page Application designed with a reactive framework (e.g., React or Vue). We should point our domain name to our new serverless website if we purchased the domain outside of AWS.

Before You Go

Join my mailing list to receive updates about my writing.

Stay secure,
Miguel

About the Author

Miguel is a Principal Security Engineer and is the author of the "Serverless Security" book. He has worked on multiple serverless projects as a developer and security engineer, contributed to open-source serverless projects, and worked on large military systems in various engineering roles.

Photo by KOBU Agency on Unsplash

18