dev@portfolio:~
back to projects
>_

Portfolio Delivery

Infrastructure behind this portfolio

This portfolio is also a live infrastructure project: provisioned with Terraform, deployed through GitHub Actions using AWS OIDC, and delivered globally through CloudFront from a private S3 origin.

Infrastructure / DevOps • View on GitHub ↗

  • Terraform
  • AWS
  • CloudFront
  • S3
  • GitHub Actions
  • OIDC
  • Cloudflare
Status
● Live
Type
Infrastructure
Environment
Dev
Delivery
Global CDN
Origin
Private S3

Global HTTPS Delivery

CloudFront delivers the site globally with TLS and modern security headers.

Private Origin

Content is stored in a private S3 bucket and accessed via CloudFront and OAC.

Keyless CI/CD

GitHub Actions deploys with AWS OIDC—no long-lived AWS credentials.

Visitors reach the portfolio through Cloudflare DNS. Traffic is served by CloudFront over HTTPS. CloudFront accesses a private S3 origin through Origin Access Control. Infrastructure is provisioned with Terraform.

Public entry point

CloudFront is the only public entry point and handles TLS, caching, and security headers.

Private origin

The S3 bucket remains private and is reachable only through CloudFront using OAC.

Infrastructure ownership

Terraform provisions the infrastructure and GitHub Actions handles automated delivery.

Portfolio Infrastructure

✓

Private by default

Content stays in a private S3 bucket and is only accessible through OAC.

✓

Global HTTPS delivery

CloudFront delivers content over HTTPS with low latency and automatic TLS.

✓

Cost-conscious design

Leverages caching and serverless services to keep operating costs low.

Terraform keeps the portfolio infrastructure reproducible and low-maintenance by composing focused modules around a single environment root. The design separates backend bootstrap, runtime resources, and CI/CD identities while keeping the deployment workflow straightforward.

Remote state

Encrypted S3 backend with native .tflock locking.

Focused modules

Small modules with explicit responsibilities and clear contracts.

Explicit dependencies

Outputs connect modules and make resource relationships visible.

Infrastructure structure

terraform/
├── bootstrap/
│   └── backend/
└── environments/
    ├── dev/
    └── modules/
        ├── s3/
        ├── acm-cloudflare/
        ├── cloudfront/
        ├── cloudflare-dns/
        ├── github-actions-iam/
        └── monitoring/

Design principles

  • Single dev root module
  • AWS provider alias us_east_1
  • Module contracts through inputs and outputs
  • Terraform validation and policy checks in CI

Module responsibilities

s3

Private origin bucket and CloudFront access logs bucket

acm-cloudflare

ACM certificate and Cloudflare DNS validation

cloudfront

CDN, OAC, security headers, caching, logging and error handling

cloudflare-dns

Public DNS records pointing to the CloudFront distribution

github-actions-iam

OIDC provider, scoped roles, policies and permissions boundary

monitoring

CloudFront 4xx/5xx alarms and operational visibility

  • ✓Reproducible infrastructure
  • ✓Cross-provider automation
  • ✓Low operational complexity

Automated delivery and explicit trust boundaries keep AWS credentials temporary, permissions scoped, and infrastructure and content delivery responsibilities separate.

Delivery pipelines

01

Infrastructure pipeline

PRs run static validation only. Push and manual runs revalidate, pass through the dev environment, assume the Terraform role, then run init, plan and apply.

02

Website delivery pipeline

PRs validate the build without deploying. Main and manual runs build a fresh artifact, then a restricted publishing role synchronizes S3 metadata and invalidates CloudFront.

Trust boundaries

GitHub Actions

Builds and validates code, requests short-lived AWS access through OIDC, and stores the scoped Cloudflare token in the protected environment.

CI platform

AWS account

Hosts the infrastructure and issues temporary credentials only when repository, audience, and environment claims match.

Cloud boundary

Cloudflare DNS

Terraform manages DNS records through a separately scoped API token, independent of the AWS IAM roles.

DNS provider

Privileged bootstrap identity

Creates the backend and initially provisions or changes OIDC and IAM resources outside normal CI/CD.

Operator boundary

Identity & access flow

GitHub Actions

Requests AWS access

→

GitHub OIDC

Issues identity token

→

AWS STS

Returns temporary credentials

Terraform Apply Role

Manages scoped AWS infrastructure. A permissions boundary caps its maximum access and it has no IAM write permissions.

Terraform workflow

Frontend Deploy Role

Publishes website objects and invalidates only the managed CloudFront distribution.

Website workflow

Cloudflare API Token

Authenticates the Cloudflare provider separately for DNS record management.

Separate credential path

Key trust principles

✓

Least privilege

Each AWS role has only the permissions required by its workflow.

✓

Short-lived AWS access

OIDC tokens and STS credentials expire automatically.

✓

Separation of concerns

Infrastructure, website publishing and DNS use distinct authorization paths.

✓

Protected deployments

GitHub Environment protections and reviewers can gate deployments when configured.

✓

No AWS key sprawl

No long-lived AWS access keys are stored as repository or environment secrets.

✓

Delivery traceability

GitHub workflow history, CloudFront access logs and CloudWatch alarms support investigation.

ⓘCI/CD uses GitHub OIDC for AWS access and a separately scoped API token for Cloudflare DNS—no long-lived AWS credentials are stored in GitHub.

1

Private S3 origin

Choice
CloudFront with OAC instead of public S3 website hosting
Why
Keeps the bucket private and makes CloudFront the only public content entry point
Trade-off
Requires additional origin access configuration and bucket policies
2

Cloudflare + ACM

Choice
Keep authoritative DNS in Cloudflare while using ACM and CloudFront for HTTPS
Why
Preserves existing DNS management while keeping content delivery on AWS
Trade-off
Cross-provider Terraform and automated DNS validation add coordination
3

Separate delivery paths

Choice
Split infrastructure changes from website content deployments
Why
HTML, CSS and JavaScript updates do not require a Terraform apply
Trade-off
Requires separate workflows, roles and deployment logic
4

Bootstrap outside CI/CD

Choice
Handle backend and IAM bootstrap outside routine automation
Why
Prevents normal delivery pipelines from controlling their own trust boundary
Trade-off
Sensitive IAM and bootstrap changes remain privileged operator tasks
  • Private by default
  • Least privilege
  • Low operational complexity
1

Single dev environment

Choice
One dev environment keeps the project simple and reproducible.
Trade-off
No staging/production split or artifact promotion workflow.
2

PriceClass_100

Choice
CloudFront edge coverage is intentionally limited to control CDN cost.
Trade-off
Less geographic coverage than broader CloudFront price classes.
3

Full invalidation

Choice
Invalidate the full CloudFront distribution with /* after deployment.
Trade-off
Less efficient than targeted invalidation, but simpler at this scale.
4

Explicit cache strategy

Choice
HTML is no-cache, hashed CSS/JS is immutable, and other assets cache for one hour.
Trade-off
The deployment must apply object metadata in multiple passes.
5

No advanced resilience layer

Choice
No WAF, origin failover, or cross-region replication is provisioned.
Trade-off
Lower complexity and cost, but fewer resilience and edge-security capabilities.
6

Redeploy-based recovery

Choice
Recover a partial or failed publish by redeploying a complete known-good build.
Trade-off
Recovery requires a clean workflow rerun instead of an automatic atomic rollback.
  • Low cost
  • Low maintenance
  • Deliberate scope