AWS Static Website with S3 and Lambda

I wonder how many simple “presence” websites are still out there running on hosted services like GoDaddy or similar. What’s a presence website, you say? Have you ever had an idea for a new business or product, maybe even registered an awesome domain name. You want to test the waters to see if your idea has legs. So you need a point of presence on the web that gives your idea some substance and a way for prospects to contact you. I’ve created more than a few of these websites over the years, and each time, I usually over-buy and drop another $100 at GoDaddy. What if you could have virtually free hosting for that website and only pay a few bucks for the domain? 

The answer is to simply set up an Amazon Web Services account and host your static website on S3 (Simple Storage Service).  Here are some of the benefits:

  • The cost is literally nothing. You pay very little for storage and only pay for data retrieval. Combine your site with CloudFront worldwide CDN and there is very little retrieval from S3. 
  • CloudFront also has some built-in protection from DDOS (distributed denial of service) attacks. See here
  •  Through AWS Certificate Manager, public SSL/TLS certificates are free, meaning you can expose your site over https at no cost.
  • Easily integrate with AWS Web API Gateway and Lambda for some server-side capabilities such as sending  a contact request notification. 
  • Best of all, free tier credits can eliminate the hosting cost completely for 1 year. If your idea bombs, just delete the account.  

I am going to be breaking this into two blog posts. The first will deal with creating and deploying the site and the second will take care of creating functionality for the ContactUs feature. The basic steps for creating the site are:

Create an AWS Account

With a new AWS account, you qualify for free-tier hosting on S3 which is usually more than adequate for simple presence websites. The link to create an AWS account is  here. You will need to provide a credit card in order to create the account but you will not be charged unless you exceed the free tier thresholds. It is a good idea to setup a billing alert so that you will be notified if your bill is somehow exceeding your expectation. For a free account like this, I set up a billing alert for $5. Instructions for doing this can be found here.

Register your Domain

If you haven’t registered a Domain yet, there are many choices. In the past I’ve relied on GoDaddy for Domain registration and DNS for convenience reasons. Obviously, if you are hosting at GoDaddy, its better to have just one bill. However, you could choose AWS Route 53 at a cost of $12/yr for registration and DNS. There may be a cheaper alternative, but if you’re looking for convenience, this is the way to go. Also, there can be some complications using GoDaddy as a Registrar and AWS Route 53 for DNS. For this example, I had already registered my domain,, at GoDaddy so we won’t be using Route 53 for DNS. 

Configure and create your S3 bucket

Next steps are to get the website file up to AWS in an S3 bucket. S3 or Simple Storage Service is one of the first web services ever offered by AWS back in 2006. Its an object based storage system that resembles a file system directory structure but under the covers its just a key-value store. Objects are organized into Buckets to facilitate managing access to files. So once you are logged into the AWS console, select S3 from the services drop down. Go ahead and click the Create Bucket button and you will be presented with the following: 

You can really use any name you want, but if your website has any assets or images that you have referenced in html with a relative link, you will want your bucket to be named the same as your URL so that those asset files can be found. On the Configure Options and Set Permissions tabs, you can accept all the defaults. Next, you will need to create a Bucket Policy,  so select the newly created bucket and click the Permissions tab. Click on Bucket Policy and add the following text:

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "*"

The preceding bucket policy grants all anyone (Principal: *) read access of the bucket resource*.

The next step is to enable website hosting on your bucket. Click on the Properties tab for you buck and select Static Website Hosting. Here you will identify which file will server as the root of your website. In most cases this will be something like Index.html or Default.htm, etc. Also optionally provide an error file such as error.html.



Upload your site

Next, you’re going to need the html for your site. If you don’t have the site yet, I recommend downloading a free one-page template from one of the literally thousands of offerings on the internet. At most it will cost you your email address. For this post I downloaded the EBusiness-Master free template from here. I chose this template because its a single-page(index.html + CSS + javascript), it’s responsive(looks good on a tablet and mobile), has a contact form(we’re going to hook that up to AWS Web API Gateway), and looks cool. Just unpack the files and modify the content in Index.html to your hearts content. 

Now its time to copy your website files and assets into your S3 bucket. On my local machine I created a directory called \FundWiz and extracted the EBusiness-Master template. The folder contents are as follows:

There are a number of ways of moving files into S3. You could use the AWS S3 Management console and manually upload your files and folders. This can be a pain if you are making many revisions and testing them out on AWS. Another method is to use the AWS CLI to  copy/synchronize a local directory to your S3 bucket. I like this option because I can keep the command available in a command window and re-run it quickly if needed. If you haven’t done so already, you will need to set up the AWS CLI on your workstation. Instructions for doing so are here. Keep in mind, that if using the CLI, you will need to configure your workstation with the appropriate Access Key and Access Key Secret for your IAM user. Instructions for configuring your CLI are here. Once the CLI is configured, the following command run from the local website folder will synchronize your website files and folders into your S3 bucket. 

AWS s3 sync . s3://

Now, your website should be in your bucket. Subsequent local updates to any particular file in your website can be synchronized with the bucket simply by re-running the above command. Keep in mind that free-tier usage allows for 5GB of data. However, there is a AWS Free tier limit of 2000 S3 Put Requests. So you definitely don’t want to do a Put Request for a file that hasn’t changed. At this point, your static website should be available from the internet with the predefined S3 bucket URL. This can be found by selecting your Bucket on the S3 console and clicking into the Static WebSite Hosting tab. Click or select/paste that endpoint and your website should be up and running.


Create an SSL Certificate

Notice, right off the bat, that the page is not secure. Its using http and we would really like to use https. In order to fix this issue, you will need an SSL Certificate. Thankfully, AWS provides a managed certificate that you can use free of charge. Simply go to Services and under Sercurity, Identity and Compliance, select Certificate Manager. Assuming you have access to the DNS records at the registrar, go ahead a click Request a Certificate.  AWS needs to confirm that you indeed own the Domain so it will ask you to create a couple DNS record at the registrar. So click Request a public certificate. You will enter the domain name and click Next. Choose the DNS validation option and select Review. Finally, click Confirm and Request. The validation status will be set to “Pending” and AWS will begin to query DNS for a special CName record associated with your domain. Download the .csv file from the link at the bottom of the page to see the CName record its looking for.


Next, go to your Registrar(i.e. GoDaddy->My Domains->Manage DNS) and create a new CName record using the Record Name and Value from the csv file above. Note, you will need to omit the trailing ‘.’ on each the Record Name and Record Value. Also keep in mind that the Record Name should not include the root domain…in this case Once you have updated the CName record at the registrar, AWS will be able to validate that you indeed have the rights to the domain and issues the certificate. This could take anywhere from a few minutes to an hour.

Create your CloudFront Distribution

Once your certificate is issued, you will use the certificate to set up a CloudFront Distribution for your S3 website. There are many S3 website tutorials that skip this step, but if you do, you may regret it. Keep in mind that costs for S3 are based on the amount of object reads and writes. Each website file and artifact is one object. The AWS free tier does give you several thousand reads and writes for free, but if your site contains many assets such as images, you could exceed that threshold easily. Now consider the prospect of being the target of a DDOS attack where your website is accessed hundreds or thousand of times per second. Earlier in this article I recommended setting up an AWS billing alert which would at least let you know something bad is happening, but it won’t take long before you wrack up some serious costs. CloudFront can help minimize that because its a Cache. In the case of a DDOS attack, CloudFront would simply keep serving up cached files and spare the S3 GetObject calls. There are also some more advance methods in CloudFront for detecting and dealing with a DDOS, namely WAF.

So to use CloudFront for your S3 website, go to the AWS Console and select Services and under Networking & Content Delivery select CloudFront. Choose Create Distribution and then Get Started  under the Web section. When you click on Origin Domain Name you should see your S3 bucket website endpoint. Scroll down to Distribution Settings and select Custom SSL Certificate. When you click in the text box, you should see your certificate is available. The remaining defaults are sufficient so go ahead and click Create Distribution.  The distribution could take as long as 30 minutes to create, but note the Domain Name and copy that to the clipboard.

Update DNS

For this example, I initially attempted to use Route53 for DNS and GoDaddy for the Registrar but found that Route53 would deny access to the CName record for some reason. If you would like to try this on your own, the process is quite simple. You create a Public Hosted Zone in Route53 and then replace the GoDaddy’s NS (Name Server) records with the NS records from Route53. The detailed instructions can be found here. Nonetheless, my experience following these instructions did not end well. The alternative that I chose was to leave all the zone records at GoDaddy and let them provide the DNS. In order to route traffic to the CloudFront Distribution, On GoDaddy I created a new CName record for “www” and provided my CloudFront Distribution’s Domain Name endpoint.


You may need to wait a few minutes for the DNS changes to propagate, but you should see your new website available with SSL under your www domain url. Next, we are going to take a look at using AWS API Gateway and AWS Lambda to expose a web api that will send a contact request notification. See you there.


About the Author Don McRae

CEO of and Independent Software Development Consultant. Specializing in AWS Cloud Architecture, Development and DevOps and Cloud Security.

Leave a Comment: