はじめに#
この記事では、CloudFrontで配信している技術ブログに独自ドメインを設定します。 Route53でドメインを購入し、ACM(AWS Certificate Manager)でSSL/TLS証明書を発行してHTTPS通信を実現します。
この記事で構築するもの#
- Route53でのドメイン購入
- ACM証明書の発行(DNS検証)
- CloudFrontへのカスタムドメイン設定
- Route53 Aliasレコードの設定
想定する読者#
- 前回までの記事でS3 + CloudFront + 監視 + ログ分析環境を構築済みの方
- CloudFrontのデフォルトドメイン(
dxxxxx.cloudfront.net)から独自ドメインに変更したい方 - AWS初心者〜中級者
完成イメージ#

【変更前】
https://dxxxxx.cloudfront.net/
【変更後】
https://example.com/ ← 独自ドメインでアクセス可能に
独自ドメインでHTTPSアクセスできるようになります。
シリーズ全体像#
【Hugo×AWS】シリーズ全体で5記事投稿予定です。今回の記事は最終回の5本目です。
| # | タイトル | 内容 |
|---|---|---|
| 1 | Hugo + S3 + CloudFrontで技術ブログを公開する | Hugo環境構築〜手動デプロイまで |
| 2 | GitHub Actions + OIDCで自動デプロイ | CI/CD構築、アクセスキー不要の認証 |
| 3 | CloudWatch + SNSで監視・アラート通知 | ダッシュボード、エラー率アラーム |
| 4 | Athenaでアクセスログを分析する | CloudFrontログのSQL分析 |
| 5 | 独自ドメインを設定する(Route53 + ACM) | カスタムドメイン、HTTPS |
なぜ独自ドメインが必要なのか#
CloudFrontのデフォルトドメイン(dxxxxx.cloudfront.net)でも技術的には問題ありませんが、独自ドメインには以下のメリットがあります。
| 観点 | デフォルトドメイン | 独自ドメイン |
|---|---|---|
| ブランディング | △ AWSのサブドメイン | ✅ 自分の名前 |
| 覚えやすさ | △ ランダムな文字列 | ✅ 意味のある名前 |
| 信頼性 | △ 一時的に見える | ✅ 本格的に見える |
| SEO | △ ドメインパワーなし | ✅ 独自ドメインで蓄積 |
| ポートフォリオ | △ 印象が弱い | ✅ プロフェッショナル |
転職ポートフォリオとして見せる場合、独自ドメインは「本気で運用している」印象を与えます。
前提条件#
必要な環境#
本記事は、これまでの記事で以下が構築済みであることを前提としています。
- CloudFront Distribution
- Terraformプロジェクト
必要な情報#
cd hugo-s3-demo-infra/prod
terraform output
cloudfront_distribution_id = "E2XXXXXXXXXX"
cloudfront_domain_name = "dxxxxx.cloudfront.net"
【重要】ACM証明書のリージョン制約#
:::message alert
CloudFrontでACM証明書を使う場合、必ず us-east-1(バージニア北部)で証明書を作成する必要があります。
東京リージョン(ap-northeast-1)で作成した証明書は、CloudFrontの設定画面で選択できません。
:::
なぜus-east-1なのか#
CloudFrontはグローバルサービスであり、グローバルサービスは us-east-1 のACM証明書しか参照できない仕様です。
| サービス | ACM証明書のリージョン |
|---|---|
| CloudFront | us-east-1のみ |
| ALB | ALBと同じリージョン |
| API Gateway(Edge) | us-east-1のみ |
AWS公式ドキュメントにも明記されています。
“To use an ACM certificate with Amazon CloudFront, you must request or import the certificate in the US East (N. Virginia) region.” — Supported Regions - AWS Certificate Manager
ドメインの購入(Route53)#
Route53でドメインを購入する理由#
| 購入先 | メリット | デメリット |
|---|---|---|
| Route53 | AWSサービスとの連携が簡単、DNS検証が1クリック | 一部TLDは割高 |
| お名前.com等 | 安いTLDが多い | ネームサーバー移管が必要 |
| Cloudflare | .dev等が購入可能 | Route53との連携に手間 |
本記事ではRoute53での購入を前提に解説します。
:::message
Route53では .dev ドメインを購入できません。.dev を使いたい場合は、Cloudflare等で購入後、Route53にネームサーバーを移管する必要があります。
:::
購入手順#
- AWSコンソールで Route53 を開く
- 左メニューの「登録済みドメイン」→「ドメインの登録」
- 希望のドメイン名を検索(例:
example) - 利用可能なTLDと価格を確認し、カートに追加
- 連絡先情報を入力
- 以下の設定を確認
- プライバシー保護: 有効(WHOIS情報を非公開)
- 自動更新: 有効(更新忘れ防止)
- 購入を完了
購入後の確認#
購入後、以下のメールが届きます。
| # | メール件名 | 対応 |
|---|---|---|
| 1 | Amazon Registrar にサインアップ〜 | 対応不要 |
| 2 | [Action Required] Verify your email address | ⚠️ リンクをクリックして承認 |
| 3 | Registration of example.com succeeded | 対応不要(完了通知) |
:::message alert 承認メールが迷惑メールフォルダに入っていることがあります。届かない場合は迷惑メールを確認してください。 :::
ホストゾーンの確認#
ドメイン購入時に、Route53のホストゾーンが自動作成されます。
- Route53 → ホストゾーン
- 購入したドメイン名のホストゾーンを開く
- NS(ネームサーバー)とSOAレコードが存在することを確認
:::message
ドメイン購入はTerraformで管理できません(一度きりの操作、連絡先入力が必要なため)。
ホストゾーンは data ソースで参照します。
:::
ACM証明書の発行#
ACMとは#
ACM(AWS Certificate Manager) は、SSL/TLS証明書を管理するAWSサービスです。
| 従来の方法 | ACM |
|---|---|
| 証明書を購入(年間数千〜数万円) | 無料 |
| 手動でサーバーにインストール | AWS側で自動設定 |
| 有効期限切れを手動管理 | 自動更新 |
Terraformでのマルチリージョン設定#
ACM証明書を us-east-1 で作成するため、マルチリージョンのprovider設定が必要です。
versions.tf の修正#
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# デフォルトプロバイダー(東京リージョン)
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Project = var.project_name
ManagedBy = "terraform"
}
}
}
# us-east-1プロバイダー(ACM証明書用)
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
default_tags {
tags = {
Project = var.project_name
ManagedBy = "terraform"
}
}
}
alias = "us_east_1" を設定することで、リソースごとにプロバイダーを使い分けられます。
acm.tf#
acm.tf を新規作成します。
# ===========================================
# ACM証明書(us-east-1で作成)
# ===========================================
resource "aws_acm_certificate" "main" {
provider = aws.us_east_1 # us-east-1で作成
domain_name = var.domain_name
subject_alternative_names = ["*.${var.domain_name}"]
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
tags = {
Name = "${var.project_name}-certificate"
}
}
# ===========================================
# DNS検証用レコード
# ===========================================
resource "aws_route53_record" "acm_validation" {
for_each = {
for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
zone_id = data.aws_route53_zone.main.zone_id
name = each.value.name
type = each.value.type
records = [each.value.record]
ttl = 60
allow_overwrite = true
}
# ===========================================
# 証明書の検証完了を待機
# ===========================================
resource "aws_acm_certificate_validation" "main" {
provider = aws.us_east_1
certificate_arn = aws_acm_certificate.main.arn
validation_record_fqdns = [for record in aws_route53_record.acm_validation : record.fqdn]
}
コード解説#
証明書リソース#
resource "aws_acm_certificate" "main" {
provider = aws.us_east_1 # 重要: us-east-1で作成
domain_name = var.domain_name # example.com
subject_alternative_names = ["*.${var.domain_name}"] # *.example.com(ワイルドカード)
validation_method = "DNS" # DNS検証
}
| 属性 | 説明 |
|---|---|
provider | us-east-1プロバイダーを指定 |
domain_name | メインドメイン |
subject_alternative_names | サブドメイン(ワイルドカードで全て対応) |
validation_method | DNS検証(Route53なら自動化可能) |
DNS検証レコード#
resource "aws_route53_record" "acm_validation" {
for_each = {
for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => { ... }
}
# ...
}
ACMがDNS検証用に要求するCNAMEレコードを、Route53に自動作成します。
for_each でドメインごとにレコードを作成します(メインドメイン + ワイルドカード)。
検証完了の待機#
resource "aws_acm_certificate_validation" "main" {
certificate_arn = aws_acm_certificate.main.arn
validation_record_fqdns = [for record in aws_route53_record.acm_validation : record.fqdn]
}
証明書の検証が完了するまで待機するリソースです。 これにより、証明書が「発行済み」になるまでTerraformが次のリソース作成を待ちます。
variables.tf に追記#
variable "domain_name" {
description = "Domain name for the website"
type = string
}
terraform.tfvars に追記#
domain_name = "example.com" # 購入したドメイン名に置き換え
Route53の設定#
route53.tf#
route53.tf を新規作成します。
# ===========================================
# ホストゾーンの参照(ドメイン購入時に自動作成済み)
# ===========================================
data "aws_route53_zone" "main" {
name = var.domain_name
private_zone = false
}
# ===========================================
# Aliasレコード(CloudFrontへのルーティング)
# ===========================================
resource "aws_route53_record" "main" {
zone_id = data.aws_route53_zone.main.zone_id
name = var.domain_name
type = "A"
alias {
name = aws_cloudfront_distribution.main.domain_name
zone_id = aws_cloudfront_distribution.main.hosted_zone_id
evaluate_target_health = false
}
}
# wwwサブドメイン用(任意)
resource "aws_route53_record" "www" {
zone_id = data.aws_route53_zone.main.zone_id
name = "www.${var.domain_name}"
type = "A"
alias {
name = aws_cloudfront_distribution.main.domain_name
zone_id = aws_cloudfront_distribution.main.hosted_zone_id
evaluate_target_health = false
}
}
# ===========================================
# Outputs
# ===========================================
output "website_url" {
value = "https://${var.domain_name}"
}
コード解説#
ホストゾーンの参照#
data "aws_route53_zone" "main" {
name = var.domain_name
private_zone = false
}
ドメイン購入時に自動作成されたホストゾーンを data ソースで参照します。
Aliasレコード#
resource "aws_route53_record" "main" {
type = "A"
alias {
name = aws_cloudfront_distribution.main.domain_name
zone_id = aws_cloudfront_distribution.main.hosted_zone_id
evaluate_target_health = false
}
}
Aliasレコードは、AWSサービス(CloudFront、ALB、S3等)への特殊なルーティングです。
| 通常のAレコード | Aliasレコード |
|---|---|
| IPアドレスを指定 | AWSサービスのドメイン名を指定 |
| TTLを設定 | TTL不要(自動) |
| DNSクエリ課金あり | 無料 |
CloudFrontへのルーティングには、Aliasレコードを使用するのがベストプラクティスです。
CloudFrontの更新#
CloudFront Distributionにカスタムドメインと証明書を設定します。
main.tf の修正#
aws_cloudfront_distribution リソースを修正します。
resource "aws_cloudfront_distribution" "main" {
# ...既存の設定...
# カスタムドメインを追加
aliases = [var.domain_name, "www.${var.domain_name}"]
# viewer_certificate を修正
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.main.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
# 証明書の検証完了を待ってから作成
depends_on = [aws_acm_certificate_validation.main]
# ...既存の設定...
}
コード解説#
aliases#
aliases = [var.domain_name, "www.${var.domain_name}"]
CloudFrontが受け付けるドメイン名を指定します。
example.com と www.example.com の両方からアクセス可能になります。
viewer_certificate#
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.main.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
| 属性 | 説明 |
|---|---|
acm_certificate_arn | ACM証明書のARN |
ssl_support_method | sni-only(SNI対応クライアントのみ、追加料金なし) |
minimum_protocol_version | 最小TLSバージョン(セキュリティ向上のため1.2以上推奨) |
:::message
ssl_support_method = "vip" を選択すると、専用IPアドレスが割り当てられますが、月額$600の追加料金が発生します。
個人ブログでは sni-only で十分です。
:::
depends_on#
depends_on = [aws_acm_certificate_validation.main]
証明書の検証が完了してから、CloudFront Distributionを作成/更新するようにします。
Hugoの設定更新#
hugo.toml の baseURL を独自ドメインに更新します。
baseURL = 'https://example.com/'
languageCode = 'en-us'
title = 'My Tech Blog'
theme = 'ananke'
更新後、pushすればGitHub Actionsが自動デプロイします。
実行#
terraform plan
terraform apply
:::message
ACM証明書の検証には数分〜数十分かかる場合があります。
terraform apply が長時間待機状態になっても、正常に処理が進んでいます。
:::
動作確認#
1. 証明書のステータス確認#
AWSコンソール → ACM(us-east-1リージョン)で、証明書のステータスが「発行済み」になっていることを確認します。
2. ブラウザでアクセス#
以下のURLにアクセスし、正常に表示されることを確認します。
https://example.com/https://www.example.com/
確認ポイント:
- サイトが正常に表示される
- ブラウザのアドレスバーに鍵マークが表示される(HTTPS)
- 記事詳細ページにもアクセスできる
3. HTTPリダイレクト確認#
http://example.com/ にアクセスし、https://example.com/ にリダイレクトされることを確認します。
(CloudFrontの viewer_protocol_policy = "redirect-to-https" により自動リダイレクト)
コストについて#
Route53#
| 項目 | 料金 |
|---|---|
| ドメイン(.com) | $15/年 |
| ホストゾーン | $0.50/月 |
| DNSクエリ(Alias) | 無料 |
ACM#
| 項目 | 料金 |
|---|---|
| パブリック証明書 | 無料 |
| 自動更新 | 無料 |
独自ドメインの追加コストは、ドメイン代 + ホストゾーン代で月額約200円程度です。
トラブルシューティング#
証明書がCloudFrontの選択肢に表示されない#
原因: 証明書が us-east-1 以外のリージョンで作成されている
対処法:
- AWSコンソールで現在の証明書のリージョンを確認
us-east-1以外の場合は、証明書を削除してus-east-1で再作成
DNS検証が完了しない#
原因: DNS検証レコードが正しく作成されていない
確認ポイント:
- Route53のホストゾーンにCNAMEレコードが作成されているか確認
- レコードの値がACMの要求と一致しているか確認
対処法: terraform apply を再実行
サイトにアクセスできない#
原因: DNSの伝播に時間がかかっている
対処法:
dig example.comでDNSレコードを確認- 数分〜数時間待ってから再度アクセス
ERR_SSL_VERSION_OR_CIPHER_MISMATCH#
原因: 証明書の設定が正しくない
確認ポイント:
- CloudFrontの
aliasesに正しいドメイン名が設定されているか - ACM証明書のドメイン名が一致しているか
まとめ#
本記事では、以下を構築しました。
- Route53: ドメイン購入、DNSレコード管理
- ACM: SSL/TLS証明書の発行(us-east-1)
- CloudFront: カスタムドメイン設定
- Terraform: マルチリージョンprovider設定
作成したリソース#
| リソース | 用途 |
|---|---|
| Route53 Aliasレコード | CloudFrontへのルーティング |
| Route53 CNAMEレコード | ACM DNS検証 |
| ACM証明書 | HTTPS通信の実現 |
| CloudFront aliases | カスタムドメインの受け付け |
重要ポイント#
| 項目 | ポイント |
|---|---|
| ACM証明書のリージョン | us-east-1必須 |
| Aliasレコード | CloudFrontへのルーティングは無料 |
| ssl_support_method | sni-only で追加料金なし |
| DNS伝播 | 最大72時間かかる場合がある |
これで【Hugo×AWS】シリーズは完了です!
5記事を通じて、以下の技術ブログ基盤を構築しました。
- 静的サイトホスティング: S3 + CloudFront
- 自動デプロイ: GitHub Actions + OIDC
- 監視・アラート: CloudWatch + SNS + AWS Budgets
- ログ分析: Athena + Glue
- 独自ドメイン: Route53 + ACM
すべてTerraformでコード化されているため、再現性があり、ポートフォリオとしても活用できます。