Context
This project rebuilds an AWS fundamentals exercise from a cloud bootcamp (account setup, IAM, S3 static hosting, an EC2 instance serving a Streamlit app reading a CSV from S3). Instead of a placeholder page and a tutorial dataset, though, both deployments serve a real artifact from this portfolio's own AE-01: its dbt documentation site, and its dimensional-model market data.
Business Problem
How do you put an Analytics Engineering deliverable, whether that's dbt's auto-generated documentation or a dbt mart itself, in front of someone who won't clone a repo and run dbt docs serve locally? Static hosting and a small serving layer, provisioned as code and secured with least-privilege access, is the minimum real answer.
Architecture
Two independent paths out of the same source project, each demonstrating a different AWS serving pattern: a fully static site behind S3 website hosting, and a private data object served only through an application with a scoped IAM role, never a public HTTP GET.
Data
market_prices.csv:fct_daily_pricesjoined todim_tickers, 5,010 rows, one per ticker per trading day, with sector/industry attached for the dashboard's filters.- dbt docs site:
index.html+manifest.json+catalog.json, regenerated bydbt docs generateagainst AE-01: the same lineage graph AE-01's own README describes, served from a different place. - Both exports are read-only against AE-01. Nothing in this project writes back into AE-01's warehouse or models.
Methodology
- Export (read-only):
scripts/export_marts_to_csv.pyopens AE-01's DuckDB warehouse inread_onlymode. - Infrastructure as code: Terraform defines every resource: two S3 buckets, one EC2 instance behind a security group open only on 22 (single trusted CIDR) and 80, one IAM role, one AWS Budgets alert.
- Billing alert first:
budgets.tfhas no dependency on any other resource, so it applies, and must apply, alone, before anything that can incur cost. - App code tested independently of AWS: the Streamlit app reads its data source from an environment variable, a local CSV path today, an
s3://URI in production, same code either way.
Design Decisions
- Least-privilege IAM instead of the bootcamp's admin user. The original exercise attached
AdministratorAccessto a new IAM user. Here the EC2 role can read exactly one S3 bucket and nothing else: no IAM user, no console access created at all. - The data bucket stays private end to end. The bootcamp's version made the bucket public so the app could read the CSV over plain HTTP. This version authenticates as the instance role instead.
- Terraform over console clicks: the deploy is reviewable, reproducible, and fully torn down with
terraform destroyonce the evidence is captured.
Results
terraform apply and the live URLs, is a documented handoff: this environment has no working AWS credentials for a personal account.What's verified without AWS:
- Export script run against the real AE-01 warehouse: 5,010 rows, matches AE-01's published count.
- Streamlit app run locally and screenshotted with real data (charts, filters, KPIs all live).
- dbt docs regenerated from AE-01 and served locally, screenshotted.
Tech Stack
| Category | Tool |
|---|---|
| IaC | Terraform (AWS provider) |
| Compute | EC2 (Amazon Linux 2023, t3.micro) |
| Storage | S3 (static website + private bucket) |
| IAM | Least-privilege instance role |
| Cost control | AWS Budgets |
| App | Streamlit, pandas, boto3/s3fs |