In today’s fast-paced development environment, automating repetitive tasks not only saves time but also reduces errors, enhances consistency, and streamlines deployments. Deploying static websites to Amazon S3 (Simple Storage Service) is a popular use case for cloud enthusiasts and developers alike. Amazon S3 provides a robust and cost-effective way to host static content. By combining Terraform—an Infrastructure as Code (IaC) tool—with GitHub Actions for continuous integration and deployment (CI/CD), you can fully automate the deployment of a static website.
In this blog, we’ll walk through the entire process of automating the deployment of a static website on AWS S3 using Terraform and GitHub Actions. By the end, you’ll have a seamless pipeline that provisions the infrastructure and updates your website with minimal manual intervention.
Why Choose Terraform and GitHub Actions?
Before diving into the implementation, it’s important to understand why Terraform and GitHub Actions make an excellent combination for automation.
Terraform
- Infrastructure as Code: Terraform enables you to manage your infrastructure using declarative configuration files. This approach makes it easy to version-control your infrastructure and ensures reproducibility.
- Multi-Cloud Support: Terraform supports multiple cloud providers, allowing you to integrate your infrastructure provisioning into one tool.
- Scalability: It is designed to handle small to large-scale deployments efficiently.
GitHub Actions
- Built-In CI/CD: GitHub Actions provides a native CI/CD solution tightly integrated with your GitHub repositories.
- Event-Driven: Trigger workflows based on specific events, such as a push to the
mainbranch. - Customizable: You can write reusable workflows and integrate third-party actions to suit your needs.
Step 1: Set Up the AWS S3 Bucket
Create an S3 Bucket for Static Website Hosting
To host a static website on S3, the first step is to create a bucket configured for website hosting.
- Login to AWS Management Console:
- Navigate to the S3 dashboard and click “Create bucket.”
- Bucket Configuration:
- Choose a globally unique name for your bucket (e.g.,
my-static-website-bucket). - Set the AWS Region.
- Disable “Block all public access” since static websites require public access.
- Choose a globally unique name for your bucket (e.g.,
- Enable Static Website Hosting:
- Under “Properties,” enable the “Static website hosting” option.
- Specify an index document (e.g.,
index.html) and an error document (e.g.,error.html).
- Bucket Policy:
- Add a bucket policy to allow public read access to the content. Example policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-static-website-bucket/*"
}
]
}
Enable Logging and Versioning (Optional)
Enabling bucket versioning and logging helps in debugging and provides a way to revert to previous versions of files.
Step 2: Write Terraform Configuration Files
Terraform will manage the creation and configuration of the S3 bucket and other resources. Follow these steps:
- Install Terraform:
- Download and install Terraform from terraform.io.
- Initialize a Terraform Project:
- Create a directory for your project (e.g.,
s3-website-deployment). - Inside the directory, create the following files:
- Create a directory for your project (e.g.,
main.tf
This is the primary configuration file that defines resources.
provider "aws" {
region = "us-east-1" # Change to your desired region
}
resource "aws_s3_bucket" "static_website" {
bucket = "my-static-website-bucket"
acl = "public-read"
website {
index_document = "index.html"
error_document = "error.html"
}
}
resource "aws_s3_bucket_policy" "public_access" {
bucket = aws_s3_bucket.static_website.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.static_website.arn}/*"
}
]
})
}
output "bucket_name" {
value = aws_s3_bucket.static_website.bucket
}
variables.tf
Define any variables required for the configuration.
variable "region" {
description = "AWS region"
default = "us-east-1"
}
outputs.tf
Capture outputs, such as the bucket name.
output "website_url" {
value = aws_s3_bucket.static_website.website_endpoint
}
- Initialize and Apply Terraform:
- Run the following commands:
terraform init
terraform apply -auto-approve
This will provision the S3 bucket and output the website endpoint.
Step 3: Automate Deployments with GitHub Actions
Create a GitHub Repository
- Initialize a GitHub repository and push your static website code (HTML, CSS, JS) to it.
Configure GitHub Actions Workflow
Inside your repository, create a .github/workflows/deploy.yml file with the following content:
name: Deploy to S3
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Sync Files to S3
run: |
aws s3 sync . s3://my-static-website-bucket --delete
- name: Invalidate CloudFront Cache (Optional)
run: |
aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DIST_ID }} --paths "/*"
Set Up GitHub Secrets
Add the following secrets in your GitHub repository:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYCLOUDFRONT_DIST_ID(if using CloudFront for caching)
Step 4: Test the Deployment
Push Changes to GitHub
Commit your changes and push them to the main branch. This will trigger the GitHub Actions workflow, which will:
- Sync your static files to the S3 bucket.
- Optionally invalidate CloudFront caches if configured.
Access Your Website
Visit the S3 website endpoint (e.g., http://my-static-website-bucket.s3-website-us-east-1.amazonaws.com) to verify that your static website is live.
Enhancements and Best Practices
- CloudFront Integration:
- Use Amazon CloudFront to distribute your content with low latency and enable HTTPS.
- Custom Domain:
- Configure Route 53 to point your domain to the S3 bucket or CloudFront distribution.
- Terraform State Management:
- Use a remote backend (e.g., S3 with DynamoDB locking) to manage Terraform state files securely.
- Monitoring:
- Enable Amazon S3 Access Logs and CloudWatch for monitoring traffic and diagnosing issues.
- Versioning:
- Implement S3 bucket versioning to maintain previous versions of your files.
Conclusion
By leveraging Terraform and GitHub Actions, you can automate the entire lifecycle of a static website hosted on AWS S3. This approach ensures a robust, repeatable, and efficient workflow, empowering you to focus on content and functionality rather than manual deployments. With additional integrations, such as CloudFront and Route 53, you can further enhance your website’s performance and user experience. Start implementing this pipeline today to streamline your static website deployments!