Terraform provider
The doon-io/aigw provider is the official way to manage your aigw tenant as code: zones, records, GSLB pools and members, health monitors, zone security policies, notification channels, and TLS certs issued via ACME with DNS-01 solved automatically.
It’s the same surface area as the console, in HCL.
Install
terraform {
required_providers {
aigw = {
source = "doon-io/aigw"
version = "~> 0.1"
}
}
}
# api_key can also come from AIGW_API_KEY in the env.
provider "aigw" {
api_key = var.aigw_api_key
}
variable "aigw_api_key" {
description = "API key from Settings, API keys in the aigw console."
type = string
sensitive = true
}
The API key comes from Settings → API keys in the console. Lock it to a CIDR on the same screen if you only run Terraform from known runners; the API enforces the allow-list and a 403 fires the moment the key is used from anywhere else.
For self-hosted aigw, override endpoint (or AIGW_ENDPOINT)
with the full URL including the /api prefix:
provider "aigw" {
endpoint = "https://aigw.internal.example.com/api"
api_key = var.aigw_api_key
}
Full example
A zone, a weighted GSLB pool with two backends, the record that serves it, a health monitor on the backends, and a TLS cert for the FQDN, in one apply:
resource "aigw_zone" "acme" {
name = "acme.com"
}
resource "aigw_pool" "api" {
name = "api-backends"
selection_method = "weighted"
}
resource "aigw_pool_member" "api_us" {
pool_id = aigw_pool.api.id
target = "203.0.113.10"
weight = 100
enabled = true
}
resource "aigw_pool_member" "api_eu" {
pool_id = aigw_pool.api.id
target = "203.0.113.20"
weight = 100
enabled = true
}
resource "aigw_health_monitor" "api" {
name = "api-tcp-443"
type = "tcp"
port = 443
interval = 30
}
resource "aigw_record" "api" {
zone_id = aigw_zone.acme.id
name = "api"
type = "POOL"
ttl = 60
pool_id = aigw_pool.api.id
}
resource "aigw_cert" "api" {
names = ["api.acme.com"]
}
terraform plan shows exactly what will change. terraform apply walks
the dependency graph: the zone, the pool, the members, the monitor, the
record, then the cert (which needs the zone to solve DNS-01).
What’s covered
| Resource | Notes |
|---|---|
aigw_zone | Apex settings (default TTL, SOA RNAME, negative TTL). |
aigw_record | A, AAAA, CNAME, MX, TXT, SRV, NS, CAA, ANAME, plus the GSLB types. |
aigw_pool | GSLB pool definition with selection method. |
aigw_pool_member | Backends attached to a pool. |
aigw_endpoint | Probe target for uptime + SLA tracking. |
aigw_health_monitor | TCP, HTTP, UDP, ICMP, DNS probes for pool members. |
aigw_zone_policy | Per-zone hijack monitor and query firewall. |
aigw_notification_channel | Slack, webhook, or email target. |
aigw_cert | TLS cert issued via your tenant’s ACME CA, DNS-01 solved for you. |
Read-only data sources are available for zones, pools, endpoints, and health monitors when you need to look something up by name from elsewhere in your config.
The per-resource reference, every argument and computed attribute, lives on the Terraform Registry.
TLS certs
aigw_cert is the part most other DNS providers can’t do in one
move. Because aigw owns the zone, it can solve the ACME DNS-01
challenge against the zone you already manage, no second provider for
cert issuance, no out-of-band ACME runner, no manual TXT records.
resource "aigw_cert" "web" {
names = [
"acme.com",
"*.acme.com",
]
# Triggers replacement when fewer than 21 days remain. Default is 30.
# Set to 0 to disable auto-renewal and rotate with terraform apply
# -replace=... on a cron instead.
min_days_remaining = 21
}
output "web_fullchain" {
value = aigw_cert.web.fullchain_pem
sensitive = false
}
output "web_private_key" {
value = aigw_cert.web.private_key_pem
sensitive = true
}
The private key is generated server-side, signed, returned in the response once, and never persisted on the aigw side. It lives in your Terraform state, so make sure your state backend is encrypted at rest.
Renewal happens at plan-time: when the cert is within min_days_remaining
of expiry the next plan marks the resource for replacement and a fresh
cert is issued on apply.
Verify what you actually deployed
The provider also ships aigw_test_query, a data source that runs a
real DNS query at plan-time and fails the apply if the answer doesn’t
match what you declared. Useful as a guardrail on the records you care
most about.
data "aigw_test_query" "api_resolves" {
name = "api.acme.com"
type = "A"
expect = {
contains = ["203.0.113.10", "203.0.113.20"]
}
}
If the live answer doesn’t contain the expected IPs at apply-time, the
apply halts. Combined with depends_on, you can use it to gate
downstream resources (a CDN config, a load balancer pointing at the
same FQDN) on the DNS actually being live.
Where to go next
- Terraform Registry: per-resource reference with every argument and computed attribute.
- GitHub: source, issues, releases.
- Records: every record type, including the GSLB ones the provider knows how to model.
- Pools & members: selection methods, member priority, attaching pools to records.
- TLS: how the ACME side works, including CAA pre-flight and the coverage gap detector.