Skip to main content

NTC Route53 Migration (v1 → v2)

This guide covers the migration of terraform-aws-ntc-route53 from v1.x to v2.x.

Overview of Changes

v2.0.0 introduces significant architectural improvements to simplify multi-region configurations:

Key Changes

Featurev1.xv2.x
Provider ArchitectureAWS Provider v5AWS Provider v6 with region attribute
DNSSEC ConfigurationSeparate moduleIntegrated into root module
Query Logs ConfigurationSeparate moduleIntegrated into root module
Multi-Region SupportMultiple provider aliases + module callsSingle module with regions configuration
Module Complexity3+ module calls neededSingle module call

Before & After Comparison

Previous approach required 3 separate module configurations:

# Main hosted zone module
module "ntc_route53" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53?ref=1.3.0"
# ... configuration
}

# Separate DNSSEC module
module "ntc_route53_dnssec" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/dnssec?ref=1.3.0"
zone_id = module.ntc_route53.zone_id
# ... configuration
providers = {
aws.us_east_1 = aws.use1
}
}

# Separate Query Logs module
module "ntc_route53_query_logging" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/query-logs?ref=1.3.0"
zone_id = module.ntc_route53.zone_id
# ... configuration
providers = {
aws.us_east_1 = aws.use1
}
}

Migration Steps

Step 1: Upgrade AWS Provider to v6 (Keep NTC at v1.x)

Why Upgrade the Provider First?

Upgrade the AWS provider to v6 before upgrading NTC modules. This writes the new region attribute into the Terraform state for all existing resources. Without this intermediate step, resources managed through non-default (aliased) providers may be flagged for recreation during the NTC v2 upgrade.

Update only the provider version constraint. Keep all existing provider aliases and NTC module versions unchanged.

main.tf
terraform {
required_version = ">= 1.3.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0" # ← Updated from ~> 5.0
}
}
}

# Keep all existing provider aliases unchanged
provider "aws" {
region = "eu-central-1"
}

provider "aws" {
alias = "euc1"
region = "eu-central-1"
}

provider "aws" {
alias = "euc2"
region = "eu-central-2"
}

provider "aws" {
alias = "use1"
region = "us-east-1"
}

Initialize and apply:

terraform init -upgrade
terraform plan
# Expected: in-place updates adding the region attribute — NO recreations
terraform apply

Step 2: Simplify Provider Configuration

After the provider upgrade is applied, simplify the provider configuration for NTC v2:

main.tf
terraform {
required_version = ">= 1.5.7"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}

provider "aws" {
region = "eu-central-1"
}

# Regional providers still needed for some exceptions (where region attribute isn't supported)
provider "aws" {
alias = "use1"
region = "us-east-1"
}

Step 3: Consolidate Module Configuration

Extract DNSSEC and Query Log Configuration

If you have separate DNSSEC and Query Log modules, consolidate them:

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - PUBLIC HOSTED ZONE
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53?ref=1.3.0"

zone_name = "mydomain.com"
zone_description = "Managed by Terraform"
zone_type = "public"
}

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - DNSSEC (Separate Module)
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53_dnssec" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/dnssec?ref=1.3.0"

zone_id = module.ntc_route53.zone_id

key_signing_keys = [
{
ksk_name = "ksk-1"
ksk_status = "active"
}
]

providers = {
aws.us_east_1 = aws.use1
}
}

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - QUERY LOGGING (Separate Module)
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53_query_logging" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/query-logs?ref=1.3.0"

zone_id = module.ntc_route53.zone_id

providers = {
aws.us_east_1 = aws.use1
}
}

Step 4: Add State Migration Blocks

Create a state_migrations.tf file to migrate resources without recreating them:

state_migrations.tf
# ---------------------------------------------------------------------------------------------------------------------
# ¦ STATE MIGRATIONS - v1.x to v2.x
# ---------------------------------------------------------------------------------------------------------------------
# These moved blocks ensure Terraform state is updated without recreating resources
# Run: terraform plan - should show only "moved" operations (no creates/destroys)
# After successful migration, this file can be deleted

# -------------------------------------------------------------------------------------------------------------------
# DNSSEC
# -------------------------------------------------------------------------------------------------------------------
moved {
from = module.ntc_route53_dnssec.aws_kms_alias.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_kms_alias.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_kms_key.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_kms_key.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_route53_hosted_zone_dnssec.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_route53_hosted_zone_dnssec.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_route53_key_signing_key.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_route53_key_signing_key.ntc_dnssec["ksk-1"]
}

# -------------------------------------------------------------------------------------------------------------------
# QUERY LOGS
# -------------------------------------------------------------------------------------------------------------------
moved {
from = module.ntc_route53_query_logging.aws_route53_query_log.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_route53_query_log.ntc_query_log
}

moved {
from = module.ntc_route53_query_logging.aws_kms_key.ntc_query_log_encryption[0]
to = module.ntc_route53.module.query_logs[0].aws_kms_key.ntc_query_log_encryption[0]
}

moved {
from = module.ntc_route53_query_logging.aws_kms_alias.ntc_query_log_encryption[0]
to = module.ntc_route53.module.query_logs[0].aws_kms_alias.ntc_query_log_encryption[0]
}

moved {
from = module.ntc_route53_query_logging.aws_cloudwatch_log_resource_policy.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_cloudwatch_log_resource_policy.ntc_query_log
}

moved {
from = module.ntc_route53_query_logging.aws_cloudwatch_log_group.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_cloudwatch_log_group.ntc_query_log
}
State Migration Notes
  • These moved blocks tell Terraform to update its state without recreating resources
  • After successful migration (successful apply), you can delete state_migrations.tf
  • If you have different regions, adjust the region names accordingly

Step 5: Remove Old Definitions

After consolidating the configuration, remove the DNSSEC and Query Logs module calls.

Step 6: Initialize and Plan

# Upgrade to AWS Provider v6
terraform init -upgrade

# Review the plan
terraform plan

Expected plan output:

  • ✅ Many moved operations (state migrations)
  • ✅ Some in-place updates (configuration changes)
  • NO resource deletions or recreations

If you see deletions or recreations, do NOT apply! Review your configuration and state migration blocks carefully.

Step 7: Apply Migration

terraform apply

Monitor the output. The migration should complete without errors.

Step 8: Clean Up

After successful migration:

# Remove the state migration file (optional, but recommended)
rm state_migrations.tf

# Commit your changes
git add .
git commit -m "Migrate ntc-route53 from v1.x to v2.x"

Complete Example

See a complete before/after example in the GitHub repository:

Troubleshooting

Issue: Resources Being Recreated

Symptom: terraform plan shows deletions and recreations

Solution:

  1. Check your moved blocks match your existing state exactly
  2. Verify resource names haven't changed
  3. Use terraform state list to see current resource addresses

Issue: Provider Configuration Errors

Symptom: "provider configuration not present" errors

Solution:

  1. Ensure AWS Provider v6 is installed (terraform init -upgrade)
  2. Verify your required_providers block has version = "~> 6.0"

Issue: Region Not Supported

Symptom: "region not available" errors in ESC

Solution:

  1. For ESC, ensure you're using supported regions
  2. Check region codes match your partition (e.g., eu-central-1 vs eusc-de-east-1)

Need Help?