Skip to main content

Configure HTTPS records

Managed DNS supports HTTPS records — a specialized form of the Service Binding (SVCB) DNS record standardized by the IETF. HTTPS records consolidate connection parameters into a single DNS response, reducing the round trips required to establish a secure connection and enabling future protocol upgrades without client-side changes.

HTTPS connection overhead

A and AAAA records provide the server IP address but do not describe other connection parameters — supported application protocols, ports, or alternate endpoints. Clients may therefore need to discover this information separately during connection establishment — often via a subsequent DNS query or an Alt-Svc header returned only after the first response. Sites that still redirect HTTP to HTTPS add an extra round trip before any of this begins.

HTTPS records deliver these parameters — ALPN identifiers, IP hints, and port information — as part of the original DNS response, allowing compatible clients to begin the connection with more information already available.

HTTPS record structure

An HTTPS record for sample-test.com looks like this:

www.sample-test.com. 1800 IN HTTPS 1 . alpn=h3,h3-29,h2 ipv4hint=1.2.3.4,9.8.7.6 ipv6hint=2001:db8:3333:4444:5555:6666:7777:8888,2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF

Each element represents:

  • www.sample-test.com — the domain name
  • 1800 — Time To Live (TTL)
  • IN — the record class
  • HTTPS — the record type
  • 1 — the priority (selection preference when multiple HTTPS records exist for the same name)
  • . — the target host when it is the same as the domain name
  • alpn=h3,h3-29,h2 — the application protocol versions
  • ipv4hint=1.2.3.4,9.8.7.6 — IPv4 addresses (optional)
  • ipv6hint=2001:db8:3333:4444:5555:6666:7777:8888,2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF — IPv6 addresses (optional)

When a browser requests the HTTPS record, it receives all parameters needed to connect to https://sample-test.com in a single response:

  • The exact protocol configuration and server preferences for the domain.
  • IP addresses of web servers — potentially from multiple CDNs or providers — which also resolves the limitations of records at the domain apex.

Combining all parameters into a single lookup response reduces the additional round trips needed before a connection can begin.

Configure HTTPS records

To add an HTTPS record to a zone, navigate to the zone in the Customer Portal and fill in the record form.

  1. 1

    Open the zone records

    In the CDB Technical Web Portal, navigate to DNS → All zones and click the zone name.

    DNS zones list
  2. 2

    Open the Add record form

    Click Add record.

    Zone records list with the Add record button
  3. 3

    Configure the HTTPS record

    Fill in the form:

    1. Type: Select HTTPS.
    2. (Optional) Name: Leave empty to create a record for the zone apex. To target a specific subdomain, enter the prefix — www for www.sample-test.com.
    3. (Optional) TTL: Leave empty or enter a value in seconds. For production, 1800 or higher allows recursive resolvers to cache the record effectively.
    4. Priority: Enter a number. Use incrementing values when multiple HTTPS records exist for the same name.
    5. TargetName: Enter a valid domain name or leave it as ..
    6. In the Key dropdown, select alpn, then enter the supported protocol identifiers as a comma-separated list: h3, h2, http/1.1, or h3-29.
    7. (Optional) Add an ipv4hint or ipv6hint key and enter the corresponding server IP addresses.
    HTTPS record form with alpn attribute configured
    1. Click Add.

The record now appears in the zone records list:

Zone records list showing the new HTTPS record

Verify the record using kdig (the Knot DNS variant of dig). When using standard dig, confirm the version is current — older versions don't support HTTPS record types. The DNS Lookup tool also resolves HTTPS records.

kdig https sample-test.com @ns1.gcorelabs.net

;; ->>HEADER<<\- opcode: QUERY; status: NOERROR; id: 34710
;; Flags: qr aa rd; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;;sample-test.com. IN HTTPS

;; ANSWER SECTION:
sample-test.com. 1800 IN HTTPS 1 . alpn=h3,h2,http/1.1 ipv4hint=1.2.3.4,9.8.7.6 ipv6hint=2001:db8:3333:4444:5555:6666:7777:8888,2001:db8:3333:4444:cccc:dddd:eeee:ffff

The DNS API creates an HTTPS RRset with a single POST request. The record content is an ordered array: priority, target name, then one sub-array per SvcParam key — alpn, ipv4hint, ipv6hint, port, or ech.

An API token is required.

Open a terminal and export the required variables:

export GCORE_API_KEY="{YOUR_API_KEY}"
export ZONE_NAME="{YOUR_ZONE_NAME}"      # e.g. example.com
export RECORD_NAME="{YOUR_RECORD_NAME}"  # e.g. www.example.com

Create an HTTPS record

The content array encodes the full HTTPS record:

  • First element: priority (1 = highest preference)
  • Second element: target ("." = same domain)
  • Subsequent elements: SvcParam arrays — ["alpn", "h3", "h2"], ["ipv4hint", "1.2.3.4"]

To add IPv6 hints, include ["ipv6hint", "2001:db8::1"] in the same content array.

import os
from gcore import CDB

client = CDB()

rrset = client.dns.zones.rrsets.create(
    "HTTPS",
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    ttl=1800,
    resource_records=[&#123;
        "content": [
            1,
            ".",
            ["alpn", "h3", "h2"],
            ["ipv4hint", "1.2.3.4", "9.8.7.6"],
        ]
    &#125;],
)
print(rrset.name, rrset.type, (rrset.resource_records or [{}])[0].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()

    rrset, err := client.DNS.Zones.Rrsets.New(ctx, "HTTPS", dns.ZoneRrsetNewParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
        Ttl:       gcore.Int(1800),
        ResourceRecords: []dns.ZoneRrsetNewParamsResourceRecord{
            {
                Content: []any{
                    1,
                    ".",
                    []any{"alpn", "h3", "h2"},
                    []any{"ipv4hint", "1.2.3.4", "9.8.7.6"},
                },
            },
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s %s content:%v\n", rrset.Name, rrset.Type, rrset.ResourceRecords[0].Content)
}
curl -X POST "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/HTTPS" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ttl": 1800,
    "resource_records": [&#123;
      "content": [1, ".", ["alpn", "h3", "h2"], ["ipv4hint", "1.2.3.4", "9.8.7.6"]]
    &#125;]
  }'

The API returns:

{
  "name": "www.example.com",
  "type": "HTTPS",
  "ttl": 1800,
  "resource_records": [
    {
      "id": 1001,
      "content": [1, ".", ["alpn", "h3", "h2"], ["ipv4hint", "1.2.3.4", "9.8.7.6"]],
      "enabled": true,
      "meta": {}
    }
  ]
}

Check the stored configuration

Retrieve the RRset to confirm that its content was saved correctly.

import os
from gcore import CDB

client = CDB()

rrset = client.dns.zones.rrsets.get(
    "HTTPS",
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
)
print(rrset.name, rrset.type, "ttl:", rrset.ttl)
for rr in rrset.resource_records or []:
    print("content:", 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()

    rrset, err := client.DNS.Zones.Rrsets.Get(ctx, "HTTPS", dns.ZoneRrsetGetParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s %s ttl:%d\n", rrset.Name, rrset.Type, rrset.Ttl)
    for _, rr := range rrset.ResourceRecords {
        fmt.Println("content:", rr.Content)
    }
}
curl "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/HTTPS" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns the full RRset with the same structure as the create response.

Query the record through DNS using kdig, or resolve it with the DNS Lookup tool.

Create HTTPS records using gcore_dns_zone_rrset from the CDB Terraform provider v2. The content field is a list of strings — SvcParam entries (alpn, ipv4hint, ipv6hint, port) must be JSON-encoded because they are arrays internally. Wire-format strings like "alpn=h3,h2" are rejected by the API.

Create an HTTPS record

Each content element maps to one field in the HTTPS record wire format: priority, target, then SvcParams. Encode each SvcParam array with jsonencode().

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

resource "gcore_dns_zone_rrset" "https_www" {
  zone_name  = gcore_dns_zone.example.name
  rrset_name = "www.${gcore_dns_zone.example.name}"
  rrset_type = "HTTPS"
  ttl        = 1800

  resource_records = [
    {
      content = [
        "1",                                                       # priority
        ".",                                                       # target (. = same domain)
        jsonencode(["alpn", "h3", "h2", "http/1.1"]),             # supported protocols
        jsonencode(["ipv4hint", "1.2.3.4", "9.8.7.6"]),           # IPv4 address hints
        jsonencode(["ipv6hint", "2001:db8::1", "2001:db8::2"]),   # IPv6 address hints (optional)
      ]
    },
  ]
  # terraform import gcore_dns_zone_rrset.https_www yourdomain.com/www.yourdomain.com/HTTPS
}

To create the record at the zone apex, set rrset_name = gcore_dns_zone.example.name. HTTPS records at the apex coexist with NS and SOA records without conflict.

Update an HTTPS record

Edit content — add or remove SvcParam entries, change protocol list, update IP hints — and run terraform apply. Terraform updates the record in place.

resource "gcore_dns_zone_rrset" "https_www" {
  zone_name  = gcore_dns_zone.example.name
  rrset_name = "www.${gcore_dns_zone.example.name}"
  rrset_type = "HTTPS"
  ttl        = 1800

  resource_records = [
    {
      content = [
        "1",
        ".",
        jsonencode(["alpn", "h3", "h2"]),       # removed http/1.1
        jsonencode(["ipv4hint", "203.0.113.1"]), # updated IP
      ]
    },
  ]
}

Delete an HTTPS record

Remove the resource block — Terraform deletes the RRset on the next terraform apply.

# Remove or comment out this block:
# resource "gcore_dns_zone_rrset" "https_www" { ... }
terraform apply