Squarespace の NS 委譲問題と CNAME 委譲へのアーキテクチャ pivot

本シリーズで 一番苦労した のがこの DNS 周りです。iigtn.com は Google Workspace と Squarespace で運用されている既存ドメインで、その配下に lab.iigtn.com として AWS のサブドメインを切る作業。当初の「NS 委譲案」が Squarespace の制約で頓挫し、設計を pivot して CNAME のみで完結させた記録です。

初期の DNS 状態(着手前)

iigtn.com は既に運用中のドメインで、構築開始時点でこんな状態でした:

レコード意味
NSns-cloud-bN.googledomains.comDNS は Google Cloud DNS / Squarespace 経由で管理
A198.49.23.144 系Squarespace のサイトホスティング IP
MXsmtp.google.comGoogle Workspace のメール

つまり iigtn.com は既存サイト + メールが本番運用中。ここを壊さずに、lab.iigtn.com だけ AWS に切り出す必要がありました。

当初の設計(NS 委譲案)

当初の設計書では、AWS で Route53 hosted zone を作って NS を 4 個登録 し、Squarespace 側で「lab サブドメインの権威 DNS を Route53 に委譲」する案でした:

# 親側 (Squarespace) の DNS
lab.iigtn.com    NS    ns-1503.awsdns-59.org.
lab.iigtn.com    NS    ns-154.awsdns-19.com.
lab.iigtn.com    NS    ns-1719.awsdns-22.co.uk.
lab.iigtn.com    NS    ns-617.awsdns-13.net.

これにより、lab.iigtn.com 配下の全レコード(A / CNAME / TXT 等)を Terraform で完全管理できる「AWS 完結型」になるはずでした。

Terraform で Hosted Zone を作って NS を取得

まず Route53 hosted zone を作って NS を取得しました:

resource "aws_route53_zone" "this" {
  name = var.domain_name        # lab.iigtn.com
  tags = var.tags
}

output "name_servers" {
  value = aws_route53_zone.this.name_servers
}

apply すると、Route53 が 4 個の NS サーバを払い出してくれます:

name_servers = [
  "ns-1503.awsdns-59.org",
  "ns-154.awsdns-19.com",
  "ns-1719.awsdns-22.co.uk",
  "ns-617.awsdns-13.net",
]

Squarespace で NS 登録を試みる

Squarespace の DNS 管理画面(account.squarespace.com/domains/managed/iigtn.com/dns/dns-settings)で、Custom Records に NS を追加しようとしました:

HostTypeData
labNSns-1503.awsdns-59.org.

「Save」を押すと…

このレコードを保存できませんでした。しばらくしてから再度お試しください。 この問題が解決しない場合は、カスタマー サポートにお問い合わせください。

何回試しても同じエラー。Type を CNAME や A にすると保存できるが、NS だけが拒否される

原因の特定

調べた結果、Squarespace は Workspace バンドルドメインに対して、サブドメインの NS 委譲を許可していない ようでした。これは Squarespace 側の意図的な制限で、ユーザー側で何をしても回避不能。

選択肢を整理:

内容判定
ASquarespace を解約して別レジストラに移管×(既存サイト・メールに影響大)
BSquarespace のサポートに相談△(時間がかかる、結果不明)
CNS 委譲を諦めて、Squarespace で CNAME だけ管理する設計に変更◎(現実的)

Cloudflare に DNS を移管する案もありましたが、メールも巻き込むので影響範囲が大きい。C 案で pivot する ことに決めました。

新しい設計(CNAME 委譲案)

変更内容:

  1. Route53 hosted zone は 作らない(destroy)
  2. ACM 証明書はリクエストするが、検証 CNAME を Squarespace 側に手動投入
  3. CloudFront Distribution が払い出す *.cloudfront.net 名を、Squarespace で lab の CNAME として登録

つまり 「DNS は Squarespace のまま、AWS リソースは ARN で受け渡す」 構成。Route53 を介在させません。

network_dns モジュールの簡素化

当初は「hosted zone + 検証 CNAME 自動投入 + 検証待ち」の 3 リソースを持つモジュールでしたが、CNAME 委譲案では「ACM 証明書 + 検証完了待ち」の 2 リソースだけに簡素化:

# modules/network_dns/main.tf (pivot 後)
resource "aws_acm_certificate" "this" {
  provider = aws.us_east_1

  domain_name               = var.domain_name
  subject_alternative_names = ["*.${var.domain_name}"]
  validation_method         = "DNS"

  lifecycle { create_before_destroy = true }
}

resource "aws_acm_certificate_validation" "this" {
  provider = aws.us_east_1

  certificate_arn = aws_acm_certificate.this.arn

  validation_record_fqdns = [
    for dvo in aws_acm_certificate.this.domain_validation_options :
    dvo.resource_record_name
  ]

  timeouts { create = "75m" }
}

検証 CNAME は output として外に出して、Squarespace に手動投入する設計:

output "validation_records" {
  value = {
    for dvo in aws_acm_certificate.this.domain_validation_options :
    dvo.domain_name => {
      name  = dvo.resource_record_name
      type  = dvo.resource_record_type
      value = dvo.resource_record_value
    }
  }
}

Squarespace に検証 CNAME を投入

apply 後、output に表示された CNAME を Squarespace の Custom Records に登録:

HostTypeDataTTL
_2611...labCNAME_00b9...acm-validations.aws.5 min

NS と違って CNAME は Squarespace で問題なく保存できる。これで ACM 検証が走り、5 分程度で証明書が ISSUED になりました。

CloudFront 連携用 CNAME も同じ要領

後で CloudFront Distribution が dXXXXXXXXX.cloudfront.net を払い出すので、これを lab の CNAME として登録:

HostTypeDataTTL
labCNAMEdXXXXXXXXX.cloudfront.net.5 min

これで https://lab.iigtn.com/ が CloudFront に解決されるようになります。

Pivot で得たもの・失ったもの

項目NS 委譲案CNAME 委譲案 (採用)
DNS 完全 IaC 化×(Squarespace で手動)
Route53 月額$0.50$0(不要)
既存メール影響大(NS 切替リスク)
サブドメインの追加Terraform で完結Squarespace で 1 個ずつ手動
採用評価訴求「全部 AWS で揃えた」「外部 DNS と連携できる」(実は実務的)

意外なメリットとして、「外部 DNS プロバイダと AWS を連携させた経験」 は採用評価では実は強い。実案件では「DNS は移管できないお客様」が普通なので、CNAME 連携の経験は価値があります。

Cloud Shell で全プロジェクト探索

余談ですが、本件の途中で「Cloud DNS にゾーンが見当たらない」という別の混乱もありました。NS が ns-cloud-bN.googledomains.com だったので Google Cloud DNS だと推定したものの、自分の GCP プロジェクトには iigtn.com ゾーンが無い。

結局、Squarespace が裏側で Google のインフラを使っているだけ で、ユーザーが操作するのは Squarespace の UI、というのが正解でした。NS の表面的な値で判断せず、レジストラから辿るのが鉄則。

学び

  1. 既存ドメインに AWS を後付けする時、レジストラの DNS UI 制約は事前確認
  2. 「全部 AWS で揃える」は美しいが、現実は外部 DNS と共存することが多い
  3. NS 委譲は強力だが、リスクも大きい(メール壊し事故の温床)。CNAME のみで済むなら CNAME がベター
  4. Pivot を躊躇しない。設計通りに行かない時に粘って 3 日溶かすより、別ルートに切替える勇気

次の記事

証明書発行と DNS 連携の問題が解決したら、いよいよ静的サイトの本体を作っていきます。次の記事では S3 + CloudFront + OAC を組み合わせて、「非公開バケットを CDN 経由で世界に配信する」構成について書きます。OAC vs OAI、Bucket Policy の SourceArn 条件、SecurityHeadersPolicy の自動付与など、おさえておきたいポイントが多いです。

📚 用語集

NS レコード (Name Server Record)
「このドメインの権威 DNS サーバはこれ」と宣言するレコード。サブドメインに NS を登録すると、そのサブドメインの DNS 管理を別サーバに委譲できる(NS 委譲)。
CNAME レコード (Canonical Name Record)
「このドメイン名は、別のドメイン名の別名」を表すレコード。lab.iigtn.com → dXXXXX.cloudfront.net のように、別の名前に解決させる。
権威 DNS サーバ (Authoritative DNS Server)
あるドメインの公式な DNS 情報を持つサーバ。ブラウザが DNS 問い合わせするとき、最終的にこれに行き着く。
NS 委譲 (DNS Delegation)
あるサブドメインの権威を別の DNS サーバに委ねる仕組み。lab.iigtn.com の NS を Route53 に向ければ、lab.iigtn.com 配下のレコードは Route53 で管理できる。
レジストラ (Registrar)
ドメイン名を販売・管理する事業者。Squarespace / Google Domains / お名前.com など。レジストラは通常 DNS 管理機能も提供する。
Squarespace
サイトビルダー + ドメインレジストラを提供する米国企業。本シリーズの iigtn.com もここで管理されている。
Google Workspace
Google が提供する企業向けメール・カレンダー・ストレージサービス。独自ドメインのメール(例: contact@iigtn.com)が使える。
hosted zone (Route53)
Route53 の DNS ゾーン管理単位。1 ドメインにつき 1 hosted zone を作り、その中にレコードを登録する。
Route53
AWS の DNS サービス。Hosted Zone を作って権威 DNS として運用できる。
ACM 検証 CNAME
ACM が「このドメインの所有者が DNS にアクセスできることを確認」するために要求する CNAME レコード。_xxx.lab.iigtn.com → _yyy.acm-validations.aws. 形式。
CloudFront Distribution の cloudfront.net 名
Distribution が払い出す dXXXXXXXXX.cloudfront.net 形式のドメイン。CNAME でカスタムドメインから紐付ける。
pivot (設計の方向転換)
当初設計が現実の制約で実現困難になった時、別ルートに切り替えること。スタートアップ用語からの転用。
レコードセット (Record Set)
同じ Host + Type の組み合わせを持つ複数のレコードをまとめた単位。NS なら 4 個の値が 1 つのレコードセット。
TTL (Time to Live)
DNS レコードがキャッシュされる秒数。短くすると変更が早く反映、長くすると DNS サーバへの負荷が下がる。
dig コマンド
DNS 問い合わせコマンド。dig CNAME lab.iigtn.com @8.8.8.8 で「Google DNS から見て lab.iigtn.com の CNAME が引けるか」を確認できる。