Deleting tunnel should clean dns as well
I deleted tunnel named "main", but result of cloudflared tunnel route dns main <hostname> was not deleted and then when trying to create tunnel with same name and route again, got this error:
Failed to add route: code: 1003, reason: An A, AAAA or CNAME record already exists with that host.
Having the same issue.
I can change the subdomain for the dns record but am unauthorized to delete it

what is the status on this?
Bump on this too, I'm still facing this issue and it's becoming very annoying to move records from one tunnel connector to another. Currently the process to move the test.example.com hostname to another connector is:
- Delete the
test.example.comhostname in the relevant tunnel connector page - Navigate to the
example.comDNS settings page from within normal Cloudflare - Delete the CNAME record for
test.example.com - Navigate back to Zero Trust
- Create new
test.example.comhostname under new tunnel connector - Things start working again
Ideally this process should be majorly simplified, something along the lines of :
- Delete the
test.example.comhostname in the relevant tunnel connector page - Create new
test.example.comhostname under new tunnel connector - Things start working again
As you can see, this process is extremely tedious, especially when you have multiple domains managed with tunnels, each with multiple hostnames configured, requiring even more steps to go through.
My final recommendation would be to change the "Delete hostname" action within the tunnel connector to also clean up the DNS record that IT CREATED, so that you can easily go back and recreate it again under a different connector.
what I found while going through it again is. -> If you create publiic hostname in the tunnel it creates dns record. -> if you delete the public hostname, it deletes the dns record -> if you delete the tunnel without deleting the public hostname, the dns record stays.
Ah yes you're right @pen-pal! That must've been a recent change. Regardless, deleting the a tunnel with two dozen hostnames configured under it should absolutely then delete the associated DNS records as well.
I ran into this issue today after recreating all my tunnels. Instead of fixing the entries manually, I created a little script to do this for me. I put it up on GitHub just in case it might help someone else: https://github.com/JonMerlevede/fix-cloudflare-tunnel-dns.
I'm also encountering this issue. I've automated our infrastructure using Terraform and Ansible, and everything works well, except that the CNAME DNS records pointing to the tunnel are not deleted when the tunnel is destroyed by Terraform. This is quite frustrating.
When a DNS record is automatically created with the public hostname of a tunnel, it should definitely also be automatically deleted when the tunnel is removed.
I'm also encountering this issue. I've automated our infrastructure using Terraform and Ansible, and everything works well, except that the CNAME DNS records pointing to the tunnel are not deleted when the tunnel is destroyed by Terraform. This is quite frustrating.
When a DNS record is automatically created with the public hostname of a tunnel, it should definitely also be automatically deleted when the tunnel is removed.
I use this sh script for my ansible playbooks:
#!/bin/bash
## Set the following variables in your playbook as environment variables
# CF_RECORD_NAME="" # DNS record name to delete
# ZONE_ID="" # Cloudflare zone ID in vault
# API_KEY="" # Cloudflare API key in vault
# EMAIL="" # Cloudflare email in vault
# 1. Find RECORD_ID
FIND_URL="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${CF_RECORD_NAME}"
FIND_RESULT=$(curl -s -X GET "$FIND_URL" -H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $API_KEY" -H "Content-Type: application/json")
RECORD_ID=$(echo "$FIND_RESULT" | jq -r '.result[0].id')
if [ -z "$RECORD_ID" ]; then
echo "DNS record '$CF_RECORD_NAME' not found in zone '$ZONE_ID'."
exit 1
fi
echo "Found DNS record ID: $RECORD_ID"
# 2. Delete CF_RECORD_NAME
DELETE_URL="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}"
DELETE_RESULT=$(curl -s -X DELETE "$DELETE_URL" -H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $API_KEY" -H "Content-Type: application/json")
DELETED=$(echo "$DELETE_RESULT" | jq -r '.success')
if [ "$DELETED" == "true" ]; then
echo "DNS record '$CF_RECORD_NAME' successfully deleted."
else
echo "Failed to delete DNS record '$CF_RECORD_NAME'."
echo "$DELETE_RESULT"
exit 1
fi
Here are the playbook tasks:
- name: Delete Cloudflare DNS record using script
ansible.builtin.template:
src: templates/cloudflare-delete-dns-record.sh.j2
dest: /tmp/cloudflare-delete-dns-record.sh
mode: "0755"
become: true
tags:
- uninstall
- name: Delete Cloudflare DNS record
ansible.builtin.command: /tmp/cloudflare-delete-dns-record.sh
environment:
CF_RECORD_NAME: "{{ inventory_hostname }}.YOUR-DOMAIN"
ZONE_ID: "{{ vault_cf_zone_id }}"
API_KEY: "{{ vault_cf_api_key }}"
EMAIL: "{{ vault_cf_email }}"
register: my_output
changed_when: my_output.rc != 0
become: true
tags:
- uninstall
I would prefer to have a separate command to delete dns record. See https://github.com/cloudflare/cloudflared/issues/781/