VM with Automatic DNS Registration
Learning objective: Experience the full infrastructure automation workflow from VM creation to DNS resolution.
What This Example Demonstrates
This is the "holy grail" of infrastructure automation - deploy infrastructure and have DNS automatically configured:
Terraform Deploy → Proxmox VM Created → NetBox IP Registered
→ PowerDNS Records Auto-Created → Ready for Ansible
Benefits:
- ✅ No manual DNS configuration
- ✅ Single source of truth (NetBox)
- ✅ Audit trail for all infrastructure changes
- ✅ Automatic forward + reverse DNS
- ✅ Ready for dynamic inventory
Architecture
┌──────────────┐
│ Terraform │
└──────┬───────┘
│
├─ Creates VM in Proxmox ─────────────► VM: docker-01-nexus
│ IP: 192.168.1.100
│
└─ Registers IP in NetBox ────────────► NetBox IPAM
│ Tags: ["production-dns"]
│
│ netbox-powerdns-sync plugin (automatic)
│
▼
┌────────────┐
│ PowerDNS │
└─────┬──────┘
│
├─► A record: docker-01-nexus.spaceships.work → 192.168.1.100
└─► PTR record: 100.1.168.192.in-addr.arpa → docker-01-nexus.spaceships.work
Prerequisites
1. Proxmox Template
Template must exist (default: VMID 9000):
# Create using Virgo-Core template deployment
cd ../../../terraform/netbox-template
tofu apply
2. NetBox Configuration
NetBox PowerDNS Sync Plugin must be configured with:
- Zone:
spaceships.work - Tag rule matching:
production-dns - PowerDNS server connection configured
See: ../../reference/sync-plugin-reference.md
3. Environment Variables
# Proxmox
export PROXMOX_VE_ENDPOINT="https://192.168.3.5:8006"
export PROXMOX_VE_API_TOKEN="user@realm!token-id=secret"
# NetBox
export NETBOX_API_TOKEN="your-netbox-token"
export TF_VAR_netbox_api_token="$NETBOX_API_TOKEN"
# SSH Key
export TF_VAR_ssh_public_key="$(cat ~/.ssh/id_rsa.pub)"
4. DNS Naming Convention
FQDN must follow: <service>-<NN>-<purpose>.<domain>
Validate name first:
../../tools/validate_dns_naming.py docker-01-nexus.spaceships.work
Quick Start
1. Initialize
tofu init
2. Plan
tofu plan
Expected resources:
- 1 Proxmox VM (docker-01-nexus)
- 1 NetBox IP address (192.168.1.100)
- DNS records created automatically (not shown in plan)
3. Deploy
tofu apply
Wait 30 seconds for DNS propagation (netbox-powerdns-sync runs async).
4. Verify Complete Workflow
Step 1: Check VM exists
# On Proxmox node
qm status $(terraform output -raw vm_id)
Step 2: Check NetBox registration
curl -H "Authorization: Token $NETBOX_API_TOKEN" \
"https://netbox.spaceships.work/api/ipam/ip-addresses/?address=192.168.1.100" | jq
Step 3: Verify DNS forward resolution
dig @192.168.3.1 docker-01-nexus.spaceships.work +short
# Expected: 192.168.1.100
Step 4: Verify DNS reverse resolution
dig @192.168.3.1 -x 192.168.1.100 +short
# Expected: docker-01-nexus.spaceships.work.
Step 5: SSH into VM
ssh ansible@docker-01-nexus.spaceships.work
# or
ssh ansible@192.168.1.100
5. Cleanup
tofu destroy
Note: DNS records are automatically removed when NetBox IP is deleted.
How It Works
The Magic Tag: production-dns
resource "netbox_ip_address" "docker_host" {
tags = [
"terraform",
"production-dns", # ← This triggers DNS automation
"docker-host"
]
}
The production-dns tag matches a zone rule in NetBox PowerDNS Sync plugin configuration.
NetBox PowerDNS Sync Plugin
Configuration (in NetBox):
# Plugins → NetBox PowerDNS Sync → Zones → spaceships.work
zone_config = {
"name": "spaceships.work",
"powerdns_server": "PowerDNS Server 1",
"tag_match": ["production-dns"], # ← Matches our tag
"naming_method": "device", # Use device/IP name
"auto_sync": True,
"sync_schedule": "*/5 * * * *" # Every 5 minutes
}
What happens:
- IP address created in NetBox with
production-dnstag - Plugin detects new IP matches zone rule
- Plugin calls PowerDNS API to create records:
- A record from
dns_namefield - PTR record from IP address
- A record from
- Records appear in DNS within 30 seconds
Customization
Different Service Type
# In terraform.tfvars or as -var
vm_name = "k8s-01-master"
fqdn = "k8s-01-master.spaceships.work"
Development Environment
Use different domain and tags:
variable "dns_domain" {
default = "dev.spaceships.work"
}
resource "netbox_ip_address" "docker_host" {
tags = ["terraform", "dev-dns", "docker-host"] # Different tag for dev zone
}
Multiple Environments
# Production
tofu apply -var-file=prod.tfvars
# Development
tofu apply -var-file=dev.tfvars
Troubleshooting
DNS Records Not Created
1. Check NetBox IP registration:
curl -H "Authorization: Token $NETBOX_API_TOKEN" \
"https://netbox.spaceships.work/api/ipam/ip-addresses/?dns_name=docker-01-nexus.spaceships.work" | jq
Verify:
- IP exists in NetBox
- Has
production-dnstag dns_namefield is set
2. Check zone configuration:
- NetBox → Plugins → NetBox PowerDNS Sync → Zones
- Verify
spaceships.workzone exists - Check tag rules match
production-dns
3. Check sync results:
- NetBox → Plugins → NetBox PowerDNS Sync → Zones → spaceships.work
- Click "Sync Now" to manually trigger
- Review sync results for errors
4. Check PowerDNS:
# Query PowerDNS API directly
curl -H "X-API-Key: $POWERDNS_API_KEY" \
http://192.168.3.1:8081/api/v1/servers/localhost/zones/spaceships.work | jq
SSH Connection Fails
Try IP first:
ssh ansible@192.168.1.100
If IP works but FQDN doesn't:
- DNS not propagated yet (wait 30s)
- Check DNS resolution:
dig @192.168.3.1 docker-01-nexus.spaceships.work
NetBox Provider Authentication
Error: authentication failed
Solution:
# Test API token
curl -H "Authorization: Token $NETBOX_API_TOKEN" \
https://netbox.spaceships.work/api/status/ | jq
# Regenerate token if needed
# NetBox → Admin → API Tokens → Create
Integration with Ansible
After deployment, use for Ansible configuration:
---
# Ansible playbook using NetBox dynamic inventory
- name: Configure Docker hosts
hosts: tag_docker_host # From NetBox tags
become: true
tasks:
- name: Install Docker
ansible.builtin.apt:
name: docker.io
state: present
Run with dynamic inventory:
cd ../../../ansible
ansible-playbook -i inventory/netbox.yml playbooks/configure-docker.yml
See: ../../workflows/ansible-dynamic-inventory.md
Next Steps
Learn More Workflows
- Bulk Deployment:
../02-bulk-deployment/(coming soon) - DNS Automation Guide: ../../workflows/dns-automation.md
- Naming Conventions: ../../workflows/naming-conventions.md
Production Checklist
Before using in production:
- NetBox PowerDNS Sync plugin tested and working
- DNS naming convention documented
- Zone rules configured for all environments
- API tokens secured (not in version control)
- Backup/restore procedures for NetBox
- Monitoring for DNS sync failures
- Documentation for team
Benefits of This Approach
Single Source of Truth:
- All infrastructure documented in NetBox
- DNS automatically matches reality
- Easy to audit what exists
Automation:
- No manual DNS configuration
- Reduced human error
- Faster deployments
Consistency:
- Naming convention enforced
- Tag-based organization
- Audit trail via Terraform
Integration:
- Ansible dynamic inventory
- Monitoring integrations
- IPAM + DNS + DCIM in one place