Production-grade AWS Portfolio with Secure Serverless CI/CD.
Designed to demonstrate production-ready cloud engineering practices including Amazon S3, CloudFront, Route 53, AWS WAF, ACM, GitHub Actions, GitHub OIDC federation, cross-account IAM role assumption, and automated deployments using temporary STS credentials. Every deployment is performed without storing long-lived AWS access keys.
infrastructure livezero stored aws keysgithub oidc + stscross-account iam
The project started as a traditional static website uploaded manually to Amazon S3. Every update required manual synchronization and CloudFront cache invalidation.
2. Secure Automation
I replaced manual deployments with GitHub Actions authenticated through GitHub OIDC and AWS STS, eliminating long-lived credentials completely.
3. Enterprise Security
The final design separates deployment and production AWS accounts using cross-account IAM roles, mirroring enterprise landing zone patterns.
show request-flow
Request Lifecycle
Browser
➜
Route53
➜
CloudFront
➜
AWS WAF
➜
Origin Access Control
➜
Amazon S3
Why this matters: Visitors never communicate directly with the S3 bucket. Every request is protected by CloudFront, HTTPS, AWS WAF, and Origin Access Control before reaching the origin.
Design Objective: I wanted this portfolio to resemble a production AWS deployment rather than a simple static website. The architecture emphasizes serverless infrastructure, least-privilege IAM, secure cross-account deployments, and zero long-lived AWS credentials while remaining inexpensive to operate.
Production Architecture — Click to enlarge
Security by design:
The Amazon S3 origin bucket is never publicly accessible. DNS resolution is handled by Route 53, content is delivered through CloudFront, requests are inspected by AWS WAF, and Origin Access Control is the only path to the S3 origin. GitHub Actions authenticates through GitHub OIDC and AWS STS using temporary credentials, eliminating stored AWS access keys.
cat overview.md
No servers. No SSH. No 2am uploads.
laxstack.com is fully serverless — there's no EC2 instance to patch and no origin server
sitting behind the scenes. It's static HTML, CSS, and JavaScript in an S3 bucket, distributed globally through
CloudFront, filtered by WAF before it ever reaches the origin, resolved by Route 53, and encrypted end-to-end
with a certificate ACM renews on its own.
Getting the infrastructure live was only half of this project. The other half was making sure updating the
site never meant manually re-uploading files to S3 or babysitting a cache invalidation by hand — that's
what the GitHub Actions + OIDC pipeline below solves.
show topology
Request Path
The bucket is never exposed directly to the internet — every request is fronted by CloudFront and screened by WAF before it reaches storage.
Manually uploading to S3 and invalidating CloudFront by hand worked, but it wasn't how production gets managed. This is what replaced it.
path — commit to liveclick to expand
6 hops · zero stored aws keys · two aws accounts
show running-config
Deployment Workflow
!01-commit
Developer commits locally and pushes to GitHub.
!02-trigger
A push to the main branch automatically triggers the GitHub Actions deployment workflow.
!03-oidc-auth
GitHub authenticates to AWS via OpenID Connect — no stored access keys.
!04-sts-creds
AWS STS issues short-lived credentials scoped to the deploy role.
!05-s3-sync
Website files sync to the S3 bucket in the free AWS account.
!06-cross-account
The deploy role assumes a role in the paid AWS account via STS.
!07-invalidate
CloudFront cache is invalidated — visitors get the latest build.
show iam trust-policy
Cross-Account Trust
The pipeline spans two AWS accounts — a free account handling deployment, and a paid account holding CloudFront and WAF. Each role can do exactly one thing.
Free AWS Account
Github-website-Deploy
cross-account
AssumeRole via STS
Paid AWS Account
Cloudfront-Invalidation
Github-website-Deploy can
s3:ListBucket
s3:GetObject
s3:PutObject
s3:DeleteObject
sts:AssumeRole
Cloudfront-Invalidation can
cloudfront:CreateInvalidation
the paid account trusts only this one deploy role — nothing else
The trickiest part of this build wasn't the AWS side — it was GitHub's OIDC trust policy. Diagnosing a
failed federation handshake meant decoding the actual JWT claims GitHub was sending and tracing a mismatch back
to GitHub's newer subject-claim format. That's the kind of bug that doesn't show up until federation actually
happens.
GitHub OIDCTemporary STS credentialsLeast-privilege IAMCross-account role assumptionAWS WAF protectionHTTPS via ACMZero stored AWS keys
cat engineering-decisions.md
Engineering Decisions
Why Serverless?
I intentionally avoided EC2 to eliminate operating system maintenance, patching, backups, and unnecessary operational overhead. Static hosting provides high durability with minimal cost.
Why CloudFront?
CloudFront provides global edge caching, TLS termination, Origin Access Control, and seamless integration with AWS WAF, improving both performance and security.
Why GitHub OIDC?
Instead of storing AWS access keys inside GitHub Secrets, GitHub exchanges a signed OIDC token for short-lived AWS STS credentials. No permanent AWS credentials exist in the repository.
Why Two AWS Accounts?
The deployment pipeline and production infrastructure reside in separate AWS accounts. Cross-account IAM role assumption mirrors enterprise environments while enforcing least-privilege access.
cat troubleshooting.log
Engineering Challenges
OIDC Federation
Resolved GitHub OIDC subject-claim mismatches by decoding JWT claims and updating IAM trust policies.
Cross-Account IAM
Designed least-privilege IAM roles allowing deployment and CloudFront invalidation across separate AWS accounts.
Origin Security
Configured Origin Access Control and bucket policies so Amazon S3 is never directly exposed to the Internet.
show metrics
Project Metrics
Deployment
~90 second manual workflow execution from GitHub to production.
Security
Zero long-lived AWS credentials, least-privilege IAM, HTTPS via ACM, AWS WAF, and temporary STS credentials.
Cost
Designed to operate almost entirely within the AWS Free Tier. Primary recurring cost is the Route 53 hosted zone.