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
- Log into CloudFlare Dashboard
- Go to: My Profile → API Tokens
- Create Token with these permissions:
- Zone permissions:
Zone:Read
- Zone resources: Include all zones (or specific zones you want to migrate)
- Zone permissions:
- 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
-
Update the API token in the script:
# Edit the script and replace YOUR_CLOUDFLARE_API_TOKEN with your actual token nano cloudflare_export.py
-
Make the script executable:
chmod +x cloudflare_export.py
-
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
-
Navigate to the exported zones directory:
cd cloudflare_zones
-
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:
- From CloudFlare nameservers:
xxx.ns.cloudflare.com
- 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:
- Keep CloudFlare active until migration is fully verified
- DNS TTL management: Lower TTLs before migration for faster rollback
- Nameserver timing: Only update nameservers after thorough testing
For questions about PowerDNS configuration, see our main PowerDNS setup guide.