This is my Cloud Portfolio/Blog project. It's a static Astro website with a serverless AWS backend featuring dual test and production environments. Lambda handles visitor tracking, DynamoDB for state, and automated CI/CD via Terraform and GitHub Actions.
Visit my site here! Kaleb Castillo
π The frontend is a static Astro website hosted on S3. Route53 manages DNS, pointing to a Cloudfront distribution for CDN.
- Here is the Astro template I used: fuwari
ποΈ The backend visitor counter feature is a Lambda function written in Python which queries DynamoDB for view counts.
- I followed Rishab Kumar's Guide
π Dual environments, test and production, are managed through Terraform and GitHub Actions. The infrastructure uses modular design with separate test.tfvars and prod.tfvars files, each with their own S3 backend Terraform state. This enables seamless CI/CD workflows. The test environment deploys automatically while the production environment requires a manual approval following successful tests.
I've designed this project so that anyone can fork and deploy it with minimal setup. Use it as a template for your own cloud portfolio.
- π Prerequisites
- π Initial Setup
- βοΈ AWS Account Setup
- π§ Configure Local Environment
- π¦ Configure Terraform S3 Backend
- ποΈ Bootstrap Terraform S3 Backend
- β¨ Personalize Your Portfolio
- π§ͺ Deploy to Test Environment
- π Deploy to Production
- π Set Up GitHub Workflows
- π To Do
- π€ Contributions
- π License
Before starting, ensure you have the following installed and configured:
-
VS Code with WSL (I use Ubuntu)
- Setup WSL
- Download VS Code
- Install the "Remote - WSL" extension
- Install the "Dev Containers" extension
-
Git
sudo apt-get update && sudo apt-get install git -
Docker Desktop - For the Devcontainer
- Download
- After installation, ensure Docker daemon is running
-
Terraform - IaC
- Installation Steps
- Verify installation:
terraform version
-
Node.js - Optional for local testing
git clone https://github.com/<YOUR_PROFILE>/<YOUR_REPO>.gitVS Code will detect the dev container and prompt you to reopen in container. Click "Reopen in Container" when prompted.
- Go to AWS Console
- Create your account and add payment information.
- Go to Route53 in AWS Console
- Click Domains β Register domain
- Search for and purchase your domain
- Route53 will automatically create the hosted zone
- Go to IAM in AWS Console
- Click Users β Create User
- Enter username:
terraform - On Permissions page, select "Attach policies directly"
- Search for and attach:
AdministratorAccess(temporarily) - Next β Create User
- Go to Security Credentials tab
- Create Access Key
- Choose "Local code/AWS CLI"
- Next β Create Access Key
- Save your Access Key ID and Secret Access Key - you'll need these
Now replace the broad permissions with a more restrictive policy:
- Copy the policy from
terraform-policy.jsonin the project root - Go to your Terraform user
- Add permissions β Create inline policy
- Choose JSON tab
- Paste the policy
- Click Create policy
- Remove the
AdministratorAccesspolicy
Create a credentials file on your local machine:
mkdir -p ~/.aws
touch ~/.aws/credentials
chmod 600 ~/.aws/credentialsAdd the profile
[terraform]
aws_access_key_id = <YOUR_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>
region = <YOUR_REGION># Test that Terraform can access AWS
aws sts get-caller-identity --profile terraform
# You should see output like:
# {
# "UserId": "...",
# "Account": "123456789",
# "Arn": "arn:aws:iam::123456789:user/terraform"
# }Edit infra/test.tfvars and infra/prod.tfvars with your information.
Edit infra/backend/test-backend.hcl and infra/backend/prod-backend.hcl with your information.
The "backend" folder contains the infrastructure for Terraform state management. You only need to do this once.
cd infra/backendterraform initterraform applyReview the resources to be created and apply.
Visit the Astro template repo for a usage guide. But here are some pointers:
Edit site/src/config.ts:
Edit site/src/content/spec/about.md
Edit site/src/components/Footer.astro
Use the built-in script to create new posts:
cd site
pnpm new-post <post_title>First test that the site builds correctly:
cd site
pnpm install
pnpm buildRun the local dev environment and view the site at http://localhost:4321
pnpm devcd infra
terraform init -backend-config="backend/test-backend.hcl"
# When asked to copy existing state, type "no"terraform plan -var-file="test.tfvars"terraform apply -var-file="test.tfvars"aws s3 sync site/dist/ s3://your_test_bucket/ --delete --profile terraform- Visit your test site URL
- Verify everything looks correct
cd infra
terraform init -backend-config="backend/prod-backend.hcl"
# When asked about existing state, type "no"- Follow Steps from test, but use "prod.tfvars"
terraform plan -var-file="prod.tfvars"
terraform apply -var-file="prod.tfvars"
aws s3 sync site/dist/ s3://your_prod_bucket/ --delete --profile terraformAdd these Actions Secrets to your repo:
Name: AWS_ACCESS_KEY_ID
Value: Your Key ID
Name: AWS_SECRET_ACCESS_KEY
Value: Your Key
The GitHub Actions workflow is configured in .github/workflows/deploy.yml. When you push to main, it will:
- Run code quality checks for Astro content
- Build the site
- Deploy to test environment
- Run tests
- Await manual approval before production
- Deploy to production upon approval
Make sure to make adjustments to the deploy.yml as necessary with your information.
Now you can develop your blog locally. Pushes to your repo will deploy straight to AWS.
- Improve tests.
- Implement ephemeral preview environments.
Feel free to contribute! I'm always learning and will be glad to improve this project further.
This project is licensed under the MIT License.