- Chapter 1: Create a project with AWS Management Console
The organization that governs domain names is called the Internet Corporation for Assigned Names and Numbers (ICANN) and it has made it impossible for anyone to acquire a domain name forever.
- Buy domain name with
AWS Route 53
service or anotherRegistrars
for example, the best in my opinion Porkbun
Create Route 53
hosted zone
If you bought domain name not from AWS you'll need to reconfigure
AUTHORITATIVE NAMESERVERS
- Copy from created
hosted zone
your fourNS
records
- Configure and Paste to your domain name registrar DNS records
example for
porkbun
Distribution NS
records on the top-level domain (TLD) can take from 5 minutes to 12 hours
- Next, enhance the security of your website by acquiring an
SSL
certificate throughAWS Certificate Manager (ACM)
to enable secure communication. Request a public certificate for your new domain,thevopz_yourdomain.com
, and include a wildcard domain,thevopz_yourdomain.com
, to ensure robust encryption and security for all subdomains underthevopz_yourdomain.com
, utilizing a single comprehensive certificate.
Click
next
SSL Cert config
Create ssl cert
The certificate will initially appear as Pending validation
as the certificate authority (CA) verifies domain ownership or control. Please be patient until the status transitions to Issued
. As soon as we have created our domain and the SSL certificate, we should create ."
- Go to AWS Certificate Manager (ACM) choose your successfully created SSL cert and click Create records in Route53
To initiate our setup, we leverage Amazon S3 as a storage solution for our website HTML, CSS, and JavaScript files. S3, renowned for its high durability and scalable object storage, stands as an optimal choice for hosting static content. Begin by creating an S3 bucket where you can securely store and manage your website’s files. Choose a unique Name and Region that suits your requirements.
- Create an s3 bucket as shown in the screenshot, leave the rest of the settings as default
For best compatibility, we recommend that you avoid using dots (.) in bucket names, except for buckets that are used only for static website hosting. If you include dots in a bucket's name, you can't use virtual-host-style addressing over HTTPS, unless you perform your own certificate validation. This is because the security certificates used for virtual hosting of buckets don't work for buckets with dots in their names. This limitation doesn't affect buckets used for static website hosting, because static website hosting is only available over HTTP.
-
Now you can Upload your website source code to s3 bucket, for this
- Install AWS CLI
- Configure AWS credentials in the cli
aws configure
- Check that you see your s3 bucket
aws s3 ls
- Upload your resume website source code to s3 bucket
aws s3 cp </your directory with source code> <s3 bucket name> --recursive
CloudFront efficiently caches and disseminates your website’s content across a global network of edge locations, effectively minimizing latency and enhancing the overall user experience.
When establishing the distribution
-
Designate the S3 bucket as the Origin Domain for my example
thevopz.com.s3.us-east-1.amazonaws.com
-
Select
Origin access control settings(recommended)
under Origin Access. Origin Access Control (OAC) in CloudFront is a key feature that enables you to limit access to your origin server, ensuring that only specified CloudFront distributions can interact with it.
-
Click on the Create control setting for Origin access control => choose for your s3 bucket
-
In the field below Viewer change Viewer protocol policy to
Redirect HTTP to HTTPS
-
below in the settings Alternate domain name (CNAME) - optional click the button Add item and paste two records
<your_domain>
and nextwww.<your_domain>
-
In the field below Settings settings Custom SSL certificate - optional change blank to
<your SSL certificate>
generated in the Step 1 -
In the field below Default root object - optional change blank to
/index.html
-
Leave the rest of the settings as default and click Create distribution
-
When you create the "Distribution", you will see Warnings that you need to update your
Bucket Policy
, click Copy Policy
- Go to your s3 bucket for resume website and in the 3rd tab Permissions in the field to the right click Edit, and paste your copied distribution policy click Save changes
- Copy your CloudFront distribution domain name and open link in a browser, you should see your webpage
-
We bought a custom domain name
-
We created a
hosted zone
for our resume website -
We have generated and added an SSL CNAME records for our domain name in the route 53
hosted zone
entry
For use custom domain name in your browser we should create A
records type with routing traffic rule to Alias to CloudFront distribution
- Create two
A
records for blank domain name andwww
domain name, choose settings like in a picture
Finally you should get something like this (6 records), and now you can use custom domain name for your website
Tell your neighbors send a link to your friends now you're on the World Wide Web:)
Now we are set to enhance our project by implementing crucial improvements and addressing conditions 7 to 11 in our Cloud Resume Challenge.
-
Our resume webpage should include a visitor counter that displays how many people have accessed the site. We will need to write a bit of Javascript to make this happen.
-
We will retrieve the visitor counter and update its count in a DynamoDB database using a Lambda function written in Python code.
-
Navigate in the AWS Management Console
DynamoDB
on the main Dashboard click Create table -
Fill in the Table name
<your table name>
, next fill to Partition key field nameid
, next fields leave as default
- Next click Explore table items, you should creat Create item, fill
views
value forid
and create new Attribute number like in the picture
You should have something like this
- Navigate in the AWS Management Console
Lambda
click Create function
Fill fields:
-
Function name
<your name>
-
Runtime choose lattest supported
Python
-
Architecture
x86_64
-
In Advanced settings enable - [x]
Enable function URL
, choose Auth typeNONE
, Invoke modeBUFFERED(default)
and enable CORS - [x]Configure cross-origin resource sharing (CORS)
-
Click Create function
- Add Python code to your lambda function
#This section imports necessary libraries, including json and boto3 for working with AWS services.
import json
import boto3
#Here, an instance of the DynamoDB resource and a reference to the '<your dynamodb table name>' table are created.
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('<your dynamodb table name>')
#The Lambda function is triggered with an event and context.
def lambda_handler(event, context):
#The subsequent code is wrapped in a try-except block to catch and handle any exceptions that might occur during execution.
try:
# Retrieve current views
response = table.get_item(Key={'id': 'number'})
views = response.get('Item', {}).get('views', 0)
# Increment views count
views += 1
print(f"Updated views: {views}")
# Update DynamoDB with new views count
response = table.put_item(Item={'id': 'number', 'views': views})
return views
except Exception as e:
print(f"An error occurred: {e}")
raise
- Configure CORS settings, as illustrated in the image, to enhance security. To restrict calls to your Lambda function solely from
<your domain name>
, ensure proper CORS configuration.
- In the same window copy Lambda Function URL to notepad for the next javascript code
- Create
index.js
file and add javascript code to this file
//This line selects the HTML element with the class name "counter-number" and assigns it to the variable counter. This element is likely intended to display the view count.
const counter = document.querySelector(".counter-number");
//The code defines an asynchronous function named updateCounter. The async keyword is used to indicate that this function will perform asynchronous operations.
async function updateCounter() {
try {
//The code fetches data from a Lambda function using the fetch API. If the response status is not okay (not in the range 200-299), it throws an error.
const response = await fetch("Your-LambdaFunction-URL");
if (!response.ok) {
throw new Error(`Failed to fetch data. Status: ${response.status}`);
}
//If the fetch is successful, it parses the JSON response and updates the content of the counter element with the retrieved data.
const data = await response.json();
counter.innerHTML = `This page has ${data} Views!`;
} catch (error) {
console.error(`An error occurred: ${error.message}`);
// Handle error gracefully, e.g., show a fallback message or log the error
}
}
//Finally, the updateCounter function is invoked, initiating the process of fetching data and updating the view count on the web page.
updateCounter();
- Add reference to your
index.js
file inindex.html
file
<script src="/path/to/index.js"></script>
- Add the
counter-number
class to the html code element of your web page
for example
<div class="counter-number"></div>
If you have already downloaded your source code to the S3 bucket, delete the modified 'index.html' file from the bucket and download the new file to update your website.
-
In navigation pane AWS Management Console find CloudFront, go to the distribution
-
Click Invalidation tab
-
Then Create invalidation tab
-
Add object paths paste
/index.html
click Create invalidation
Your website will be updated and you should see visitor counter number
In the next step, we will configure a CI/CD workflow to automate these processes.
- Create a Github repository for your website source code
- Push your source code to the repo
- Initialize a Git repository in your local project folder.
git init
- Include all files in your project folder in the Git repository.
git add
- Commit the changes along with a descriptive message.
git commit -m "Initial commit"
- Establish the remote repository URL
git remote add origin <repository_url>
# where <repository_url> represents the URL of your GitHub repository.
- Finally, push the local files to the remote repository
git push origin master
We aim to streamline the process of updating our website code, ensuring that modifications made locally are seamlessly reflected on our live website. By pushing these changes to GitHub, our CI/CD process will automatically upload the files to AWS S3 Bucket, facilitating dynamic updates on the website and invalidate our CloudFront distribution cache.
- Return to your website source code and establish a new directory named
.github/workflows
in the root folder. Inside this directory, create a YAML file namedcicd.yml
to house the GitHub Action configuration. Insert the following code snippet into thecicd.yml
file
name: Upload Website
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: jakejarvis/s3-sync-action@master
with:
args: --follow-symlinks --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }} # optional: defaults to us-east-1
#SOURCE_DIR: '' # optional: defaults to entire repository
# When s3 bucket files updated, we need to invalidate our CloudFront distribution cache
- name: invalidate
uses: chetan/invalidate-cloudfront-action@v2
env:
PATHS: "/index.html /assets/css/main.css" # files that you want to invalidate cache
AWS_REGION: ${{ secrets.AWS_REGION }}
DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Source code for
cicd.yml
file
- Add secrets ENV VAR for Github Actions
- Navigate to your GitHub repository
settings
. - On the left sidebar, click on
Secrets and variables
. - Click New repository secret
Create ALL ENV VAR for the secret, such as AWS_S3_BUCKET
// AWS_ACCESS_KEY_ID
// AWS_SECRET_ACCESS_KEY
// AWS_REGION
// AWS_S3_BUCKET
.
- To test CI/CD Github Actions, push changes to your remote github repo
You must achive a successful execution
Well Done, you did a great job!
In the upcoming Chapter 2, we will enhance our project using Infrastructure as Code (IaC).