Drivers

Cloudflare DNS Driver

Introduction

The Cloudflare DNS Driver provides a fully typed interface for managing DNS zones and records via the Cloudflare API v4. It uses the Kipchak HTTP driver as its HTTP client, so no additional HTTP library is required.

Key features include:

  • Multiple Connections: Configure separate API tokens for multiple Cloudflare accounts.
  • Fully Typed API: Dedicated request objects, result objects, and enums — your IDE will guide you through every call.
  • Zone Management: List and inspect zones.
  • DNS Record Management: Create, read, full-replace (PUT), partial-update (PATCH), and delete records.
  • All Record Types: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, and all other types supported by Cloudflare.

Installation

Install the driver via Composer:

composer require kipchak/driver-cloudflare-dns

Initialise the Driver

Add the following to your drivers/drivers.php file. The Cloudflare DNS driver depends on the Config and HTTP drivers, so it must be initialised after them:

use Kipchak\Driver\CloudflareDns\CloudflareDns;

CloudflareDns::initialise($container);

Configuration

Create a file named kipchak.cloudflare-dns.php in your project's config/ directory.

Connection Settings

Define one or more named connections under the connections key:

  • api_token (required): A Cloudflare API Token with Zone:Read and DNS:Edit permissions.
  • base_url (optional): Override the API base URL. Defaults to https://api.cloudflare.com/client/v4.

Example Configuration

<?php

use function Kipchak\Core\env;

return [
    'connections' => [
        'default' => [
            'api_token' => env('CF_API_TOKEN', ''),
        ],
        // Add further named connections for multiple Cloudflare accounts:
        // 'secondary' => [
        //     'api_token' => env('CF_SECONDARY_API_TOKEN', ''),
        // ],
    ],
];

Environment Variables

CF_API_TOKEN=your-cloudflare-api-token

Usage

Retrieve a connection by name. If no name is given, default is used.

use Kipchak\Driver\CloudflareDns\CloudflareDns;

$cf = CloudflareDns::get();             // 'default' connection
$cf = CloudflareDns::get('secondary');  // named connection

Zones

use Kipchak\Driver\CloudflareDns\Enum\ZoneStatus;
use Kipchak\Driver\CloudflareDns\Request\ListZonesRequest;

// List all zones — returns ZoneResult[]
$zones = $cf->listZones();

// Filter by name and status
$zones = $cf->listZones(new ListZonesRequest(
    name:   'example.com',
    status: ZoneStatus::Active,
));

foreach ($zones as $zone) {
    echo $zone->id;
    echo $zone->name;
    echo $zone->status->value; // 'active'
}

// Get a single zone — returns ZoneResult
$zone = $cf->getZone('023e105f4ecef8ad9ca31a8372d0c353');

Listing DNS Records

use Kipchak\Driver\CloudflareDns\Enum\DnsRecordType;
use Kipchak\Driver\CloudflareDns\Request\ListDnsRecordsRequest;

$zoneId = '023e105f4ecef8ad9ca31a8372d0c353';

// List all records — returns DnsRecordResult[]
$records = $cf->listDnsRecords($zoneId);

// Filter by type and name
$records = $cf->listDnsRecords($zoneId, new ListDnsRecordsRequest(
    type: DnsRecordType::A,
    name: 'api.example.com',
));

// Get a single record — returns DnsRecordResult
$record = $cf->getDnsRecord($zoneId, 'dns-record-id');
echo $record->type->value;  // 'A'
echo $record->content;      // '192.0.2.1'

Creating a DNS Record

use Kipchak\Driver\CloudflareDns\Request\CreateDnsRecordRequest;

// A record
$record = $cf->createDnsRecord($zoneId, new CreateDnsRecordRequest(
    type:    DnsRecordType::A,
    name:    'api.example.com',
    content: '192.0.2.1',
    ttl:     1,       // 1 = automatic
    proxied: false,
    comment: 'API server',
));

// MX record (priority required)
$record = $cf->createDnsRecord($zoneId, new CreateDnsRecordRequest(
    type:     DnsRecordType::MX,
    name:     'example.com',
    content:  'mail.example.com',
    priority: 10,
));

Updating a DNS Record

Use updateDnsRecord (PUT) for a full replacement where all fields must be supplied, or patchDnsRecord (PATCH) to change only specific fields.

use Kipchak\Driver\CloudflareDns\Request\PatchDnsRecordRequest;
use Kipchak\Driver\CloudflareDns\Request\UpdateDnsRecordRequest;

$recordId = 'dns-record-id';

// Full replacement — all fields sent to Cloudflare
$record = $cf->updateDnsRecord($zoneId, $recordId, new UpdateDnsRecordRequest(
    type:    DnsRecordType::A,
    name:    'api.example.com',
    content: '192.0.2.2',
    proxied: false,
));

// Partial update — only the supplied fields are changed
$record = $cf->patchDnsRecord($zoneId, $recordId, new PatchDnsRecordRequest(
    content: '192.0.2.3',
));

Deleting a DNS Record

// Throws RuntimeException on failure; returns void on success
$cf->deleteDnsRecord($zoneId, 'dns-record-id');

Type Reference

Enums

EnumValues
DnsRecordTypeA AAAA CAA CERT CNAME DNSKEY DS HTTPS LOC MX NAPTR NS PTR SMIMEA SOA SRV SSHFP SVCB TLSA TXT URI
ZoneStatusActive Pending Initializing Moved

Request Objects

ClassUsed forRequired fields
ListZonesRequestFiltering listZones()none
ListDnsRecordsRequestFiltering listDnsRecords()none
CreateDnsRecordRequestcreateDnsRecord()type, name, content
UpdateDnsRecordRequestupdateDnsRecord() (full replace)type, name, content
PatchDnsRecordRequestpatchDnsRecord() (partial update)none

Result Objects

ClassReturned by
ZoneResultlistZones(), getZone()
DnsRecordResultlistDnsRecords(), getDnsRecord(), createDnsRecord(), updateDnsRecord(), patchDnsRecord()

Error Handling

All methods throw a RuntimeException when the Cloudflare API returns an error. The message includes the Cloudflare error code and the HTTP status:

[CF 7003] Could not route to /zones. (HTTP 400)

Git Repository

The source code for this driver is available on 1x.ax at https://1x.ax/mamluk/kipchak/drivers/cloudflare-dns.

Previous
Anthropic