はじめに
技術的な学びをアウトプットする機会を増やそうと思い、まずは自分でブログを構築してみることにしました。
フレームワークにはHugo
を採用し、インフラはTerrafromで管理、Github ActionsでCDを組みました。
今回は個人ブログを構築する際にやったことを紹介したいと思います。
本記事ではブログをホストする環境を作成するところまでを書き、ActionsをつかったCDについては別記事で書きます。
構築するもの

書かないこと
- Hugoのインストール方法や使い方
- ドメインの取得方法
- AWSアカウントの発行方法
書くこと
- Terraformでブログをホストする環境を構築する手順
インフラ構成
今回個人ブログをホストする環境をAWSで用意しました。
昔AWSのCloud Solutions Architect Associate(SAA)の勉強をしていた時に発行したAWSアカウントがあったのですが、資格勉強以降ほとんどつかわれていなかったので今回AWSで環境を作成しました。
ただ、環境を作成するだけだとアレなので、Terraformをつかった構成管理 + Github ActionsでCDを組む + OIDCでAWSとActions間の認証をすることにしました。
ブログをホストする環境はCloudfront + S3環境で構築しました。
Cloudfront + S3をつかって静的サイトをつくる構成は、S3の静的ウェブサイトホスティング機能を使うパターンとCloudfrontのOACを使ってS3へのアクセス制御をするパターンがありますが、今回は後者を採用しました。
OACについて参考にした記事↓
https://dev.classmethod.jp/articles/amazon-cloudfront-origin-access-control/
Terrafromでリソースを作成
ディレクトリ構成は以下のようにしました。
別環境に複製することは想定していないので、以下の単純なディレクトリ構成になっています。
acm.tf,route53.tf,main.tf,variable.tfの説明は省きます。
ディレクトリ構成
terraform/
├── acm.tf
├── cloudfront.tf
├── code
│ └── addIndexFunction.js
├── main.tf
├── route53.tf
├── s3.tf
└── variable.tf
cloudfront.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# Create a CloudFront distribution for serving the static content
resource "aws_cloudfront_distribution" "example_domain" {
origin {
domain_name = aws_s3_bucket.main.bucket_regional_domain_name
origin_id = aws_s3_bucket.main.id
origin_access_control_id = aws_cloudfront_origin_access_control.example_domain.id
}
enabled = true
default_root_object = "index.html"
aliases = ["${var.service_domain}"]
default_cache_behavior {
target_origin_id = aws_s3_bucket.main.id
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
function_association {
event_type = "viewer-request"
function_arn = aws_cloudfront_function.add-index-function.arn
}
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate_validation.example_domain.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2018"
}
}
resource "aws_cloudfront_origin_access_control" "example_domain" {
name = aws_s3_bucket.main.bucket_domain_name
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
resource "aws_cloudfront_function" "add-index-function" {
name = "add-index-function"
runtime = "cloudfront-js-1.0"
comment = "Add index.html to the path"
publish = true
code = file("${path.module}/code/addIndexFunction.js")
}
###############################################################################
# Output
###############################################################################
output "cloud_front_destribution_domain_name" {
value = aws_cloudfront_distribution.example_domain.domain_name
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
resource "aws_s3_bucket" "main" {
bucket = "hogehoge"
}
resource "aws_s3_bucket_policy" "bucket_policy" {
bucket = aws_s3_bucket.main.id
policy = data.aws_iam_policy_document.s3_policy.json
}
data "aws_iam_policy_document" "s3_policy" {
statement {
principals {
type = "Service"
identifiers = ["cloudfront.amazonaws.com"]
}
actions = [
"s3:GetObject",
"s3:putBucketAcl",
]
resources = [
aws_s3_bucket.main.arn,
"${aws_s3_bucket.main.arn}/*",
]
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = [aws_cloudfront_distribution.n_kent2_net.arn]
}
}
}
|
さきほど説明したとおりCloudfrontのOrigin Access Control(OAC)を使用してS3へのアクセス制御しています。
OACの設定は上記コードのハイライトした箇所で行っています。
Terraformのaws_cloudfront_origin_access_control
でOACの設定を行いディストリビューションに紐づけています。
S3側ではOACにバケットへのアクセス許可を付与するためにS3のバケットポリシーでActionを制御し、サービスプリンシパルにcloudfront.amazonaws.com
をしていしています。さらにConditionで ディストリビューションのARNを指定することで特定のディストリビューションからのアクセスのみを許可するように設定しています。
Viewer-requestでadd-index-function
というCloudfront Functionを実行するようにしています。
これはルートオブジェクトに設定されているindex.html
は問題なく表示されるものの、それ以外のサブディレクトリが表示されない問題を回避するために設定しています。
関数の中身は公式が用意しているコードをそのまま使用しています。
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html
以上でブログをホストするための環境は用意できました。
次はGithub ActionsをつかってCDを作成について書きたいとおもいます。
参考
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
https://dev.classmethod.jp/articles/cloudfront-and-s3-using-hugo-with-github-actions/
https://zenn.dev/kou_pg_0131/articles/tf-cloudfront-oac