Files
2025-11-29 18:00:21 +08:00
..
2025-11-29 18:00:21 +08:00
2025-11-29 18:00:21 +08:00
2025-11-29 18:00:21 +08:00

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:

  1. IP address created in NetBox with production-dns tag
  2. Plugin detects new IP matches zone rule
  3. Plugin calls PowerDNS API to create records:
    • A record from dns_name field
    • PTR record from IP address
  4. 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-dns tag
  • dns_name field is set

2. Check zone configuration:

  • NetBox → Plugins → NetBox PowerDNS Sync → Zones
  • Verify spaceships.work zone 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

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