{"id":30807,"date":"2026-02-17T15:39:39","date_gmt":"2026-02-17T10:09:39","guid":{"rendered":"https:\/\/opstree.com\/blog\/?p=30807"},"modified":"2026-02-17T15:44:35","modified_gmt":"2026-02-17T10:14:35","slug":"secure-website-hosting-aws-s3-cloudfront-oac","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2026\/02\/17\/secure-website-hosting-aws-s3-cloudfront-oac\/","title":{"rendered":"Secure, Serverless And Private: Hosting Static Sites with AWS S3 And CloudFront OAC"},"content":{"rendered":"<p>Modern platforms demand architectures that are not only fast and scalable but also <em>impossible<\/em> to attack at the storage layer. A static website might seem simple, but hosting it securely on AWS\u2014<strong>without exposing S3 to the public internet<\/strong>\u2014requires careful design.<\/p>\n<p>As part of my DevOps journey, I was given a straightforward but strict objective:<!--more--><\/p>\n<blockquote><p>Host a static site that loads globally fast, while keeping the S3 bucket 100% private. No public access. No website hosting mode. No shortcuts.<\/p><\/blockquote>\n<p>This blog covers the Proof of Concept (PoC) I executed using <a href=\"https:\/\/opstree.com\/blog\/2024\/11\/05\/amazon-s3-security-essentials-protect-your-data-with-these-key-practices\/\" target=\"_blank\" rel=\"noopener\"><strong>Amazon S3<\/strong><\/a>, <strong>CloudFront<\/strong>, and the modern <strong>Origin Access Control (OAC), <\/strong>the secure successor to the legacy Origin Access Identity (OAI).<\/p>\n<p><!-- ===== TABLE OF CONTENTS START ===== --><\/p>\n<div style=\"background: #f8fafc; padding: 18px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: Inter, Arial, sans-serif; margin: 20px 0;\">\n<h2 style=\"margin-top: 0; font-size: 18px;\">Table of Contents<\/h2>\n<ol style=\"margin: 0; padding-left: 18px; line-height: 1.6;\">\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#goal-secure-serverless-architecture\">Goal: A Secure, Serverless, Zero-Exposure Architecture<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#architecture-overview\">Architecture Overview<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#phase-1-private-storage\">Phase 1 &#8211; Private Storage Setup (S3)<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#phase-2-cdn-setup\">Phase 2 &#8211; CDN Setup Using CloudFront (New Wizard Flow)<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#phase-3-security-handshake\">Phase 3 &#8211; The Security Handshake (Bucket Policy)<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#phase-4-verification\">Phase 4 &#8211; Verification (Trust, but Verify)<br \/>\n<\/a><\/li>\n<li><a style=\"text-decoration: none; color: #2563eb;\" href=\"#final-outcome\">Final Outcome<\/a><\/li>\n<\/ol>\n<\/div>\n<p><!-- notionvc: 5cb01222-be11-4e20-9095-4069c63fcc89 --><\/p>\n<h2 id=\"goal-secure-serverless-architecture\">Goal: A Secure, Serverless, Zero-Exposure Architecture<\/h2>\n<p>The architecture needed to satisfy three non-negotiable conditions:<\/p>\n<ol>\n<li><strong>The S3 bucket must block all public access<\/strong><\/li>\n<li><strong>CloudFront must serve the content securely over HTTPS<\/strong><\/li>\n<li><strong>Only <a href=\"https:\/\/opstree.com\/blog\/2024\/11\/26\/understanding-oai-and-oac-in-aws-cloudfront-concepts-configuration-and-best-practices\/\" target=\"_blank\" rel=\"noopener\">CloudFront<\/a> should be able to read from S3<\/strong>, enforced by cryptographic OAC signing<\/li>\n<\/ol>\n<p>In short: <strong>Global speed on the front, private storage at the back.<\/strong><\/p>\n<div style=\"border: 1px solid #d1d5db; padding: 16px; margin: 20px 0; background-color: #f0f4f8;\">\n<p style=\"margin: 0; font-weight: 600; font-size: 16px;\"><strong>Designing secure, zero-exposure architectures like this is often easier and faster when working with a <a href=\"https:\/\/opstree.com\/aws-partner\/\" target=\"_blank\" rel=\"noopener\">certified AWS Partner<\/a> who understands compliance, scalability, and modern cloud best practices.<\/strong><\/p>\n<\/div>\n<h2 id=\"architecture-overview\">Architecture Overview<\/h2>\n<p>Below is the exact flow the PoC implements:<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-30808 size-large\" src=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM-1024x628.png\" alt=\"\" width=\"840\" height=\"515\" srcset=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM-1024x628.png 1024w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM-300x184.png 300w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM-768x471.png 768w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM-1200x736.png 1200w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.31.43\u202fPM.png 1412w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<div style=\"overflow-x: auto; width: 100%; margin: 20px 0;\">\n<table style=\"width: 100%; min-width: 700px; border-collapse: collapse; border: 1px solid #e5e7eb; font-size: 14px;\">\n<thead>\n<tr style=\"background: #f8fafc;\">\n<th style=\"border: 1px solid #e5e7eb; padding: 12px; text-align: left;\">Component<\/th>\n<th style=\"border: 1px solid #e5e7eb; padding: 12px; text-align: left;\">Purpose<\/th>\n<th style=\"border: 1px solid #e5e7eb; padding: 12px; text-align: left;\">Security Mechanism<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">S3 Bucket<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Stores static files<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Block Public Access + Restrictive Bucket Policy<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">CloudFront CDN<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Serves users globally<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">HTTPS enforced<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Origin Access Control (OAC)<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Authenticates CloudFront \u2192 S3<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 12px;\">Cryptographic signing + SourceArn restriction<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>The key upgrade here is <span class=\"notion-enable-hover\" data-token-index=\"1\">OAC<\/span>, which AWS now recommends over the older OAI method because it works across all S3 regions and supports full SSE-KMS compatibility.<!-- notionvc: 63f8af5a-6e56-4b07-88fc-6989056ec7aa --><\/p>\n<h2 id=\"phase-1-private-storage\">Phase 1 &#8211; Private Storage Setup (S3)<\/h2>\n<h3>Challenge<\/h3>\n<p>Static website hosting mode requires public read access\u2014even if you don\u2019t want it.<\/p>\n<h3>Solution<\/h3>\n<p>I created an S3 bucket (example: <code>s3-cdn-ninja-bucket<\/code>) with:<\/p>\n<ul>\n<li><strong>Block All Public Access \u2192 ON (mandatory)<\/strong><\/li>\n<li><strong>SSE-S3 encryption<\/strong><\/li>\n<li>Uploaded a basic <code>index.html<\/code><\/li>\n<\/ul>\n<p>Even with a misconfigured policy, \u201cBlock Public Access\u201d guarantees that the bucket stays private.<\/p>\n<h3>Why This Matters<\/h3>\n<p>This ensures the storage layer is fully isolated from the public internet, satisfying zero-exposure compliance requirements.<\/p>\n<div style=\"border: 1px solid #d1d5db; padding: 16px; margin: 20px 0; background-color: #f0f4f8;\">\n<p style=\"margin: 0; font-weight: 600; font-size: 16px;\">Also Read- <a href=\"https:\/\/opstree.com\/blog\/2026\/02\/10\/event-hub-vs-confluent-cloud\/\" target=\"_blank\" rel=\"noopener\">Event Hub vs Confluent Cloud: Which One Should You Use and When?\u00a0<\/a><\/p>\n<\/div>\n<h2 id=\"phase-2-cdn-setup\">Phase 2 &#8211; CDN Setup Using CloudFront (New Wizard Flow)<\/h2>\n<h3>Challenge<\/h3>\n<p>How do you let CloudFront access a <em>private<\/em> S3 bucket without exposing credentials or making the bucket public?<\/p>\n<h3>Solution &#8211; Using OAC (Origin Access Control)<\/h3>\n<p>AWS recently updated the CloudFront setup wizard with a new \u201cRecommended\u201d option that:<\/p>\n<ul>\n<li>Creates the OAC automatically<\/li>\n<li>Links it to the S3 origin<\/li>\n<li>Simplifies configuring the bucket policy<\/li>\n<\/ul>\n<p>My distribution configuration included:<\/p>\n<div style=\"overflow-x: auto; width: 100%; margin: 20px 0;\">\n<table style=\"width: 100%; min-width: 480px; border-collapse: collapse; border: 1px solid #e5e7eb; font-size: 14px;\">\n<thead>\n<tr style=\"background: #f8fafc;\">\n<th style=\"border: 1px solid #e5e7eb; padding: 10px; text-align: left;\">Setting<\/th>\n<th style=\"border: 1px solid #e5e7eb; padding: 10px; text-align: left;\">Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Origin Domain<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Private S3 bucket<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Origin Access<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">OAC (Recommended)<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Viewer Protocol<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Redirect HTTP \u2192 HTTPS<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Cache Policy<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\"><strong>CachingOptimized<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Default Root Object<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\"><strong>index.html<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-30810 size-large\" src=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-1024x666.png\" alt=\"\" width=\"840\" height=\"546\" srcset=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-1024x666.png 1024w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-300x195.png 300w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-768x499.png 768w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-1536x999.png 1536w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-2048x1332.png 2048w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.52\u202fPM-1200x780.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<h3>The Gotcha I Encountered<\/h3>\n<p>At first, <code>https:\/\/xyz.cloudfront.net<\/code> returned <strong>403 Access Denied<\/strong>.<\/p>\n<p>The root cause? <strong>CloudFront didn\u2019t know which file to serve.<\/strong><\/p>\n<p>Setting <strong>Default Root Object = index.html<\/strong> fixed it instantly.<\/p>\n<h3>Why OAC Works Better Than OAI<\/h3>\n<ul>\n<li>No regional limitations<\/li>\n<li>Works seamlessly with SSE-KMS<\/li>\n<li>Uses the <a href=\"https:\/\/opstree.com\/services\/cloud-migration-and-modernization-services\/\" target=\"_blank\" rel=\"noopener\">CloudFront service<\/a> principal + SourceArn condition<\/li>\n<li>More secure and future-proof<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-30811 size-large\" src=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-1024x666.png\" alt=\"\" width=\"840\" height=\"546\" srcset=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-1024x666.png 1024w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-300x195.png 300w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-768x499.png 768w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-1536x999.png 1536w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-2048x1332.png 2048w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.03.36\u202fPM-1200x780.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<h2 id=\"phase-3-security-handshake\">Phase 3 &#8211; The Security Handshake (Bucket Policy)<\/h2>\n<p>Even with OAC, CloudFront still needs explicit permission to fetch objects.<\/p>\n<p>Here is the restrictive policy I applied:<\/p>\n<pre style=\"background: #0f172a; color: #e5e7eb; padding: 16px; border-radius: 8px; font-size: 14px; line-height: 1.6; overflow-x: auto; max-width: 100%;\">{\r\n  \"Version\": \"2012-10-17\",\r\n  \"Statement\": [\r\n    {\r\n      \"Sid\": \"AllowCloudFrontServicePrincipal\",\r\n      \"Effect\": \"Allow\",\r\n      \"Principal\": {\r\n        \"Service\": \"cloudfront.amazonaws.com\"\r\n      },\r\n      \"Action\": \"s3:GetObject\",\r\n      \"Resource\": \"arn:aws:s3:::my-private-site-intern-task-2024\/*\",\r\n      \"Condition\": {\r\n        \"StringEquals\": {\r\n          \"AWS:SourceArn\": \"arn:aws:cloudfront::YOUR_ACCOUNT_ID:distribution\/YOUR_DISTRIBUTION_ID\"\r\n        }\r\n      }\r\n    }\r\n  ]\r\n}\r\n<\/pre>\n<h3>Why This Works<\/h3>\n<p><a href=\"https:\/\/docs.aws.amazon.com\/AmazonCloudFront\/latest\/DeveloperGuide\/private-content-restricting-access-to-s3.html\" target=\"_blank\" rel=\"noopener\">CloudFront<\/a> sends a signed request \u2192 S3 verifies the signature \u2192 grants access <strong>only if<\/strong> the request came from the exact distribution we configured.<\/p>\n<p>No public access. No backdoors.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-30812 size-large\" src=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-1024x666.png\" alt=\"\" width=\"840\" height=\"546\" srcset=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-1024x666.png 1024w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-300x195.png 300w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-768x499.png 768w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-1536x999.png 1536w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-2048x1332.png 2048w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.06.50\u202fPM-1200x780.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<h2 id=\"phase-4-verification\">Phase 4 &#8211; Verification (Trust, but Verify)<\/h2>\n<p>I validated the setup using two tests:<\/p>\n<h3><strong>Test 1 &#8211; Direct S3 Access (Expected Failure)<\/strong><\/h3>\n<p>URL:<\/p>\n<p><code>https:\/\/[bucket].s3.amazonaws.com\/index.html<\/code><\/p>\n<p>Result: <strong>403 Forbidden<\/strong><\/p>\n<ul>\n<li>Confirms the bucket is private.<\/li>\n<\/ul>\n<p><!-- notionvc: 9cd98188-5295-459f-8e42-fd5e2cc8128c --><\/p>\n<p><!-- notionvc: 727e2bc6-e45f-412e-9b5b-35c334f90010 --><\/p>\n<h3><strong>Test 2 &#8211; CloudFront Distribution (Expected Success)<\/strong><\/h3>\n<p>URL:<\/p>\n<p><code>https:\/\/[distribution].cloudfront.net<\/code><\/p>\n<p>Result: <strong>200 OK<\/strong><\/p>\n<ul>\n<li>Page loads successfully<\/li>\n<li>Confirms OAC + bucket policy is correctly implemented<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-30813 size-large\" src=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-1024x729.png\" alt=\"\" width=\"840\" height=\"598\" srcset=\"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-1024x729.png 1024w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-300x213.png 300w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-768x546.png 768w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-1536x1093.png 1536w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-2048x1457.png 2048w, https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Screenshot-2025-11-26-at-12.09.29\u202fPM-1200x854.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<h2 id=\"final-outcome\">Final Outcome<\/h2>\n<p>With this PoC, I achieved a fully secure, global static hosting setup that meets modern AWS compliance expectations:<\/p>\n<div style=\"overflow-x: auto; width: 100%; margin: 20px 0;\">\n<table style=\"width: 100%; min-width: 480px; border-collapse: collapse; border: 1px solid #e5e7eb; font-size: 14px;\">\n<thead>\n<tr style=\"background: #f8fafc;\">\n<th style=\"border: 1px solid #e5e7eb; padding: 10px; text-align: left;\">Objective<\/th>\n<th style=\"border: 1px solid #e5e7eb; padding: 10px; text-align: left;\">Result<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">S3 Block Public Access<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">\u2714 Enforced<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">CloudFront HTTPS Delivery<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">\u2714 Enabled<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">OAC + Bucket Policy<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">\u2714 Locked-down<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">Zero S3 Exposure<\/td>\n<td style=\"border: 1px solid #e5e7eb; padding: 10px;\">\u2714 Validated<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><span style=\"font-size: 28px; font-weight: 900;\">Related Searches<\/span><\/p>\n<ul>\n<li><a href=\"https:\/\/opstree.com\/aws-consulting-services\/\">AWS Consulting Service<\/a><\/li>\n<li><a href=\"https:\/\/opstree.com\/blog\/2026\/02\/03\/serverless-log-analytics-aws\/\">From Messy Logs to Structured Analytics using AWS S3, Lambda, and Athena<\/a><\/li>\n<li><a href=\"https:\/\/opstree.com\/blog\/2025\/05\/28\/aws-for-beginners-what-is-it-how-it-works-and-key-benefits\/\">AWS For Beginners: What Is It, How It Works, and Key Benefits<\/a><\/li>\n<\/ul>\n<p><!-- notionvc: a71a2bef-698c-47c9-832f-acb7e67a5b55 --><\/p>\n<p><!-- notionvc: decec3ac-437e-4295-a8c4-2477fd07ea91 --><\/p>\n<p><!-- notionvc: d224d326-0f75-4eb9-be30-41524510f731 --><\/p>\n<p><!-- notionvc: eae01967-6037-47c3-a407-990de0ce96c5 --><\/p>\n<p><!-- notionvc: be7799d0-8925-431b-a7b7-a7b278d2cd3a --><\/p>\n<p><!-- notionvc: 39af6333-1544-4ee7-ae28-d3ca482a2dad --><\/p>\n<p><!-- notionvc: 1e295db2-685d-4cf9-aa6b-c611f87390e5 --><\/p>\n<p><!-- notionvc: 5ce49c02-3492-4eef-9436-34a27b71d488 --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern platforms demand architectures that are not only fast and scalable but also impossible to attack at the storage layer. A static website might seem simple, but hosting it securely on AWS\u2014without exposing S3 to the public internet\u2014requires careful design. As part of my DevOps journey, I was given a straightforward but strict objective:<\/p>\n","protected":false},"author":223652022,"featured_media":30817,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2026\/02\/Untitled-design-1.jpg","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-80T","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/30807"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/223652022"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=30807"}],"version-history":[{"count":8,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/30807\/revisions"}],"predecessor-version":[{"id":30819,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/30807\/revisions\/30819"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/30817"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=30807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=30807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=30807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}