🌟

【Vercel】【Terraform】カスタムドメインを使ってみる

2025/01/10に公開

Vercel にアプリをデプロイすると、適当なドメインを発行しアクセスできるようになります。

しかし、特定のドメインを指定してアプリにアクセスしたい

そこで、今回はTerraform を使用して、カスタムドメインを設定します。

ゴール

こちらの記事でデプロイしたアプリにカスタムドメインでアクセスできること

https://zenn.dev/kuuki/articles/nextjs-terraform-vercel-deploy/

私の場合は、test.hisui-app.com をカスタムドメインとして設定していきます。

前提

  • Vercel にアプリをデプロイしている
  • AWS CLI および、Terraform が使える
  • Route53 にホストゾーンがある

使用しているバージョン

$ terraform -version
Terraform v1.4.2
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v4.67.0
+ provider registry.terraform.io/vercel/vercel v0.15.0

Terraform

main.tf

Route53 を使用したいので、Provider に AWS を追加します。(ハイライト部を追加)

main.tf
terraform {
  required_providers {
    vercel = {
      source  = "vercel/vercel"
      version = "~> 0.4"
    }
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
}

project.tf

Vercel のプロジェクトに設定したいカスタムドメインを指定します。

project.tf
resource "vercel_project" "example" {
  name      = "sample-blog-nextjs-app"
  framework = "nextjs"

  git_repository = {
    type = "github"
    # ユーザー名/リポジトリ名は置き換えてください
    repo = "<ユーザー名/リポジトリ名>"
  }
}

resource "vercel_project_domain" "example" {
  project_id = vercel_project.example.id
  domain     = "test.hisui-app.com"
}

route53.tf

カスタムドメインを Vercel の DNS サーバーで名前解決できるようにレコードを作成します。
Route53 に hisui-app.com のホストゾーンがあるため、そこに CNAME レコードを追加

route53.tf
# ホストゾーンの参照
data "aws_route53_zone" "example" {
  name = "hisui-app.com"

}

# CNAMEレコードを定義
resource "aws_route53_record" "example" {
  zone_id = data.aws_route53_zone.example.zone_id
  name    = "test"
  type    = "CNAME"
  ttl     = 300
  records = ["cname.vercel-dns.com"]
}

・aws_route53_record

プロパティ 説明
zone_id ホストゾーンの ID。
data で hisui-app.com のホストゾーンを参照し、その ID を指定。
name サブドメインで付け足す文字列。
test.hisui-app.com を使用したいので、test を指定。
type レコードタイプ。今回は、CNAME
ttl ttl。デフォルトの 300 を指定。
records レコードの値。
cname.vercel-dns.com は、Vercel の CNAME 用 DNS サーバーのこと。(参考)

init, plan, apply

init

Provider に AWS を追加したので、init が必要です

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 4.16"...
- Reusing previous version of vercel/vercel from the dependency lock file
- Installing hashicorp/aws v4.67.0...
- Installed hashicorp/aws v4.67.0 (signed by HashiCorp)
- Using previously-installed vercel/vercel v0.15.0

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

plan

~$ terraform plan
vercel_project.example: Refreshing state... [id=prj_****************]
vercel_deployment.example: Refreshing state... [id=dpl_*************]
data.aws_route53_zone.example: Reading...
data.aws_route53_zone.example: Read complete after 2s [id=***************]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_route53_record.example will be created
  + resource "aws_route53_record" "example" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "test"
      + records         = [
          + "cname.vercel-dns.com",
        ]
      + ttl             = 300
      + type            = "CNAME"
      + zone_id         = "***************"
    }

  # vercel_project_domain.example will be created
  + resource "vercel_project_domain" "example" {
      + domain     = "test.hisui-app.com"
      + id         = (known after apply)
      + project_id = "prj_****************"
      + team_id    = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

apply

~$ terraform apply
vercel_project.example: Refreshing state... [id=prj_****************]
data.aws_route53_zone.example: Reading...
vercel_deployment.example: Refreshing state... [id=dpl_*************]
data.aws_route53_zone.example: Read complete after 2s [id=***************]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_route53_record.example will be created
  + resource "aws_route53_record" "example" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "test"
      + records         = [
          + "cname.vercel-dns.com",
        ]
      + ttl             = 300
      + type            = "CNAME"
      + zone_id         = "***************"
    }

  # vercel_project_domain.example will be created
  + resource "vercel_project_domain" "example" {
      + domain     = "test.hisui-app.com"
      + id         = (known after apply)
      + project_id = "prj_****************"
      + team_id    = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

vercel_project_domain.example: Creating...
aws_route53_record.example: Creating...
vercel_project_domain.example: Creation complete after 1s [id=test.hisui-app.com]
aws_route53_record.example: Still creating... [10s elapsed]
aws_route53_record.example: Still creating... [20s elapsed]
aws_route53_record.example: Still creating... [30s elapsed]
aws_route53_record.example: Still creating... [40s elapsed]
aws_route53_record.example: Creation complete after 41s [id=***************_test_CNAME]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

動作確認

Vercel のコンソールにて、Project Settings > Domainsを確認します

下記のように 「Valid Configuration」や「Assigned to main」になっていれば OK!

最後に、カスタムドメインでアプリにアクセスできるか確認します。

対象のドメイン(私の場合は、https://test.hisui-app.com)にアクセスしてみましょう!

アプリが表示されれば OK ですー!

参考文献

https://vercel.com/docs/concepts/projects/domains/add-a-domain

https://vercel.com/docs/concepts/projects/domains/troubleshooting#common-dns-issues

https://registry.terraform.io/providers/vercel/vercel/latest/docs/resources/project_domain

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record

Discussion