This guide will walk you through hosting your site using a secure, high-performance architecture. Here, we’ll use cloudfront default url to access the website but you can use a domain name via Route 53 if handy.
- Goal: Host a static personal portfolio, but with a focus on security, performance, and cost.
- Business Problem: Creating a professional online presence that is fast, secure, and cheap to maintain.
- What you’ll learn: Securely storing files, global content delivery, hosting website and basic web security.
Build Portfolio Website Using AWS Services
Services Used :
- S3 (for hosting)
- CloudFront (CDN)
- AWS WAF (Web Application Firewall)
Step 1: Create a Private S3 Bucket
This bucket will store your website files (index.html
, etc.).
- Navigate to S3: In the AWS Console, go to the S3 service.
- Create Bucket: Click “Create bucket”.
- Bucket name: Give it a unique name (e.g.,
yourname-portfolio-source-files
). - AWS Region: Choose a region close to you (e.g.,
us-east-1
).
- Bucket name: Give it a unique name (e.g.,
- Block Public Access: This is the most critical security step. Ensure “Block all public access” is checked. We will grant access only to our CDN later.
- Create: Click “Create bucket”.
- Upload Files: Go into your new bucket and click “Upload”. Add the
index.html
file and any other assets you have. Refer to below sample code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Cloud Portfolio</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
.gradient-text {
background: linear-gradient(to right, #3b82f6, #8b5cf6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200">
<div class="container mx-auto max-w-4xl px-4 py-8 md:py-16">
<!-- Header Section -->
<header class="flex flex-col md:flex-row items-center justify-between mb-12">
<div class="flex items-center mb-6 md:mb-0">
<img src="https://placehold.co/80x80/1f2937/a5b4fc?text=ME" alt="Your Name" class="w-20 h-20 rounded-full mr-4 border-2 border-blue-400">
<div>
<h1 class="text-3xl font-bold text-white">Your Name</h1>
<p class="text-lg text-blue-300">Aspiring Cloud & DevOps Engineer</p>
</div>
</div>
<nav class="flex space-x-6">
<a href="#about" class="text-gray-300 hover:text-white transition">About</a>
<a href="#projects" class="text-gray-300 hover:text-white transition">Projects</a>
<a href="#contact" class="text-gray-300 hover:text-white transition">Contact</a>
</nav>
</header>
<!-- About Section -->
<main>
<section id="about" class="mb-16">
<h2 class="text-3xl font-bold mb-4 gradient-text">About Me</h2>
<p class="text-gray-300 leading-relaxed">
I am a passionate technologist with a keen interest in building scalable, secure, and resilient systems on the cloud. My journey involves mastering core infrastructure services on AWS and Azure, with a focus on automation, security-first design, and production-ready architecture. This portfolio itself is a testament to that, hosted securely and delivered globally using cloud-native services.
</p>
</section>
<!-- Projects Section -->
<section id="projects" class="mb-16">
<h2 class="text-3xl font-bold mb-6 gradient-text">Cloud Projects</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- Project 1 -->
<div class="bg-gray-800 rounded-lg p-6 shadow-lg hover:shadow-blue-500/20 transform hover:-translate-y-1 transition-all duration-300">
<h3 class="text-xl font-bold text-white mb-2">Secure Portfolio Website</h3>
<p class="text-gray-400 mb-4">This very website! Deployed on AWS S3 & Azure Blob, served via CDN with WAF protection. It's designed for high availability, low latency, and security.</p>
<div class="flex space-x-2">
<span class="bg-blue-900 text-blue-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">AWS S3</span>
<span class="bg-blue-900 text-blue-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">CloudFront</span>
<span class="bg-purple-900 text-purple-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Azure Blob</span>
<span class="bg-purple-900 text-purple-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Azure CDN</span>
</div>
</div>
<!-- Project 2 -->
<div class="bg-gray-800 rounded-lg p-6 shadow-lg hover:shadow-blue-500/20 transform hover:-translate-y-1 transition-all duration-300">
<h3 class="text-xl font-bold text-white mb-2">Automated Instance Scheduler</h3>
<p class="text-gray-400 mb-4">A serverless function that automatically stops/starts dev VMs to save costs, triggered on a schedule.</p>
<div class="flex space-x-2">
<span class="bg-blue-900 text-blue-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Lambda</span>
<span class="bg-purple-900 text-purple-300 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Azure Functions</span>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact">
<h2 class="text-3xl font-bold mb-4 gradient-text">Get In Touch</h2>
<p class="text-gray-300 mb-6">Feel free to connect with me on professional networks.</p>
<div class="flex space-x-4">
<a href="#" class="bg-gray-700 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition-colors">LinkedIn</a>
<a href="#" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-colors">GitHub</a>
</div>
</section>
</main>
<!-- Footer -->
<footer class="text-center text-gray-500 mt-16">
<p>© <span id="year"></span> Your Name. All rights reserved.</p>
<p>Built with <span class="text-red-400">♥</span> and Cloud Native Services.</p>
</footer>
</div>
<script>
// Set current year in footer
document.getElementById('year').textContent = new Date().getFullYear();
</script>
</body>
</html>

Step 2: Create a CloudFront Distribution (CDN)
The CDN will cache your website at edge locations worldwide, making it fast for all users and providing a place to attach our security layers.
- Navigate to CloudFront: Go to the CloudFront service in the console.
- Create Distribution: Click “Create a CloudFront distribution”.
- Origin Domain: In the “Origin domain” dropdown, select your S3 bucket.
- S3 bucket access (IMPORTANT):
- Choose “Origin access control settings (recommended)”.
- Click “Create control setting”. Keep the defaults and click “Create”.
- A message will appear saying you need to update the S3 bucket policy. There will be a “Copy policy” button. Click it, we’ll use this in a moment.
- Viewer Protocol Policy: Under “Default cache behavior”, set “Viewer protocol policy” to “Redirect HTTP to HTTPS”. This enforces secure connections.
- Web Application Firewall (WAF): For now, select “Do not enable security protections”. We will add the WAF after the distribution is created, which is best practice.
- Default Root Object : Scroll down to the “Settings” section. In the “Default root object” field, enter
index.html
. This tells CloudFront to serve this file when a user visits the root URL. - Create Distribution: Scroll down and click “Create distribution”. It will take about 5-10 minutes to deploy. While it’s deploying, you can proceed to the next step.

Step 3: Secure the S3 Bucket
Now, we’ll apply the policy you copied to give CloudFront permission to read files from your private S3 bucket.
- Go back to S3: Navigate to your bucket.
- Permissions Tab: Click on the “Permissions” tab.
- Bucket Policy: Click “Edit” in the “Bucket policy” section.
- Paste Policy: Paste the JSON policy you copied from the CloudFront settings. It will look something like given below.
- Finally, Save changes. Your bucket is now private but accessible by CloudFront.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::YOUR_AWS_ACCOUNT_ID:distribution/YOUR_CLOUDFRONT_DISTRIBUTION_ID"
}
}
}
]
}
Step 4: Add the Web Application Firewall (WAF)
Finally, let’s add a layer of security.
- Navigate to WAF & Shield: Go to the service in the AWS Console.
- Create Web ACL:
- Resource type: CloudFront distribution.
- Name:
portfolio-waf
. - Click “Add AWS managed rule groups”.
- Add the “Core rule set” and “Known bad inputs rule set”. These protect against the most common attacks like SQL injection and XSS.
- Set the default action to “Allow”.
- In the next step, associate it with your CloudFront distribution.
- Review and create the Web ACL.
Step 5: Access Your Website
You’re all set! Once your CloudFront distribution’s status changes from “Deploying” to “Enabled”, you can access your site.
- Navigate to your CloudFront distribution in the AWS console.
- In the list of distributions, find the “Domain name” column. It will show a URL like
d123abcdef.cloudfront.net
. - Copy this URL and paste it into your browser. Your secure, fast, and professional portfolio website will be live!
Build Portfolio Website Using Azure Services
Services Used
- Storage Account
- Azure Front Door (CDN + WAF)
Step 1: Create a Storage Account
This is Azure’s equivalent of S3 and will hold your website files.
- Navigate to Storage Accounts: In the Azure Portal, search for and select “Storage accounts”.
- Create: Click “Create”.
- Subscription/Resource Group: Select your subscription and create a new resource group (e.g.,
portfolio-rg
). - Storage account name: Give it a unique, lowercase name (e.g.,
yournameportfoliosource
). - Region: Choose a region.
- Performance/Redundancy: Standard / GRS is fine.
- Subscription/Resource Group: Select your subscription and create a new resource group (e.g.,
- Review and Create: Click “Review + create”, then “Create”.
- Enable Static Website:
- Once deployed, go to the storage account.
- In the left menu under “Data management”, click “Static website”.
- Toggle it to Enabled.
- Enter
index.html
as the “Index document name”. - Click Save. This creates a special container called
$web
.
- Upload Files: Navigate to “Containers” in the left menu, click on the
$web
container, and upload yourindex.html
file and other assets. (use the sample html code provided in AWS part)



Step 2: Create Azure Front Door (CDN + WAF)
This single service will handle content delivery, the SSL certificate, and security.
- Search for Azure Front Door: In the portal, search for and select “Front Door and CDN profiles”.
- Create: Click “Create”.
- Compare offerings: Select “Azure Front Door” and click “Continue”.
- Quick Create:
- Resource Group: Select the one you created earlier.
- Name: Give it a name (e.g.,
portfolio-frontdoor
). - Tier: Standard is sufficient.
- Endpoint name: This will be part of your public URL (e.g.,
yourname-portfolio
). The full URL will look likeyourname-portfolio.z01.azurefd.net
. Make a note of this hostname. - Origin type: Select “Storage (static website)”.
- Origin host name: Select your storage account from the dropdown.
- WAF Policy: Click “Create new” to add a security policy.
- Name:
portfolio-waf-policy
. - Click “Create”.
- Name:
- Review and Create: Click “Review + create”, then “Create”. Deployment can take 5-10 minutes.


Step 3: Secure the Storage Account (IMPORTANT)
This is the final, critical step to ensure no one can bypass your WAF and CDN.
- Navigate to your Storage Account.
- Networking: In the left menu under “Security + networking”, click “Networking”.
- Public network access: Under the “Public network access” tab, select “Enabled from selected virtual networks and IP addresses”.
- Save: Click “Save” at the top.
This firewall rule ensures that the only service in the world that can access your storage account is your specific Azure Front Door instance.

Step 4: Access Your Website
You’re all set! There’s no need to configure DNS.
- Navigate to your Azure Front Door profile in the Azure portal.
- On the Overview page, find the “Endpoint hostname”. It will be a URL like
https://yourname-portfolio.z01.azurefd.net
. - Copy this URL and paste it into your browser. Your secure, Azure-hosted portfolio will be live!