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
exportline in a.envrcfile in your project directory, add.envrcto.gitignore, then rundirenv allowonce. It loads automatically whenever youcdin, and the key stays scoped to this project rather than every shell you open. - Simpler: add the same line to your shell profile (
~/.zshrcor~/.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_eastis the pool: a/32, the parent range everything else carves from. IPv6 pools just use IPv6 CIDRs; nothing else about the shape changes.paymentsfinds its own home automatically. It only declares environment/region/family, and nxip resolves it onto the pool above with no hardcoded parent.payments_az_aandpayments_az_bnest explicitly underpaymentsviaparent_subnet_id, the deliberate path for splitting a team's range across AZs.payments_lb_vipreserves one exact address insidepayments_az_a.cidrhost()works the same way on an IPv6 CIDR as an IPv4 one.
4. Run it.
terraform init
terraform applyWhat 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"/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 destroyPlan: 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.
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.
