Provision infrastructure with Terraform
Use Terraform to provision an S3 bucket with versioning enabled, a CloudFront distribution fronting it, and an Origin Access Identity so the bucket is only accessible via CloudFront. Write the configuration, run terraform plan and apply, then destroy and recreate it cleanly to confirm there is no state drift.
Why this matters
Manually provisioned infrastructure is infrastructure that cannot be reproduced, audited, or handed off. Terraform turns infrastructure into reviewable code and makes disaster recovery a matter of running one command. The destroy-and-recreate discipline catches the difference between what your code says and what AWS actually created.
Before you start
- Terraform installed (terraform --version works)
- AWS account with S3 and CloudFront permissions
- AWS CLI configured
- Basic understanding of what S3 and CloudFront are at a conceptual level
Step-by-step guide
- 1
Write the S3 bucket resource
Define an aws_s3_bucket resource with a unique name. Add aws_s3_bucket_versioning to enable versioning, and aws_s3_bucket_public_access_block to block all public access. Run terraform plan; verify the plan shows 3 resources to create before applying.
- 2
Create the Origin Access Identity
Define an aws_cloudfront_origin_access_identity resource. Then write an aws_s3_bucket_policy that allows only the OAI's principal to GetObject from the bucket. This is the pattern that keeps your bucket private while allowing CloudFront to serve from it.
- 3
Write the CloudFront distribution
Define an aws_cloudfront_distribution with the S3 bucket as origin, the OAI attached, HTTPS redirect enforced, and a price_class of PriceClass_100 (cheapest, US/EU only). Output the distribution domain name so you can test it.
- 4
Apply and verify
Run terraform apply. Upload a test file to the S3 bucket and fetch it via the CloudFront domain. Confirm direct S3 access returns a 403. Confirm CloudFront access returns a 200. Check the Terraform state file to understand what state drift would look like.
- 5
Destroy and recreate
Run terraform destroy --auto-approve. Verify everything is gone in the AWS console. Run terraform apply again. Compare the output of both applies; they should be identical. If there are differences, your configuration is not fully declarative.