Deployment Architecture

Last Updated: 2026-01-17

Overview

The ConstructiVision project uses a fully automated CI/CD pipeline to deploy the static website from the /webpage directory to AWS infrastructure. The pipeline leverages GitHub Actions with OpenID Connect (OIDC) authentication for secure, credential-free deployments to S3 and CloudFront.

Production URL: https://simplestruct.com

Architecture Diagram

â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   Developer     â"'
â"'   Local Machine â"'
â""â"â"â"â"â"â"â"â"â"¬â"â"â"â"â"â"â"â"â"~
         â"' git push
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   GitHub Repository                 â"'
â"'   ConstructiVision/ConstructiVision â"'
â"'   Branch: main                      â"'
â""â"â"â"â"â"â"â"â"â"¬â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~
         â"' Trigger on webpage/** changes
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   GitHub Actions Workflow           â"'
â"'   .github/workflows/deploy.yml      â"'
â"'                                     â"'
â"'   1. Checkout code                  â"'
â"'   2. Request OIDC token from GitHub â"'
â"'   3. Exchange token for AWS creds   â"'
â"'   4. Sync to S3                     â"'
â"'   5. Invalidate CloudFront cache    â"'
â""â"â"â"â"â"â"â"â"â"¬â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~
         â"' OIDC Authentication
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   AWS IAM                           â"'
â"'   OIDC Provider: GitHub             â"'
â"'   Role: github-actions-deploy-role  â"'
â"'   Trust Policy: repo:ConstructiV... â"'
â""â"â"â"â"â"â"â"â"â"¬â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~
         â"' Assume Role
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   Amazon S3                         â"'
â"'   Bucket: simplestruct-site-2026... â"'
â"'   Access: Private (OAC only)        â"'
â"'   Content: /webpage files           â"'
â""â"â"â"â"â"â"â"â"â"¬â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~
         â"' Origin Access Control
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   Amazon CloudFront                 â"'
â"'   Distribution: EN0U7UU9TSIOY       â"'
â"'   Domain: simplestruct.com          â"'
â"'   Caching: Standard (24hr)          â"'
â""â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~
         â"'
         â-¼
â"OEâ"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"
â"'   End Users     â"'
â"'   Web Browsers  â"'
â""â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"â"~

Components

1. Source Control (GitHub)

  • Repository: ConstructiVision/ConstructiVision

  • Branch: main

  • Deployment Source: /webpage directory

  • Workflow File: .github/workflows/deploy.yml

Trigger Conditions:

on:
  push:
    branches: [main]
    paths:
      - 'webpage/**'

Any push to the main branch that includes changes in the webpage/ directory triggers the deployment workflow.

2. GitHub Actions Workflow

File: .github/workflows/deploy.yml

Key Configuration:

SOURCE_DIR: ./webpage
S3_BUCKET: simplestruct-site-2026-0001
CLOUDFRONT_DISTRIBUTION_ID: EN0U7UU9TSIOY

Workflow Steps:

  1. Checkout Repository

    • Uses actions/checkout@v4 to clone the repository

  2. Verify Source Directory

    • Ensures /webpage directory exists before proceeding

    • Fails fast if source directory is missing

  3. Configure AWS Credentials (OIDC)

    • Uses aws-actions/configure-aws-credentials@v4

    • Requests OIDC token from GitHub’s token service

    • Exchanges token with AWS STS to assume IAM role

    • No long-lived credentials stored in repository

  4. S3 Sync

    • Command: aws s3 sync ./webpage s3://simplestruct-site-2026-0001/ --delete

    • --delete removes files from S3 that don’t exist locally

    • Sets cache-control headers for optimal performance:

      • HTML: no-cache (always check for updates)

      • CSS/JS: max-age=31536000 (cache for 1 year)

      • Images: max-age=2592000 (cache for 30 days)

  5. CloudFront Invalidation

    • Command: aws cloudfront create-invalidation --distribution-id EN0U7UU9TSIOY --paths "/*"

    • Clears all cached content to ensure immediate updates

    • Full invalidation (/*) for simplicity (optimized per-path invalidation possible in future)

3. Authentication (OIDC)

Why OIDC over Access Keys?

  • No long-lived credentials stored in GitHub Secrets

  • Automatic credential rotation (tokens expire after use)

  • Fine-grained permissions with IAM role trust policies

  • Audit trail shows which workflow assumed which role

OIDC Provider Configuration:

  • Provider URL: https://token.actions.githubusercontent.com

  • Audience: sts.amazonaws.com

  • Thumbprint: GitHub’s SSL certificate thumbprint

Trust Policy: The IAM role only accepts tokens from:

  • Repository: ConstructiVision/ConstructiVision

  • Branch: main

  • Any other repository or branch cannot assume this role

Trust Policy Example:

{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::760725376032:oidc-provider/token.actions.githubusercontent.com"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
      "token.actions.githubusercontent.com:sub": "repo:ConstructiVision/ConstructiVision:ref:refs/heads/main"
    }
  }
}

4. IAM Role and Permissions

Role Name: github-actions-deploy-role
Role ARN: arn:aws:iam::760725376032:role/github-actions-deploy-role

Permissions Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::simplestruct-site-2026-0001",
        "arn:aws:s3:::simplestruct-site-2026-0001/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateInvalidation"
      ],
      "Resource": "arn:aws:cloudfront::760725376032:distribution/EN0U7UU9TSIOY"
    }
  ]
}

Security Notes:

  • Least privilege: Only S3 and CloudFront permissions granted

  • Resource-specific: Cannot access other S3 buckets or CloudFront distributions

  • Write-only S3 access: Cannot read sensitive configuration files

5. Amazon S3 Storage

Bucket Name: simplestruct-site-2026-0001
Region: us-east-1
Access: Private (not publicly accessible)

Bucket Configuration:

  • Block Public Access: Enabled (all 4 settings)

  • Versioning: Disabled

  • Encryption: Default (SSE-S3)

  • Access Method: CloudFront Origin Access Control (OAC) only

Bucket Policy: Grants CloudFront distribution EN0U7UU9TSIOY permission to read objects via OAC.

6. Amazon CloudFront CDN

Distribution ID: EN0U7UU9TSIOY
Domain: simplestruct.com
Origin: simplestruct-site-2026-0001.s3.us-east-1.amazonaws.com

Cache Behavior:

  • Default TTL: 86400 seconds (24 hours)

  • Min TTL: 0 seconds

  • Max TTL: 31536000 seconds (1 year)

  • Cache-Control: Honors origin headers from S3 sync

Origin Access:

  • Method: Origin Access Control (OAC)

  • Legacy OAI: Not used (deprecated by AWS)

  • Direct S3 Access: Blocked

SSL/TLS:

  • Certificate: AWS Certificate Manager (ACM)

  • Minimum TLS: TLSv1.2

  • HTTPS: Enforced (HTTP redirects to HTTPS)

Infrastructure as Code (Terraform)

Directory: /terraform
Main File: github-oidc-deploy.tf

Resources Managed:

  1. aws_iam_openid_connect_provider.github - GitHub OIDC provider

  2. aws_iam_role.github_actions_deploy - Deployment role with trust policy

  3. aws_iam_role_policy.github_actions_deploy_policy - Inline permissions policy

Terraform Variables:

github_org                   = "ConstructiVision"
github_repo                  = "ConstructiVision"
github_branch                = "main"
aws_account_id               = "760725376032"
s3_bucket_name               = "simplestruct-site-2026-0001"
cloudfront_distribution_id   = "EN0U7UU9TSIOY"

Terraform Outputs:

  • deploy_role_arn - Used in GitHub Actions workflow

  • deploy_role_name - For reference

  • oidc_provider_arn - For audit/verification

Initial Setup (One-Time)

The IAM infrastructure was created via Terraform:

cd terraform
terraform init
terraform plan
terraform apply

Bootstrap Permissions: Terraform required temporary IAM creation permissions via iam-bootstrap-policy.json, which was attached to the deploying user and removed after infrastructure creation.

Deployment Flow

Developer Workflow

  1. Make Changes

    cd C:\Users\chadw\Constructivision\webpage
    # Edit files (index.html, css, js, etc.)
    
  2. Commit and Push

    git add webpage/
    git commit -m "Update site content"
    git pull --rebase
    git push
    
  3. Automatic Deployment

    • GitHub Actions detects changes in webpage/**

    • Workflow runs automatically (2-3 minutes)

    • Site updates at simplestruct.com

  4. Verify Deployment

    • Check GitHub Actions workflow status at: https://github.com/ConstructiVision/ConstructiVision/actions

    • Visit https://simplestruct.com to see changes

    • CloudFront invalidation ensures immediate visibility

Monitoring and Troubleshooting

GitHub Actions Logs:

  • Navigate to repository â-’ Actions tab

  • Click on latest “Deploy SimpleStruct (S3 + CloudFront)” workflow

  • Expand steps to view detailed logs

Common Issues:

  1. Workflow doesn’t trigger

    • Verify changes are in webpage/ directory

    • Check branch is main

    • Confirm push succeeded (git log --oneline -1)

  2. OIDC authentication fails

    • Verify IAM role ARN in deploy.yml matches Terraform output

    • Check trust policy allows repository and branch

    • Confirm OIDC provider exists in AWS IAM

  3. S3 sync fails

    • Check IAM role has s3:PutObject, s3:DeleteObject, s3:ListBucket permissions

    • Verify bucket name is correct

    • Ensure bucket exists in us-east-1

  4. CloudFront invalidation fails

    • Check IAM role has cloudfront:CreateInvalidation permission

    • Verify distribution ID is correct

    • Confirm distribution is deployed (not in progress)

  5. Site shows old content

    • Wait 2-3 minutes for CloudFront invalidation

    • Check CloudFront invalidation status in AWS console

    • Try hard refresh in browser (Ctrl+Shift+R)

Manual Verification Commands:

# Check S3 bucket contents
aws s3 ls s3://simplestruct-site-2026-0001/

# Check CloudFront distribution status
aws cloudfront get-distribution --id EN0U7UU9TSIOY

# List recent invalidations
aws cloudfront list-invalidations --distribution-id EN0U7UU9TSIOY

Security Considerations

Principle of Least Privilege

  • IAM role has minimal permissions (S3 write, CloudFront invalidate only)

  • Trust policy restricts role assumption to specific repository and branch

  • S3 bucket is private (no public access)

Credential Management

  • No AWS access keys stored in GitHub

  • OIDC tokens are short-lived (expire after workflow completion)

  • Credentials never appear in logs

Audit Trail

  • GitHub Actions logs show all deployments

  • CloudTrail logs show all AWS API calls

  • S3 access logs can be enabled if needed

Performance Optimization

Caching Strategy

HTML Files: Cache-Control: no-cache

  • Browsers always check server for updates

  • Ensures users see latest content

  • CloudFront still caches but revalidates with origin

CSS/JS Files: Cache-Control: max-age=31536000

  • Cached for 1 year (immutable)

  • Use cache-busting techniques:

    • Query strings: style.css?v=1.2.3

    • Hashed filenames: style.a3f7b9.css

Images: Cache-Control: max-age=2592000

  • Cached for 30 days

  • Balance between freshness and performance

CloudFront Edge Locations

  • Content cached at edge locations worldwide

  • Reduced latency for global users

  • Automatic geographic routing

S3 Transfer Acceleration

  • Not currently enabled

  • Consider enabling for faster uploads from distant regions

  • Adds cost but improves deployment speed

Cost Management

Monthly Estimated Costs (low traffic site):

  • S3 storage: ~$0.02/GB/month (minimal for static site)

  • S3 requests: ~$0.005 per 1,000 GET requests

  • CloudFront data transfer: First 1 TB free, then ~$0.085/GB

  • CloudFront requests: ~$0.01 per 10,000 HTTPS requests

  • Total: Likely under $5/month for typical traffic

Cost Optimization Tips:

  • Use aggressive caching to reduce origin requests

  • Optimize image sizes to reduce data transfer

  • Consider S3 Intelligent-Tiering for infrequently accessed content

  • Monitor CloudFront invalidation costs (first 1,000 paths free per month)

Future Enhancements

Potential Improvements

  1. Staging Environment

    • Create separate S3 bucket + CloudFront distribution

    • Deploy develop branch to staging for testing

    • Manual approval gate before production deployment

  2. Optimized Invalidations

    • Instead of /*, invalidate only changed files

    • Reduces invalidation costs for large sites

    • Requires tracking file changes in workflow

  3. Asset Optimization Pipeline

    • Minify CSS/JS in GitHub Actions before upload

    • Compress images automatically

    • Generate multiple image sizes for responsive design

  4. Blue-Green Deployments

    • Use CloudFront origin groups

    • Deploy to alternate S3 bucket

    • Switch origin if health checks pass

  5. Monitoring and Alerts

    • CloudWatch alarms for 4xx/5xx errors

    • SNS notifications for failed deployments

    • Real user monitoring (RUM) via CloudWatch

  6. Content Versioning

    • Enable S3 versioning for rollback capability

    • Implement workflow to revert to previous version

    • Store deployment history metadata

Reference Documentation

  • Terraform Configuration: /terraform/github-oidc-deploy.tf

  • GitHub Actions Workflow: .github/workflows/deploy.yml

  • Deployment Guide: /DEPLOYMENT.md

  • AWS OIDC Setup: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html

  • GitHub Actions OIDC: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

Support

For issues or questions:

  1. Check GitHub Actions workflow logs

  2. Review this architecture document

  3. Consult DEPLOYMENT.md for troubleshooting steps

  4. Check AWS CloudTrail for API call history


Document Owner: ConstructiVision Development Team
Review Schedule: Quarterly or after major architecture changes