System-managed zones, for example,
<network_ID>.compute.internal., are read-only and cannot be modified or deleted.Prerequisites
- Web console
- CLI
- Terraform
- Go SDK
- Python SDK
- JavaScript SDK
Make sure you are in a group that has at least the
editor role within your tenant or project; for example, the default editors group. You can check this in the Administration → IAM section of the web console.- Install and configure the Nebius AI Cloud CLI.
- Make sure you are in a group that has at least the
editorrole within your tenant or project; for example, the defaulteditorsgroup. You can check this in the Administration → IAM section of the web console.
- Install and configure the Nebius AI Cloud provider for Terraform.
- Make sure you are in a group that has at least the
editorrole within your tenant or project; for example, the defaulteditorsgroup. You can check this in the Administration → IAM section of the web console.
- Install and initialize the Nebius SDK for Go.
- Make sure you are in a group that has at least the
editorrole within your tenant or project; for example, the defaulteditorsgroup. You can check this in the Administration → IAM section of the web console.
- Install and initialize the Nebius SDK for Python.
- Make sure you are in a group that has at least the
editorrole within your tenant or project; for example, the defaulteditorsgroup. You can check this in the Administration → IAM section of the web console.
- Install and initialize the Nebius SDK for JavaScript.
- Make sure you are in a group that has at least the
editorrole within your tenant or project; for example, the defaulteditorsgroup. You can check this in the Administration → IAM section of the web console.
Creating DNS zones
- Web console
- CLI
- Terraform
- Go SDK
- Python SDK
- JavaScript SDK
If you want to set a name for the zone or configure the negative caching time-to-live (TTL), use a different interface. The web console doesn’t support these settings.
- In the sidebar, go to
Networking → Virtual Networks.
- Click Actions → Create DNS zone.
- In the window that opens, enter a fully qualified domain name (FQDN) that ends with a dot (
.), for example,my.example.. Single-label names, such asexample., and reserved names, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions. - Select the network to attach the DNS zone to.
- Click Create DNS zone.
Run the following command:In the command, specify the following parameters:The returned resource shows the parameters you specified and the following:
nebius dns zone create \
--domain-name <domain_name> \
--parent-id <project_ID> \
--name <name> \
--labels <key>=<value>,<key2>=<value2> \
--soa-spec-negative-ttl <negative_TTL> \
--vpc-primary-network-id <network_ID>
--domain-name: Domain name for the zone. Use a fully qualified domain name (FQDN) that ends with a dot (.), for example,my.example.. You cannot change the domain name after the zone is created. Top-level domains such asexample.and some names that are reserved for internal use, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions.--parent-id: Project ID.--vpc-primary-network-id: Network ID of the network to attach the zone to. You cannot change the network after the zone is created.--name(optional): Name of the zone.--labels(optional): Labels in thekey=valueformat.--soa-spec-negative-ttl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
metadata:
id: dnszone-e00**
parent_id: project-e00**
resource_version: "144465"
created_at: "2026-06-30T12:50:55.335401Z"
updated_at: "2026-06-30T12:50:55.335401Z"
spec:
domain_name: my.example.
vpc:
primary_network_id: vpcnetwork-e00**
soa_spec:
negative_ttl: "300"
status:
record_count: "2"
resource_versionis the current version of the zone. If you later update or delete the zone, you can pass this value in--resource-versionto make sure that the command applies only to this version of the zone.status.record_countshows how many DNS records the zone currently contains. This value can already be greater than0after creation because the zone includes service-managed records that are automatically created.
-
Create the following configuration file:
In the configuration, specify the following parameters:
resource "nebius_dns_v1_zone" "my_zone" { domain_name = "<domain_name>" parent_id = "<project_ID>" vpc = { primary_network_id = "<network_ID>" } name = "<name>" labels = { <key> = "<value>" } soa_spec = { negative_ttl = <negative_TTL> } }domain_name: Domain name for the zone. Use a fully qualified domain name (FQDN) that ends with a dot (.), for example,my.example.. You cannot change the domain name after the zone is created. Top-level domains such asexample.and some names that are reserved for internal use, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions.parent_id: Project ID.vpc.primary_network_id: Network ID of the network to attach the zone to. You cannot change the network after the zone is created.name(optional): Name of the zone.labels(optional): Labels in thekey = "value"format.soa_spec.negative_ttl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
-
Check that the configuration is correct:
terraform validate -
Apply the changes:
terraform apply
Run the following code:In the code, set the following parameters:
zoneLabels := map[string]string{}
for _, label := range strings.Split("<key>=<value>,<key2>=<value2>", ",") {
key, value, _ := strings.Cut(label, "=")
zoneLabels[key] = value
}
dnsZoneService := sdk.Services().DNS().V1().
Zone()
dnsZoneOperation, err := dnsZoneService.Create(
ctx,
&dns.CreateZoneRequest{
Metadata: &common.ResourceMetadata{
Name: "<name>",
ParentId: "<project_ID>",
Labels: zoneLabels,
},
Spec: &dns.ZoneSpec{
DomainName: "<domain_name>",
Scope: &dns.ZoneSpec_Vpc{
Vpc: &dns.VpcZoneScope{
PrimaryNetworkId: "<network_ID>",
},
},
SoaSpec: &dns.SoaSpec{
NegativeTtl: <negative_TTL>,
},
},
},
)
if err != nil {
return err
}
if _, err = dnsZoneOperation.Wait(ctx); err != nil {
return err
}
fmt.Println(dnsZoneOperation)
Metadata.Name(optional): Name of the zone.Metadata.ParentId: Project ID.Metadata.Labels(optional): Labels. The code builds them from the comma-separatedkey=valuepairs inzoneLabels.Spec.DomainName: Domain name for the zone. Use a fully qualified domain name (FQDN) that ends with a dot (.), for example,my.example.. You cannot change the domain name after the zone is created. Top-level domains such asexample.and some names that are reserved for internal use, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions.PrimaryNetworkIdunderSpec.Scope: Network ID of the network to attach the zone to. You cannot change the network after the zone is created — delete and recreate the zone instead.Spec.SoaSpec.NegativeTtl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
dnsZoneOperation.ResourceID().Run the following code:In the code, set the following parameters:
zone_labels = dict(
label.split("=", 1)
for label in "<key>=<value>,<key2>=<value2>".split(",")
)
dns_zone_service = ZoneServiceClient(sdk)
dns_zone_operation = await dns_zone_service.create(
CreateZoneRequest(
metadata=ResourceMetadata(
name="<name>",
parent_id="<project_ID>",
labels=zone_labels,
),
spec=ZoneSpec(
domain_name="<domain_name>",
vpc=VpcZoneScope(
primary_network_id="<network_ID>",
),
soa_spec=SoaSpec(
negative_ttl=<negative_TTL>,
),
),
),
)
await dns_zone_operation.wait()
print(dns_zone_operation)
name(optional): Name of the zone.parent_id: Project ID.labels(optional): Labels. The code builds them from the comma-separatedkey=valuepairs inzone_labels.domain_name: Domain name for the zone. Use a fully qualified domain name (FQDN) that ends with a dot (.), for example,my.example.. You cannot change the domain name after the zone is created. Top-level domains such asexample.and some names that are reserved for internal use, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions.vpc.primary_network_id: Network ID of the network to attach the zone to. You cannot change the network after the zone is created — delete and recreate the zone instead.soa_spec.negative_ttl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
dns_zone_operation.resource_id.Run the following code:In the code, set the following parameters:
const zoneLabels = Object.fromEntries(
"<key>=<value>,<key2>=<value2>".split(",").map((label) => {
const index = label.indexOf("=");
return [label.slice(0, index), label.slice(index + 1)];
}),
);
const dnsZoneService = new ZoneService(sdk);
const dnsZoneOperation = await dnsZoneService.create(
CreateZoneRequest.create({
metadata: {
name: "<name>",
parentId: "<project_ID>",
labels: zoneLabels,
},
spec: {
domainName: "<domain_name>",
scope: {
"$case": "vpc",
"vpc": {
primaryNetworkId: "<network_ID>",
},
},
soaSpec: {
negativeTtl: <negative_TTL>,
},
},
}),
).result;
await dnsZoneOperation.wait();
console.log(dnsZoneOperation);
metadata.name(optional): Name of the zone.metadata.parentId: Project ID.metadata.labels(optional): Labels. The code builds them from the comma-separatedkey=valuepairs inzoneLabels.spec.domainName: Domain name for the zone. Use a fully qualified domain name (FQDN) that ends with a dot (.), for example,my.example.. You cannot change the domain name after the zone is created. Top-level domains such asexample.and some names that are reserved for internal use, such asconsole.nebius., aren’t allowed. Learn more in Zone domain name restrictions.primaryNetworkIdunderspec.scope: Network ID of the network to attach the zone to. You cannot change the network after the zone is created — delete and recreate the zone instead.spec.soaSpec.negativeTtl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
dnsZoneOperation.resourceId().Updating DNS zones
You cannot update DNS zones in the web console. To update a custom DNS zone, use a different interface.
- CLI
- Terraform
- Go SDK
- Python SDK
- JavaScript SDK
-
Get the ID of the zone that you want to update:
Find the zone that you want to update. The output contains the zone ID in the
nebius dns zone list.metadata.idparameter. -
Run the following command:
Specify the zone ID you got in the previous step as
nebius dns zone update <DNS_zone_ID> \ --name <name> \ --soa-spec-negative-ttl <negative_TTL> \ --resource-version <resource_version> # To replace all labels, add: # --labels <key>=<value>,<key2>=<value2> # # To add or remove specific labels, add: # --labels-add <key>=<value> # --labels-remove <label_key><DNS_zone_ID>. In the command, you can specify the following parameters to update them:--name(optional): Name of the zone.--labels(optional): Replace all labels with the specified labels, in thekey=valueformat.--labels-add(optional): Add labels, in thekey=valueformat, without replacing the existing labels.--labels-remove(optional): Remove existing labels by key.--soa-spec-negative-ttl(optional): How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.--resource-version(optional): Current version of the zone. Use themetadata.resource_versionvalue returned when you create the zone or when you get its ID and details if you want to update only the current version that you last checked. If the zone changed and has a different version, the command fails.
-
In the configuration file, update the
nebius_dns_v1_zoneresource:You can update the following parameters:resource "nebius_dns_v1_zone" "my_zone" { name = "<name>" labels = { <key> = "<value>" } soa_spec = { negative_ttl = <negative_TTL> } # ... }name: Name of the zone.labels: Labels in thekey = "value"format.soa_spec.negative_ttl: How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.
domain_nameorvpc.primary_network_id. You cannot change them in an already existing DNS zone. -
Check that the configuration is correct:
terraform validate -
Apply the changes:
terraform apply
-
Get the ID of the zone that you want to update. List the zones in the project, with
ParentIdset to the project ID:Find the zone that you want to update indnsZonesService := sdk.Services().DNS().V1(). Zone() dnsZonesResponse, err := dnsZonesService.List( ctx, &dns.ListZonesRequest{ ParentId: "<project_ID>", }, ) if err != nil { return err } fmt.Println(dnsZonesResponse)Items. The zone ID is inMetadata.Id. -
Update the zone:
Set
updatedZoneService := sdk.Services().DNS().V1(). Zone() updatedZone, err := updatedZoneService.Get( ctx, &dns.GetZoneRequest{ Id: "<DNS_zone_ID>", }, ) if err != nil { return err } updatedZone.Metadata.Name = "<name>" updatedZone.Metadata.ResourceVersion = <resource_version> updatedZone.Spec.SoaSpec = &dns.SoaSpec{ NegativeTtl: <negative_TTL>, } // Optionally replace, add, or remove labels: // updatedZone.Metadata.Labels = map[string]string{ // "environment": "stage", "team": "docs", // } // updatedZone.Metadata.Labels["owner"] = "platform" // delete(updatedZone.Metadata.Labels, "team") zoneUpdateOperation, err := updatedZoneService.Update( ctx, &dns.UpdateZoneRequest{ Metadata: updatedZone.Metadata, Spec: updatedZone.Spec, }, ) if err != nil { return err } if _, err = zoneUpdateOperation.Wait(ctx); err != nil { return err }Idto the zone ID you got in the previous step. The code gets the zone and updates the following parameters. Remove the lines for the parameters that you don’t want to change:Metadata.Name: Name of the zone.Metadata.ResourceVersion: Version of the zone that you last checked. If the zone changed and has a different version, the update fails.Spec.SoaSpec.NegativeTtl: How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.Metadata.Labels: To replace, add or remove labels, uncomment the corresponding lines in the code.
-
Get the ID of the zone that you want to update. List the zones in the project, with
parent_idset to the project ID:Find the zone that you want to update indns_zones_service = ZoneServiceClient(sdk) dns_zones_response = await dns_zones_service.list( ListZonesRequest( parent_id="<project_ID>", ), ) print(dns_zones_response)items. The zone ID is inmetadata.id. -
Update the zone:
Set
updated_zone_service = ZoneServiceClient(sdk) updated_zone = await updated_zone_service.get( GetZoneRequest( id="<DNS_zone_ID>", ), ) updated_zone.metadata.name = "<name>" updated_zone.metadata.resource_version = <resource_version> updated_zone.spec.soa_spec = SoaSpec( negative_ttl=<negative_TTL>, ) # Optionally replace, add, or remove labels: # updated_zone.metadata.labels = { # "environment": "stage", "team": "docs", # } # updated_zone.metadata.labels["owner"] = "platform" # updated_zone.metadata.labels.pop("team", None) zone_update_operation = await updated_zone_service.update( UpdateZoneRequest( metadata=updated_zone.metadata, spec=updated_zone.spec, ), ) await zone_update_operation.wait()idto the zone ID you got in the previous step. The code gets the zone and updates the following parameters. Remove the lines for the parameters that you don’t want to change:metadata.name: Name of the zone.metadata.resource_version: Version of the zone that you last checked. If the zone changed and has a different version, the update fails.spec.soa_spec.negative_ttl: How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.metadata.labels: To replace, add or remove labels, uncomment the corresponding lines in the code.
-
Get the ID of the zone that you want to update. List the zones in the project, with
parentIdset to the project ID:Find the zone that you want to update inconst dnsZonesService = new ZoneService(sdk); const dnsZonesResponse = await dnsZonesService.list( ListZonesRequest.create({ parentId: "<project_ID>", }), ).result; console.log(dnsZonesResponse);items. The zone ID is inmetadata.id. -
Update the zone:
Set
const updatedZoneService = new ZoneService(sdk); const updatedZone = await updatedZoneService.get( GetZoneRequest.create({ id: "<DNS_zone_ID>", }), ).result; updatedZone.metadata.name = "<name>"; updatedZone.metadata.resourceVersion = <resource_version>; updatedZone.spec.soaSpec = { negativeTtl: <negative_TTL>, }; // Optionally replace, add, or remove labels: // updatedZone.metadata.labels = { // environment: "stage", team: "docs", // }; // updatedZone.metadata.labels.owner = "platform"; // delete updatedZone.metadata.labels.team; const zoneUpdateOperation = await updatedZoneService.update( UpdateZoneRequest.create({ metadata: updatedZone.metadata, spec: updatedZone.spec, }), ).result; await zoneUpdateOperation.wait();idto the zone ID you got in the previous step. The code gets the zone and updates the following parameters. Remove the lines for the parameters that you don’t want to change:metadata.name: Name of the zone.metadata.resourceVersion: Version of the zone that you last checked. If the zone changed and has a different version, the update fails.spec.soaSpec.negativeTtl: How long DNS resolvers can cache a “record not found” response for this zone, in seconds. Values below5are ignored, and the service default of900is used instead.metadata.labels: To replace, add or remove labels, uncomment the corresponding lines in the code.
Deleting DNS zones
You cannot delete system-managed DNS zones. To delete a custom DNS zone, first delete all records except the defaultNS @ and SOA @ records.
- Web console
- CLI
- Terraform
- Go SDK
- Python SDK
- JavaScript SDK
- In the sidebar, go to
Networking → Virtual Networks.
- On the DNS tab, find the zone and click
→ Delete.
- Confirm the deletion.
-
Get the ID of the zone that you want to delete:
Find the zone that you want to delete. The output contains the zone ID in the
nebius dns zone list.metadata.idparameter. -
Run the following command:
In the command, specify the following parameters:
nebius dns zone delete \ --id <DNS_zone_ID> \ --resource-version <resource_version>--id: ID of the DNS zone to delete,<DNS_zone_ID>.--resource-version(optional): Current version of the zone. Use themetadata.resource_versionvalue returned when you create the zone or when you get its ID and details if you want to delete only the current version that you last checked. If the zone changed and has a different version, the command fails. If you omit this parameter or set it to0, the command uses the current version of the zone.
- Remove the corresponding
nebius_dns_v1_zoneresource from the configuration file. - Check that the configuration is correct:
terraform validate - Apply the changes:
terraform apply
-
Get the ID of the zone that you want to delete. List the zones in the project, with
ParentIdset to the project ID:Find the zone that you want to delete indnsZonesService := sdk.Services().DNS().V1(). Zone() dnsZonesResponse, err := dnsZonesService.List( ctx, &dns.ListZonesRequest{ ParentId: "<project_ID>", }, ) if err != nil { return err } fmt.Println(dnsZonesResponse)Items. The zone ID is inMetadata.Id. -
Delete the zone:
In the code, set the following parameters:
deletedZoneService := sdk.Services().DNS().V1(). Zone() deletedZoneOperation, err := deletedZoneService.Delete( ctx, &dns.DeleteZoneRequest{ Id: "<DNS_zone_ID>", ResourceVersion: <resource_version>, }, ) if err != nil { return err } if _, err = deletedZoneOperation.Wait(ctx); err != nil { return err }Id: ID of the DNS zone to delete.ResourceVersion(optional): Version of the zone that you last checked, from itsMetadata.ResourceVersion. If the zone changed and has a different version, the deletion fails. If you set it to0, the deletion uses the current version of the zone.
-
Get the ID of the zone that you want to delete. List the zones in the project, with
parent_idset to the project ID:Find the zone that you want to delete indns_zones_service = ZoneServiceClient(sdk) dns_zones_response = await dns_zones_service.list( ListZonesRequest( parent_id="<project_ID>", ), ) print(dns_zones_response)items. The zone ID is inmetadata.id. -
Delete the zone:
In the code, set the following parameters:
deleted_zone_service = ZoneServiceClient(sdk) deleted_zone_operation = await deleted_zone_service.delete( DeleteZoneRequest( id="<DNS_zone_ID>", resource_version=<resource_version>, ), ) await deleted_zone_operation.wait()id: ID of the DNS zone to delete.resource_version(optional): Version of the zone that you last checked, from itsmetadata.resource_version. If the zone changed and has a different version, the deletion fails. If you set it to0, the deletion uses the current version of the zone.
-
Get the ID of the zone that you want to delete. List the zones in the project, with
parentIdset to the project ID:Find the zone that you want to delete inconst dnsZonesService = new ZoneService(sdk); const dnsZonesResponse = await dnsZonesService.list( ListZonesRequest.create({ parentId: "<project_ID>", }), ).result; console.log(dnsZonesResponse);items. The zone ID is inmetadata.id. -
Delete the zone:
In the code, set the following parameters:
const deletedZoneService = new ZoneService(sdk); const deletedZoneOperation = await deletedZoneService.delete( DeleteZoneRequest.create({ id: "<DNS_zone_ID>", resourceVersion: <resource_version>, }), ).result; await deletedZoneOperation.wait();id: ID of the DNS zone to delete.resourceVersion(optional): Version of the zone that you last checked, from itsmetadata.resourceVersion. If the zone changed and has a different version, the deletion fails. If you set it to0, the deletion uses the current version of the zone.