Prerequisites
- foo.comのドメイン
- AWSアカウント
- blog.foo.com(ないしワイルドカード)のACM証明書(us-east-1 regionのもの)
- aws cli
- jq
Goal
- Hugoで生成したstatic siteコンテンツをS3でホストしてCloudFrontで独自ドメイン配信
- 独自ドメイン=
blog.foo.com
- 配信はhttpsへリダイレクト
- 独自ドメイン=
Hugoプロジェクト作成
brew install hugo
hugo new site site
cd site
hugo --minify
static site用S3バケット作成
- s3bucketpolicy.json
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::blog.foo.com/*" } ] }
aws s3 mb s3://blog.foo.com --region="ap-northeast-1"
aws s3api put-bucket-policy --bucket blog.foo.com --policy file://s3bucketpolicy.json
aws s3 website s3://blog.foo.com/ --index-document index.html
aws s3 sync "public/" "s3://blog.foo.com" --delete --acl "public-read"
http://blog.foo.com.s3-website-ap-northeast-1.amazonaws.com/
へアクセスできるか確認
配信用CloudFront
ログ出力用のS3バケット作成
aws s3 mb s3://logs.blog.foo.com --region="ap-northeast-1"
aws cliでCloudFront Distribution作成
完成形JSON
aws cloudfront create-distribution
に渡すやつ
cf_distribution.json
{
"DistributionConfig": {
"CallerReference": "1610246116",
"Aliases": {
"Quantity": 1,
"Items": [
"blog.foo.com"
]
},
"DefaultRootObject": "index.html",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "s3-blog.foo.com",
"DomainName": "blog.foo.com.s3-website-ap-northeast-1.amazonaws.com",
"OriginPath": "",
"CustomHeaders": {
"Quantity": 0
},
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "http-only",
"OriginSslProtocols": {
"Quantity": 1,
"Items": [
"TLSv1.2"
]
},
"OriginReadTimeout": 30,
"OriginKeepaliveTimeout": 5
}
}
]
},
"OriginGroups": {
"Quantity": 0
},
"DefaultCacheBehavior": {
"TargetOriginId": "s3-blog.foo.com",
"ForwardedValues": {
"QueryString": true,
"Cookies": {
"Forward": "none"
},
"Headers": {
"Quantity": 0
},
"QueryStringCacheKeys": {
"Quantity": 0
}
},
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"ViewerProtocolPolicy": "redirect-to-https",
"MinTTL": 0,
"AllowedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
]
}
},
"SmoothStreaming": true,
"DefaultTTL": 0,
"MaxTTL": 0,
"Compress": true,
"LambdaFunctionAssociations": {
"Quantity": 0
},
"FieldLevelEncryptionId": ""
},
"CacheBehaviors": {
"Quantity": 0
},
"CustomErrorResponses": {
"Quantity": 0
},
"Comment": "",
"Logging": {
"Enabled": true,
"IncludeCookies": false,
"Bucket": "logs.blog.foo.com.s3.amazonaws.com",
"Prefix": "cdn/"
},
"PriceClass": "PriceClass_100",
"Enabled": true,
"ViewerCertificate": {
"ACMCertificateArn": "arn:aws:acm:us-east-1:ACCOUNT_ID:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"SSLSupportMethod": "sni-only",
"MinimumProtocolVersion": "TLSv1.2_2019",
"Certificate": "arn:aws:acm:us-east-1:ACCOUNT_ID:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"CertificateSource": "acm"
},
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Quantity": 0
}
},
"WebACLId": "",
"HttpVersion": "http2",
"IsIPV6Enabled": true
}
}
Keys
- Aliases.Items
- CNAMEs(代替ドメイン)を指定(配列で複数指定可)
- DomainName
- ウェブサイトエンドポイントを指定
- eg.
blog.example.com.s3-website-ap-northeast-1.amazonaws.com
- eg.
- ウェブサイトエンドポイントを指定
- CallerReference
- Distributions内で固有値となるように(ここではunixtimeを設定)
date +%s
- Distributions内で固有値となるように(ここではunixtimeを設定)
- OriginProtocolPolicy
- S3をoriginとする場合、ウェブサイトエンドポイントがHTTPS非対応な為、
http-only
でないといけない
- S3をoriginとする場合、ウェブサイトエンドポイントがHTTPS非対応な為、
- ViewerProtocolPolicy
- HTTP > HTTPSへリダイレクトするように
- ViewerCertificate
aws acm --region us-east-1 list-certificates
で該当の証明書のarnをチェック- CloudFrontにACM証明書を関連付けるにはバージニア北部リージョンのものである必要がある
- Logging
- S3へのログ出力設定
Makefile
CLOUDFRONT_DISTRIBUTION_JSON := cf_distribution.json
.PHONY: create-cloudfront-distribution
create-cloudfront-distribution: update-cloudfront-callerreference
aws cloudfront \
create-distribution \
--cli-input-json file://$(CLOUDFRONT_DISTRIBUTION_JSON)
.PHONY: update-cloudfront-callerreference
update-cloudfront-callerreference:
cat $(CLOUDFRONT_DISTRIBUTION_JSON) | jq -r '.DistributionConfig.CallerReference = "'$$(date +%s)'"' > $(CLOUDFRONT_DISTRIBUTION_JSON)
$ make create-cloudfront-distribution
で作成
Route53
Aliases.Itemsで指定した代替ドメイン名でCloudFrontのエイリアスレコードを作成
- add_alias_record.json
{ "Comment": "Creating Alias resource record sets in Route 53", "Changes": [ { "Action": "CREATE", "ResourceRecordSet": { "Name": "blog.foo.com.", "Type": "A", "AliasTarget": { "HostedZoneId": "ZXXXXXXXXXXXXX", "DNSName": "xxxxxxxxxxxxxx.cloudfront.net.", "EvaluateTargetHealth": false } } } ] }
DNSName
はaws cloudfront list-distributions
のDistributionList.Items[i].DomainNameを参照(i値は適宜)
aws route53 change-resource-record-sets --hosted-zone-id ZXXXXXXXXXX --change-batch file://add_alias_record.json
で作成
Test
curl -LI blog.foo.com -o /dev/null -w '%{http_code}\n' -s
200