Skip to main content

Manage DNS records

Create and manage DNS records in the CDB Technical Web Portal.

Non-advanced interface mode. Verify that the Advanced toggle is off:

Zone header with Interface mode toggle in off position

Balancing and dynamic response are available in advanced mode.

Create a DNS record

  1. Navigate to All zones and select the domain zone to which records should be added. Or, click the three-dot icon on the right and then click Go to records.
DNS zone records list with Add record, Export records, and Import records buttons
  1. Click Add record. The form opens in the records list.
Add record form with Type, Name, TTL, and Content fields
  1. In the Type field, select a record type — A, AAAA, NS, CNAME, MX, SRV, HTTPS, TXT, CAA, or SVCB.

  2. In the Name field, specify the subdomain to which the record belongs:

  • Leave the field blank to add a record for the main domain (apex/naked domain).
  • Enter the subdomain name — one creates a record for one.yourdomain.com.
  • Enter an asterisk (*) to add a wildcard record for all subdomains at once.
  1. In the TTL field, specify the time to live in seconds. This determines how long recursive DNS servers cache the record. With a TTL of 300 seconds, a change to an A record value from 1.2.3.4 to 5.6.7.8 takes up to 5 minutes to propagate — resolvers return the old value until the cache expires.

  2. In the Content field, enter the value for the selected record type.

  3. Click Add.

Verify the record with the CDB DNS Lookup tool.

Record values

Manage a DNS record

  1. Navigate to All zones and select the domain zone to manage. Or, click the three-dot icon on the right and click Go to records.
DNS zone records list with Add record, Export records, and Import records buttons
  1. Click the pencil icon next to the record to expand the edit panel.

To update the record, change the TTL, value, or both, then click Save.

To delete the record, click Delete record in the expanded panel, then click Yes, delete in the confirmation dialog.

Edit record panel with TTL and content fields, Save and Delete record buttons

Create, update, and delete DNS records in a zone using the RRset API. The API manages records as RRsets identified by record name and type. An RRset can contain multiple values, such as two IP addresses for the same A record.

An API token is required.

Export these variables:

export GCORE_API_KEY="{YOUR_API_KEY}"
export ZONE_NAME="{YOUR_ZONE_NAME}"
export RECORD_NAME="{RECORD_FQDN}"
export RECORD_TYPE="{A|AAAA|CNAME|MX|TXT|...}"

RECORD_NAME is the fully qualified domain name (FQDN) of the record. For an apex record it equals ZONE_NAME; for a subdomain it is the full FQDN — www.yourdomain.com.

Create a record

Creates an A record with a TTL of 300 seconds. To assign multiple IP addresses to the same name, add one object to resource_records per address.

import os
from gcore import CDB

client = CDB()

record = client.dns.zones.rrsets.create(
    os.environ["RECORD_TYPE"],
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    resource_records=[{"content": ["1.2.3.4"]}],
    ttl=300,
)
print(record.name, record.type, record.ttl)
for rr in record.resource_records:
    print(rr.content)
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    record, err := client.DNS.Zones.Rrsets.New(ctx, os.Getenv("RECORD_TYPE"),
        dns.ZoneRrsetNewParams{
            ZoneName:  os.Getenv("ZONE_NAME"),
            RrsetName: os.Getenv("RECORD_NAME"),
            ResourceRecords: []dns.ZoneRrsetNewParamsResourceRecord{
                {Content: []any{"1.2.3.4"}},
            },
            Ttl: gcore.Int(300),
        })
    if err != nil {
        panic(err)
    }
    fmt.Println(record.Name, record.Type, record.Ttl)
    for _, rr := range record.ResourceRecords {
        fmt.Println(rr.Content)
    }
}
curl -s -X POST "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/${ZONE_NAME}/${RECORD_NAME}/${RECORD_TYPE}" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttl": 300, "resource_records": [{"content": ["1.2.3.4"]}]}'

The API returns:

{
  "name": "example.com",
  "type": "A",
  "ttl": 300,
  "resource_records": [
    {"content": ["1.2.3.4"], "enabled": true, "meta": {}}
  ]
}

List records

List the RRsets in a zone to inspect their names, types, TTLs, and current values. The response also includes system records such as NS.

import os
from gcore import CDB

client = CDB()

page = client.dns.zones.rrsets.list(os.environ["ZONE_NAME"])
print(page.total_amount)
for r in page:
    print(r.name, r.type, r.ttl)
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    page, err := client.DNS.Zones.Rrsets.List(ctx, os.Getenv("ZONE_NAME"),
        dns.ZoneRrsetListParams{})
    if err != nil {
        panic(err)
    }
    fmt.Println(page.TotalAmount)
    for _, r := range page.Rrsets {
        fmt.Println(r.Name, r.Type, r.Ttl)
    }
}
curl -s "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/${ZONE_NAME}/rrsets" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns:

{
  "rrsets": [
    {
      "name": "example.com",
      "type": "A",
      "ttl": 300,
      "resource_records": [{"content": ["1.2.3.4"], "enabled": true}]
    },
    {
      "name": "example.com",
      "type": "NS",
      "ttl": 3600,
      "resource_records": [
        {"content": ["ns1.gcorelabs.net"], "enabled": true},
        {"content": ["ns2.gcdn.services"], "enabled": true}
      ]
    }
  ],
  "total_amount": 2
}

Update a record

PUT replaces the full RRset — all previous values are overwritten. Send every IP or value the record should have after the update.

import os
from gcore import CDB

client = CDB()

record = client.dns.zones.rrsets.replace(
    os.environ["RECORD_TYPE"],
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    resource_records=[{"content": ["5.6.7.8"]}],
    ttl=600,
)
print(record.ttl)
for rr in record.resource_records:
    print(rr.content)
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    record, err := client.DNS.Zones.Rrsets.Replace(ctx, os.Getenv("RECORD_TYPE"),
        dns.ZoneRrsetReplaceParams{
            ZoneName:  os.Getenv("ZONE_NAME"),
            RrsetName: os.Getenv("RECORD_NAME"),
            ResourceRecords: []dns.ZoneRrsetReplaceParamsResourceRecord{
                {Content: []any{"5.6.7.8"}},
            },
            Ttl: gcore.Int(600),
        })
    if err != nil {
        panic(err)
    }
    fmt.Println(record.Ttl)
    for _, rr := range record.ResourceRecords {
        fmt.Println(rr.Content)
    }
}
curl -s -X PUT "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/${ZONE_NAME}/${RECORD_NAME}/${RECORD_TYPE}" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resource_records": [{"content": ["5.6.7.8"]}], "ttl": 600}'

The API returns:

{
  "name": "example.com",
  "type": "A",
  "ttl": 600,
  "resource_records": [
    {"content": ["5.6.7.8"], "enabled": true, "meta": {}}
  ]
}

Delete a record

Delete the RRset identified by RECORD_NAME and RECORD_TYPE.

import os
from gcore import CDB

client = CDB()

client.dns.zones.rrsets.delete(
    os.environ["RECORD_TYPE"],
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
)
package main

import (
    "context"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    _, err := client.DNS.Zones.Rrsets.Delete(ctx, os.Getenv("RECORD_TYPE"),
        dns.ZoneRrsetDeleteParams{
            ZoneName:  os.Getenv("ZONE_NAME"),
            RrsetName: os.Getenv("RECORD_NAME"),
        })
    if err != nil {
        panic(err)
    }
}
curl -s -X DELETE "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/${ZONE_NAME}/${RECORD_NAME}/${RECORD_TYPE}" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns an empty response body:

{}

Manage DNS records as code using the gcore_dns_zone_rrset resource from the CDB Terraform provider v2. Each gcore_dns_zone_rrset block declares one RRset — a record name, type, TTL, and one or more values.

Create a DNS record

Declare the zone and the RRset in the same configuration. Set rrset_name to the zone name for an apex record, or to the full FQDN for a subdomain.

resource "gcore_dns_zone" "example" {
  name = "example.com"
}

resource "gcore_dns_zone_rrset" "a" {
  zone_name  = gcore_dns_zone.example.name
  rrset_name = gcore_dns_zone.example.name  # apex record
  rrset_type = "A"
  ttl        = 300

  resource_records = [
    { content = ["203.0.113.1"] },
    { content = ["203.0.113.2"] },
  ]
  # terraform import gcore_dns_zone_rrset.a example.com/example.com/A
}

Each resource_records entry is one value. The content field is a list of strings whose length and meaning depends on the record type.

Record type reference

The table below shows the content format for each record type. One resource_records entry maps to one value in the RRset.

Record typecontent formatSample value
A["ipv4"]["203.0.113.1"]
AAAA["ipv6"]["2001:db8::1"]
CNAME["target."] (trailing dot required)["origin.yourdomain.com."]
MX["priority", "hostname."]["10", "mail.yourdomain.com."]
TXT["text"]["v=spf1 mx -all"]
CAA["flags", "tag", "value"]["0", "issue", "letsencrypt.org"]
SRV["priority", "weight", "port", "target."]["10", "20", "5060", "sip.yourdomain.com."]

Update a record

Edit fields in the resource block and run terraform apply to replace the RRset in-place. PUT semantics apply — all resource_records values must be present after the update.

resource "gcore_dns_zone_rrset" "a" {
  zone_name  = gcore_dns_zone.example.name
  rrset_name = gcore_dns_zone.example.name
  rrset_type = "A"
  ttl        = 600  # changed

  resource_records = [
    { content = ["203.0.113.1"] },
    { content = ["203.0.113.2"] },
    { content = ["203.0.113.3"] },  # added
  ]
}

Delete a record

Remove the resource block — Terraform detects the missing declaration and deletes the RRset on the next terraform apply.

# Remove or comment out this block:
# resource "gcore_dns_zone_rrset" "a" {
#   zone_name  = gcore_dns_zone.example.name
#   rrset_name = gcore_dns_zone.example.name
#   rrset_type = "A"
#   ...
# }
terraform apply

Import an existing record

Use when a record was created outside Terraform and needs to be managed as code. Add the resource block to main.tf, then run:

terraform import gcore_dns_zone_rrset.a example.com/example.com/A

The import ID format is zone_name/rrset_name/TYPE.