Skip to content

Instantly share code, notes, and snippets.

@reinhrst
Last active October 24, 2021 14:19
Show Gist options
  • Select an option

  • Save reinhrst/6c10b2da47bda52d7ced4e87c0f00681 to your computer and use it in GitHub Desktop.

Select an option

Save reinhrst/6c10b2da47bda52d7ced4e87c0f00681 to your computer and use it in GitHub Desktop.
Cloudformation template for static website through S3 and CloudFront
# This stack accompanies an article on my blog: https://blog.claude.nl/tech/manual/create-a-static-https-site-on-aws-with-cloudformation/
AWSTemplateFormatVersion: 2010-09-09
Description: Creates an https website
Metadata: {}
Parameters:
HostedZoneName:
Description: The HostedZoneName of the zone that you want to host the website on. This has to be in the same account, and has to be active (i.e. used as the DNS server for this domain).
Type: String
HostedZoneId:
Description: The ID for the HostedZoneName
Type: String
Hostname:
Description: The hostname to host the website on (in the HostedZoneId). This should not exist yet within the HostedZoneId.
Type: String
AllowedPattern: ^[a-z0-9][a-z0-9-]*$
Default: www
PriceClass:
Type: String
Description: The CloudFront distribution price class
AllowedValues:
- 'PriceClass_100'
- 'PriceClass_200'
- 'PriceClass_All'
Mappings: {}
Conditions: {}
Resources:
Certificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Sub "${Hostname}.${HostedZoneName}"
DomainValidationOptions:
- DomainName: !Sub "${Hostname}.${HostedZoneName}"
HostedZoneId: !Ref HostedZoneId
ValidationMethod: DNS
Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub "${Hostname}.${HostedZoneName}"
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Statement:
- Action:
- s3:GetObject
Effect: Allow
Resource: !Sub "arn:aws:s3:::${Bucket}/website/*"
Principal:
CanonicalUser: !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Aliases:
- !Sub "${Hostname}.${HostedZoneName}"
DefaultCacheBehavior:
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # caching disabled
Compress: true
ForwardedValues:
QueryString: false
TargetOriginId: !Sub "S3-${Hostname}.${HostedZoneName}"
ViewerProtocolPolicy: redirect-to-https
DefaultRootObject: index.html
CustomErrorResponses:
- ErrorCachingMinTTL: 10
ErrorCode: 403
ResponseCode: 404
ResponsePagePath: /404.html
- ErrorCachingMinTTL: 10
ErrorCode: 404
ResponseCode: 404
ResponsePagePath: /404.html
Enabled: true
HttpVersion: http2
Origins:
- DomainName: !Sub "${Bucket}.s3.amazonaws.com"
OriginPath: /website
Id: !Sub "S3-${Hostname}.${HostedZoneName}"
S3OriginConfig:
OriginAccessIdentity:
!Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}"
Logging:
Bucket: !Sub "${Bucket}.s3.amazonaws.com"
IncludeCookies: False
Prefix: cloudfront-logs/
PriceClass: !Ref PriceClass
ViewerCertificate:
AcmCertificateArn: !Ref Certificate
MinimumProtocolVersion: TLSv1
SslSupportMethod: sni-only
Tags:
- Key: Domain
Value: !Sub "${Hostname}.${HostedZoneName}"
CloudFrontOriginAccessIdentity:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: !Sub 'CloudFront OAI for ${Hostname}.${HostedZoneName}'
DNSEntry:
Type: AWS::Route53::RecordSet
Properties:
Name: !Sub "${Hostname}.${HostedZoneName}."
Type: A
AliasTarget:
DNSName: !GetAtt CloudFrontDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2 # hardcoded CloudFront zone id
HostedZoneName: !Sub "${HostedZoneName}."
Outputs:
{}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment