Docs / Terraform / IPv6

Quick start with Terraform: IPv6

The same loop as the IPv4 quick start, kept separate so it stays simple to follow: a workingmain.tf, five commands, and a real allocated IPv6 subnet by the end of it. Working in IPv4? See the IPv4 quick start instead.

Quick start

1. Get an API key. Sign up. Free tier is enough to run this end to end, and IPv6 is first-class, not a separate tier.

2. Set it as an environment variable. The provider reads it automatically, so no credential goes in a .tf file.

export NXIP_API_KEY="<your key>"

That only lasts for the current terminal session. To make it stick around:

  • Recommended: direnv. Put the same export line in a .envrc file in your project directory, add .envrc to .gitignore, then run direnv allow once. It loads automatically whenever you cd in, and the key stays scoped to this project rather than every shell you open.
  • Simpler: add the same line to your shell profile (~/.zshrc or ~/.bashrc). Works everywhere with no extra tool, at the cost of the key being available in every terminal, sitting in plaintext in a dotfile you might sync or share elsewhere.

Either way: never paste the key directly into a .tf file or commit it anywhere.

3. Save this as main.tf. Same five resources as the IPv4 walkthrough: a pool, a subnet that finds its own home, that subnet split explicitly across two AZs, and one exact address reserved inside one of them.

terraform {
  required_providers {
    nxip = {
      source  = "uk-sw/nxip"
      version = "~> 0.2" # optional, but recommended
    }
  }
}

provider "nxip" {
  # api_key / url also read from NXIP_API_KEY / NXIP_URL env vars
}

resource "nxip_pool" "production_us_east" {
  name        = "Production US-East (IPv6)"
  cidr        = "fd00:100::/32"
  family      = "IPV6"
  environment = "production"
  region      = "us-east-1"
}

# Auto-resolves onto the pool above by matching environment/region/family.
resource "nxip_subnet" "payments" {
  family        = nxip_pool.production_us_east.family
  environment   = nxip_pool.production_us_east.environment
  region        = nxip_pool.production_us_east.region
  prefix_length = 56
  name          = "Payments team"
}

# Explicit nesting via parent_subnet_id: splits the team's subnet across two AZs.
resource "nxip_subnet" "payments_az_a" {
  parent_subnet_id = nxip_subnet.payments.id
  family            = "IPV6"
  prefix_length     = 64
  kind              = "az-subnet"
  name              = "Payments AZ-a"
}

resource "nxip_subnet" "payments_az_b" {
  parent_subnet_id = nxip_subnet.payments.id
  family            = "IPV6"
  prefix_length     = 64
  kind              = "az-subnet"
  name              = "Payments AZ-b"
}

# One exact address inside that AZ subnet, e.g. a load balancer VIP.
resource "nxip_address" "payments_lb_vip" {
  subnet_id = nxip_subnet.payments_az_a.id
  address   = cidrhost(nxip_subnet.payments_az_a.cidr, 1)
  status    = "RESERVED"
  hostname  = "payments-lb-01"
}

output "payments_subnet_cidr" {
  value = nxip_subnet.payments.cidr
}
output "payments_az_a_cidr" {
  value = nxip_subnet.payments_az_a.cidr
}
output "payments_az_b_cidr" {
  value = nxip_subnet.payments_az_b.cidr
}
output "payments_lb_vip_address" {
  value = nxip_address.payments_lb_vip.address
}
  • production_us_east is the pool: a /32, the parent range everything else carves from. IPv6 pools just use IPv6 CIDRs; nothing else about the shape changes.
  • payments finds its own home automatically. It only declares environment/region/family, and nxip resolves it onto the pool above with no hardcoded parent.
  • payments_az_a and payments_az_b nest explicitly under payments via parent_subnet_id, the deliberate path for splitting a team's range across AZs.
  • payments_lb_vip reserves one exact address inside payments_az_a. cidrhost() works the same way on an IPv6 CIDR as an IPv4 one.

4. Run it.

terraform init
terraform apply

What you'll see, trimmed to the parts that matter:

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

Do you want to perform these actions?
  Enter a value: yes

nxip_pool.production_us_east: Creating...
nxip_pool.production_us_east: Creation complete after 0s [id=cm...]
nxip_subnet.payments: Creating...
nxip_subnet.payments: Creation complete after 0s [id=cm...]
nxip_subnet.payments_az_a: Creating...
nxip_subnet.payments_az_a: Creation complete after 0s [id=cm...]
nxip_subnet.payments_az_b: Creating...
nxip_subnet.payments_az_b: Creation complete after 0s [id=cm...]
nxip_address.payments_lb_vip: Creating...
nxip_address.payments_lb_vip: Creation complete after 0s [id=cm...]

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

Outputs:

payments_az_a_cidr = "fd00:100::/64"
payments_az_b_cidr = "fd00:100:0:1::/64"
payments_lb_vip_address = "fd00:100::1"
payments_subnet_cidr = "fd00:100::/56"
Same rules as IPv4: every attribute on these resources is immutable, changing one replaces the resource rather than editing it in place, since address blocks and reservations aren't safely mutable once something might already be using them. There's also no per-address quota for IPv6 the way there is for IPv4 (a single /64 already holds more addresses than a count-based limit could ever mean anything against); subnet count is what's tracked instead.

Clean up when you're done

Free tier caps out at 20 subnets total across both families, so destroying what you don't need frees that quota back up for the next thing you try.

terraform destroy
Plan: 0 to add, 0 to change, 5 to destroy.

Do you really want to destroy all resources?
  Enter a value: yes

nxip_address.payments_lb_vip: Destroying...
nxip_address.payments_lb_vip: Destruction complete after 0s
nxip_subnet.payments_az_b: Destroying...
nxip_subnet.payments_az_b: Destruction complete after 0s
nxip_subnet.payments_az_a: Destroying...
nxip_subnet.payments_az_a: Destruction complete after 0s
nxip_subnet.payments: Destroying...
nxip_subnet.payments: Destruction complete after 0s
nxip_pool.production_us_east: Destroying...
nxip_pool.production_us_east: Destruction complete after 0s

Destroy complete! Resources: 5 destroyed.

Watch it happen

The whole loop above, played back start to finish.

main.tf · terraform

Full resource docs (every attribute, import support) are on the Registry's docs tab. For the concepts behind auto-resolution and nesting, see Pools, subnets & hierarchy, or the IPv4 quick start for the same walkthrough in IPv4.