🛡️ Access Shield Pro v1.2 released - Now with Spamhaus & Emerging Threats feeds
🤖 AI Support Assistant 2.1 - GPT-5 & Claude Opus 4.1 support, auto-signatures, improved error handling.
🧮 Recalculate Prices v1.2 - Fixed addon pricing, enhanced safety checks, full billing cycle support.
🔧 PowerDNS Manager v1.11 - Enhanced logging security with better data sanitization, improved debug output handling, bug fixes.

Migrating DNS Zones from CloudFlare to PowerDNS Print

  • 0

Overview

This guide walks you through the complete process of migrating your DNS zones from CloudFlare to a PowerDNS infrastructure. The process involves exporting zones from CloudFlare via their API and importing them into PowerDNS using our specialized import script.

Prerequisites

  • CloudFlare API Token: Generate a token with Zone:Read permissions for all your zones
  • PowerDNS Setup: Have a working PowerDNS installation (see our PowerDNS Master-Slave Configuration Guide)
  • Python 3: Required for both export and import scripts
  • Required Python packages: requests for CloudFlare API interaction

Part 1: Install Dependencies

# Install required Python package
pip3 install requests

# Ensure PowerDNS importer script is available
# (This should already be installed if following the main PowerDNS guide)
sudo chmod +x /usr/local/bin/powerdns_importer.py

Part 2: Generate CloudFlare API Token

  1. Log into CloudFlare Dashboard
  2. Go to: My Profile → API Tokens
  3. Create Token with these permissions:
    • Zone permissions: Zone:Read
    • Zone resources: Include all zones (or specific zones you want to migrate)
  4. Save the token - you'll need it for the export script

Part 3: Export Zones from CloudFlare

Create the CloudFlare export script:

nano cloudflare_export.py

Add the following content:

#!/usr/bin/env python3

import requests
import os
import sys

# Set your Cloudflare API credentials
api_token = 'YOUR_CLOUDFLARE_API_TOKEN'
headers = {
    'Authorization': f'Bearer {api_token}',
    'Content-Type': 'application/json'
}

# Cloudflare API endpoints
base_url = 'https://api.cloudflare.com/client/v4'
zones_endpoint = f'{base_url}/zones'

def fetch_paginated_results(url, params=None):
    all_results = []
    while url:
        response = requests.get(url, headers=headers, params=params)
        if response.status_code == 200:
            data = response.json()
            all_results.extend(data['result'])
            info = data['result_info']
            if info['page'] < info['total_pages']:
                params = {'page': info['page'] + 1, 'per_page': info['per_page']}
            else:
                break
        else:
            print(f"Failed to fetch data: {response.status_code} - {response.text}")
            return None
    return all_results

def fetch_zones():
    return fetch_paginated_results(zones_endpoint)

def fetch_zone_records(zone_id):
    records_endpoint = f'{base_url}/zones/{zone_id}/dns_records'
    return fetch_paginated_results(records_endpoint)

def export_zone_to_file(zone_name, records):
    filename = f'{zone_name}.txt'
    with open(filename, 'w') as file:
        file.write(f"$ORIGIN {zone_name}.\n")
        file.write("$TTL 3600\n\n")
        for record in records:
            name = record['name'].replace(f".{zone_name}", "") or "@"
            file.write(f"{name}\t{record['ttl']}\tIN\t{record['type']}\t{record['content']}\n")
    print(f"Exported {zone_name} to {filename}")

def main():
    if api_token == 'YOUR_CLOUDFLARE_API_TOKEN':
        print("Please set your Cloudflare API token in the script.")
        sys.exit(1)

    zones = fetch_zones()
    if not zones:
        print("No zones found or failed to fetch zones.")
        return
    
    os.makedirs('cloudflare_zones', exist_ok=True)
    os.chdir('cloudflare_zones')
    
    for zone in zones:
        zone_id = zone['id']
        zone_name = zone['name']
        print(f"Fetching records for zone: {zone_name}")
        records = fetch_zone_records(zone_id)
        if records:
            export_zone_to_file(zone_name, records)

if __name__ == "__main__":
    main()

Part 4: Run the Export

  1. Update the API token in the script:

    # Edit the script and replace YOUR_CLOUDFLARE_API_TOKEN with your actual token
    nano cloudflare_export.py
  2. Make the script executable:

    chmod +x cloudflare_export.py
  3. Run the export:

    python3 cloudflare_export.py

    This will create a cloudflare_zones directory containing .txt files for each zone.

Part 5: Import Zones into PowerDNS

  1. Navigate to the exported zones directory:

    cd cloudflare_zones
  2. Import all zones using the PowerDNS importer:

    python3 /usr/local/bin/powerdns_importer.py .

    The importer will:

    • Create each zone in PowerDNS
    • Import all DNS records
    • Rectify zones for proper operation
    • Trigger notifications to slave servers (if configured)

Part 6: Post-Migration Tasks

Update Nameservers

After successful import, you'll need to update nameservers at your domain registrars:

  1. From CloudFlare nameservers: xxx.ns.cloudflare.com
  2. To your PowerDNS nameservers: ns1.yourdomain.com, ns2.yourdomain.com

Enable DNSSEC (Optional)

If you want DNSSEC on migrated zones:

# For each zone, enable DNSSEC
sudo pdnsutil secure-zone example.com
sudo pdnsutil increase-serial example.com
sudo pdns_control notify example.com

# Get DS records for registrar
sudo pdnsutil export-zone-ds example.com

Verify Migration

Check that zones are working correctly:

# List all imported zones
sudo pdnsutil list-all-zones

# Test DNS resolution
dig @ns1.yourdomain.com example.com SOA
dig @ns1.yourdomain.com www.example.com A

Part 7: Migration Checklist

  • ☐ CloudFlare API token generated
  • ☐ Export script configured with correct token
  • ☐ All zones exported successfully
  • ☐ Zones imported into PowerDNS
  • ☐ DNS resolution tested
  • ☐ Nameservers updated at registrars
  • ☐ DNSSEC enabled (if desired)
  • ☐ DS records updated at registrars (if using DNSSEC)
  • ☐ Monitoring configured for new setup

Troubleshooting

Common Export Issues

API Rate Limiting: If you have many zones, add delays between API calls:

import time
# Add this after each API call
time.sleep(0.1)

Authentication Errors: Verify your API token has correct permissions and isn't expired.

Common Import Issues

SOA Record Conflicts: The importer handles SOA records automatically, but verify they're correct after import.

TTL Values: CloudFlare proxy records may have modified TTLs. Review and adjust if needed.

Record Types: Some CloudFlare-specific record types may not import. Review the logs for any skipped records.

Performance Tips

  • Large migrations: Import zones in batches rather than all at once
  • Test first: Try importing a few test zones before doing the full migration
  • Monitor resources: Watch CPU and memory usage during import of large zone sets

Rollback Plan

If issues arise:

  1. Keep CloudFlare active until migration is fully verified
  2. DNS TTL management: Lower TTLs before migration for faster rollback
  3. Nameserver timing: Only update nameservers after thorough testing

For questions about PowerDNS configuration, see our main PowerDNS setup guide.


Was this answer helpful?

« Back

WHOIS Information

×
Loading WHOIS information...