cloudfront-static-website
Creates a static website hosted on S3 with CloudFront distribution, SSL certificate, and custom domain.
Note
This stack might take a long time to both apply and destroy due to the CloudFront distribution. Deployment typically takes around 5 minutes, while destruction can take 5-6 minutes.
Note
This template has a dependency on the CloudFront data template which creates the S3 buckets used for content and logging.
Architecture
This template creates the CloudFront distribution and associated resources that work with the S3 buckets created by the CloudFront data stack:
- CloudFront Distribution - CDN with custom domain, SSL, and SPA routing
- Route53 Record - DNS alias pointing to CloudFront
- ACM Certificate - SSL certificate for custom domain (us-east-1)
- IAM Role (optional) - GitHub OIDC role for CI/CD deployments
The S3 buckets (content and logs) are created separately in the Data stack to allow for independent lifecycle management.
Features
- HTTPS-only with custom domain
- Client-side routing support (when
ClientSideRouting.Enable: true) - 403 errors redirect to 200index.html(similar to react-cors-spa) - Optional URL rewriting (when
DirectoryBehavior.AddToAllUrls: true) - addsindex.htmlto directory requests and URLs without extensions, based on AWS CloudFront Functions sample - Configurable root and error objects via
DirectoryBehavior - GitHub Actions deployment permissions (when enabled)
Configuration
This template uses variables defined in the boilerplate configuration. See the Variables section below for the complete list of available options.
Usage
With Boilerplate
- Generate the CloudFront data template first (if not already done)
- Generate this template with your
Name - Update
config_override.tfwith your AWS account/environment details - Run
terraform apply - Upload static files to the S3 bucket created by the data stack
- Access your site at
https://{Name}.{environment}.oslo.systems
With ok and configuration files
Create the following files in your project directory (e.g., monkey-web):
packages.yml:
Packages:
- OutputFolder: .
Ref: main
Template: cloudfront-static-website
VarFiles:
- ../common-config.yml
- package-config.yml
package-config.yml:
StackName: "web-monkey"
cloudfront-static-website-data.StackName: "web-monkey-data"
Name: "monkey"
IamForCicd:
Enable: true
GitHubRepo: golden-path-iac
Then run:
ok pkg install- Terraform files will appearcdto the data stack directory, apply that withterraform apply- Go back to the main directory (
web-monkey) and apply withterraform apply - Upload static files to the S3 bucket created by the data stack
- Access your site at
https://{Name}.{environment}.oslo.systems
Deployment
Manual Deployment
Upload static files manually to the S3 bucket created by the CloudFront data stack.
Automated Deployment
For automated deployments, use the CloudFront deploy workflow template which:
- Builds your static site using Docker
- Syncs files to the S3 bucket
- Creates CloudFront cache invalidations
When IamForCicd.Enable is true, a GitHub OIDC role is created with permissions to:
- Upload files to S3 bucket
- Create CloudFront invalidations
- Deploy from GitHub Actions workflows
The role can be assumed by GitHub Actions in the specified repository.
Variables
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
IncludeLockFile |
Include a Terraform dependency lock file (.terraform.lock.hcl) that pins provider versions. |
bool |
false |
no |
Name |
Website name. Used as the subdomain, exposing the site at https://<Name>.<Environment>.oslo.systems. |
string |
n/a |
yes |
RedirectAllToIndex |
Serve RootObject with status 200 for every request that does not match a file, instead of the ErrorObject error page. Needed for single-page apps with client-side routing. |
bool |
false |
no |
RootObject |
The object served when the site root (/) is requested. Also the object that RedirectAllToIndex and AppendIndexToDirectories rewrite requests to. |
string |
index.html |
no |
ErrorObject |
The object served with status 404 when a requested file does not exist. Not used when RedirectAllToIndex is enabled. |
string |
404.html |
no |
AppendIndexToDirectories |
Rewrite requests ending in / or without a file extension to append /<RootObject>, so /about serves about/index.html. Useful for static site generators that output one index.html per directory. |
bool |
false |
no |
DeploymentPipelineV2 |
Deploy the website with the next-generation deployment pipeline. Replaces IamForCicd. |
map |
{"Enable": false} |
no |
IamForCicd |
Deprecated: use DeploymentPipelineV2 instead. Lets GitHub Actions in the website's repository (GitHubRepo, under the oslokommune org) deploy the site. The workflow must run in the GitHub environment <Environment>-<Name>. |
map |
{"Enable": false, "GitHubRepo": null} |
no |