Prerequisites
- CLI
- Go SDK
- Python SDK
- JavaScript SDK
- Install and configure the Nebius AI Cloud CLI.
-
Install jq to extract IDs and tokens from the JSON data returned by the Nebius AI Cloud CLI:
sudo apt-get install jqbrew install jq -
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.
How to allocate addresses
The CIDR block that you choose must fall within the RFC 1918 private address ranges:10.0.0.0/8, 172.16.0.0/12 or 192.168.0.0/16. The block must not overlap with CIDR blocks already used by other pools or subnets in the network, or with external networks the VM reaches over a Nebius VPN Gateway.
When you choose a custom CIDR block, do not use
172.17.0.0/16. It conflicts with the Docker default bridge network and can make virtual machines unreachable. For more information, see Virtual machine is unreachable due to a Docker subnet conflict.- CLI
- Go SDK
- Python SDK
- JavaScript SDK
-
Determine what CIDR block you need and save it to an environment variable:
export CUSTOM_SUBNET_CIDR=<CIDR_block> -
Get the ID of the required network and save it to an environment variable:
export NETWORK_ID=$(nebius vpc network get-by-name \ --name <network_name> \ --format jsonpath='{.metadata.id}') -
Get the ID of this network’s private pool and save it to an environment variable:
As this command contains
export PRIVATE_POOL_ID=$(nebius vpc network get \ --id $NETWORK_ID \ --format jsonpath='{.spec.ipv4_private_pools.pools[0].id}')pools[0], it saves the ID of the private pool that goes first in the network specification. If you need a different pool, specify its index inpools[<index>]. To check the order of pools, runnebius vpc network list. -
Add the
CUSTOM_SUBNET_CIDRblock to the private pool withPRIVATE_POOL_ID:echo $(nebius vpc pool get --id $PRIVATE_POOL_ID --format json | \ jq '.spec.cidrs += [{"cidr":$ENV.CUSTOM_SUBNET_CIDR}] | {metadata: .metadata, spec: .spec}') | \ nebius vpc pool update - -
Create a new subnet with this private pool and save the subnet ID to an environment variable:
export SUBNET_ID=$(nebius vpc subnet create \ --name private_subnet \ --network-id $NETWORK_ID \ --ipv4-private-pools-pools "[{\"cidrs\":[{\"cidr\":\"$CUSTOM_SUBNET_CIDR\"}]}]" \ --format jsonpath='{.metadata.id}') -
(Optional) To assign the VM a specific IP address, create an allocation within this subnet and save its ID to an environment variable:
The
export ALLOCATION_ID=$(nebius vpc allocation create \ --name private_allocation \ --ipv4-private-subnet-id $SUBNET_ID \ --ipv4-private-cidr <IP_address> \ --format jsonpath='{.metadata.id}')--ipv4-private-cidrparameter sets the IP address for the allocation. Make sure that this address is within the subnet’s CIDR block. Without this parameter, the command creates an allocation with a random IP address from the subnet. -
Create a VM in the new subnet:
The VM is assigned a private IP address from the subnet’s pool. To assign the specific address from the allocation instead, set
nebius compute instance create \ --name <VM_name> \ --stopped=<true|false> \ --resources-platform <platform> \ --resources-preset <preset> \ --boot-disk-existing-disk-id <boot_disk_ID> \ --boot-disk-attach-mode READ_WRITE \ --network-interfaces '[{"name": "<network_interface_name>", "subnet_id": "<subnet_ID>", "ip_address": {}, "public_ip_address": {}}]'ip_addressto{"allocation_id": "$ALLOCATION_ID"}inside the--network-interfacesparameter. If you later delete the VM, you can reuse the allocation for another VM.
-
Determine what CIDR block you need. In the following steps, specify it as
<CIDR_block>. -
Get the ID of the required network:
Set
customNetworkService := sdk.Services().VPC().V1(). Network() customNetwork, err := customNetworkService.GetByName( ctx, &vpc.GetNetworkByNameRequest{ ParentId: "<project_ID>", Name: "<network_name>", }, ) if err != nil { return err } networkID := customNetwork.Metadata.IdParentIdto the project ID andNameto the network name. The code saves the network ID fromMetadata.IdtonetworkID. -
Get the ID of this network’s private pool:
Set
poolNetworkService := sdk.Services().VPC().V1(). Network() poolNetwork, err := poolNetworkService.Get( ctx, &vpc.GetNetworkRequest{ Id: "<network_ID>", }, ) if err != nil { return err } privatePoolID := poolNetwork.Spec.Ipv4PrivatePools.Pools[0].IdIdto the network ID. As the code readsSpec.Ipv4PrivatePools.Pools[0].Id, it saves the ID of the private pool that goes first in the network specification toprivatePoolID. If you need a different pool, specify its index inPools[<index>]. -
Add the CIDR block to the private pool:
Set
customPoolService := sdk.Services().VPC().V1(). Pool() customPool, err := customPoolService.Get( ctx, &vpc.GetPoolRequest{ Id: "<pool_ID>", }, ) if err != nil { return err } customPool.Spec.Cidrs = append( customPool.Spec.Cidrs, &vpc.PoolCidr{Cidr: "<CIDR_block>"}, ) poolUpdateOperation, err := customPoolService.Update( ctx, &vpc.UpdatePoolRequest{ Metadata: customPool.Metadata, Spec: customPool.Spec, }, ) if err != nil { return err } if _, err = poolUpdateOperation.Wait(ctx); err != nil { return err }Idto the private pool ID andCidrto the CIDR block. The code appends the block to the pool’sSpec.Cidrsand updates the pool. -
Create a new subnet with this private pool:
Set
customSubnetService := sdk.Services().VPC().V1(). Subnet() customSubnetOperation, err := customSubnetService.Create( ctx, &vpc.CreateSubnetRequest{ Metadata: &common.ResourceMetadata{ Name: "private_subnet", ParentId: "<project_ID>", }, Spec: &vpc.SubnetSpec{ NetworkId: "<network_ID>", Ipv4PrivatePools: &vpc.IPv4PrivateSubnetPools{ Pools: []*vpc.SubnetPool{ &vpc.SubnetPool{ Cidrs: []*vpc.SubnetCidr{ &vpc.SubnetCidr{ Cidr: "<CIDR_block>", }, }, }, }, }, }, }, ) if err != nil { return err } if _, err = customSubnetOperation.Wait(ctx); err != nil { return err } subnetID := customSubnetOperation.ResourceID()Metadata.ParentIdto the project ID,Spec.NetworkIdto the network ID andCidrunderSpec.Ipv4PrivatePoolsto the CIDR block. The code saves the subnet ID tosubnetID. -
(Optional) To assign the VM a specific IP address, create an allocation within this subnet:
Set
customIpService := sdk.Services().VPC().V1(). Allocation() customIpOperation, err := customIpService.Create( ctx, &vpc.CreateAllocationRequest{ Metadata: &common.ResourceMetadata{ Name: "private_allocation", ParentId: "<project_ID>", }, Spec: &vpc.AllocationSpec{ IpSpec: &vpc.AllocationSpec_Ipv4Private{ Ipv4Private: &vpc.IPv4PrivateAllocationSpec{ Pool: &vpc.IPv4PrivateAllocationSpec_SubnetId{ SubnetId: "<subnet_ID>", }, Cidr: "<IP_address>", }, }, }, }, ) if err != nil { return err } if _, err = customIpOperation.Wait(ctx); err != nil { return err }Metadata.ParentIdto the project ID andSubnetIdto the subnet ID.CidrunderSpec.IpSpecsets the IP address for the allocation. Make sure that this address is within the subnet’s CIDR block. WithoutCidr, the code creates an allocation with a random IP address from the subnet. To get the allocation ID, usecustomIpOperation.ResourceID(). -
Create a VM in the new subnet:
In the code, set the following parameters:
privateInstanceService := sdk.Services().Compute().V1(). Instance() privateInstanceOperation, err := privateInstanceService.Create( ctx, &compute.CreateInstanceRequest{ Metadata: &common.ResourceMetadata{ Name: "<VM_name>", ParentId: "<project_ID>", }, Spec: &compute.InstanceSpec{ Resources: &compute.ResourcesSpec{ Platform: "<platform>", Size: &compute.ResourcesSpec_Preset{ Preset: "<preset>", }, }, BootDisk: &compute.AttachedDiskSpec{ AttachMode: compute.AttachedDiskSpec_READ_WRITE, Type: &compute.AttachedDiskSpec_ExistingDisk{ ExistingDisk: &compute.ExistingDisk{ Id: "<boot_disk_ID>", }, }, }, NetworkInterfaces: []*compute.NetworkInterfaceSpec{ &compute.NetworkInterfaceSpec{ Name: "<network_interface_name>", SubnetId: "<subnet_ID>", IpAddress: &compute.IPAddress{}, PublicIpAddress: &compute.PublicIPAddress{}, }, }, Stopped: <true|false>, }, }, ) if err != nil { return err } if _, err = privateInstanceOperation.Wait(ctx); err != nil { return err } fmt.Println(privateInstanceOperation)Metadata.Name: Name of the VM.Metadata.ParentId: ID of the project.Spec.Resources.PlatformandPresetunderSpec.Resources.Size: VM platform and preset.IdunderSpec.BootDisk: ID of the boot disk.NameunderSpec.NetworkInterfaces: Name of the network interface.SubnetId: ID of the new subnet.Spec.Stopped: Whether to create the VM in the stopped state,trueorfalse.
IpAddressto&compute.IPAddress{AllocationId: "<allocation_ID>"}. If you later delete the VM, you can reuse the allocation for another VM.
-
Determine what CIDR block you need. In the following steps, specify it as
<CIDR_block>. -
Get the ID of the required network:
Set
custom_network_service = NetworkServiceClient(sdk) custom_network = await custom_network_service.get_by_name( GetNetworkByNameRequest( parent_id="<project_ID>", name="<network_name>", ), ) network_id = custom_network.metadata.idparent_idto the project ID andnameto the network name. The code saves the network ID frommetadata.idtonetwork_id. -
Get the ID of this network’s private pool:
Set
pool_network_service = NetworkServiceClient(sdk) pool_network = await pool_network_service.get( GetNetworkRequest( id="<network_ID>", ), ) private_pool_id = pool_network.spec.ipv4_private_pools.pools[0].ididto the network ID. As the code readsspec.ipv4_private_pools.pools[0].id, it saves the ID of the private pool that goes first in the network specification toprivate_pool_id. If you need a different pool, specify its index inpools[<index>]. -
Add the CIDR block to the private pool:
Set
custom_pool_service = PoolServiceClient(sdk) custom_pool = await custom_pool_service.get( GetPoolRequest( id="<pool_ID>", ), ) custom_pool.spec.cidrs.append( PoolCidr(cidr="<CIDR_block>"), ) pool_update_operation = await custom_pool_service.update( UpdatePoolRequest( metadata=custom_pool.metadata, spec=custom_pool.spec, ), ) await pool_update_operation.wait()idto the private pool ID andcidrto the CIDR block. The code appends the block to the pool’sspec.cidrsand updates the pool. -
Create a new subnet with this private pool:
Set
custom_subnet_service = SubnetServiceClient(sdk) custom_subnet_operation = await custom_subnet_service.create( CreateSubnetRequest( metadata=ResourceMetadata( name="private_subnet", parent_id="<project_ID>", ), spec=SubnetSpec( network_id="<network_ID>", ipv4_private_pools=IPv4PrivateSubnetPools( pools=[ SubnetPool( cidrs=[ SubnetCidr( cidr="<CIDR_block>", ), ], ), ], ), ), ), ) await custom_subnet_operation.wait() subnet_id = custom_subnet_operation.resource_idparent_idto the project ID,network_idto the network ID andcidrunderipv4_private_poolsto the CIDR block. The code saves the subnet ID tosubnet_id. -
(Optional) To assign the VM a specific IP address, create an allocation within this subnet:
Set
custom_ip_service = AllocationServiceClient(sdk) custom_ip_operation = await custom_ip_service.create( CreateAllocationRequest( metadata=ResourceMetadata( name="private_allocation", parent_id="<project_ID>", ), spec=AllocationSpec( ipv4_private=IPv4PrivateAllocationSpec( subnet_id="<subnet_ID>", cidr="<IP_address>", ), ), ), ) await custom_ip_operation.wait()parent_idto the project ID andsubnet_idto the subnet ID.cidrunderipv4_privatesets the IP address for the allocation. Make sure that this address is within the subnet’s CIDR block. Withoutcidr, the code creates an allocation with a random IP address from the subnet. To get the allocation ID, usecustom_ip_operation.resource_id. -
Create a VM in the new subnet:
In the code, set the following parameters:
private_instance_service = InstanceServiceClient(sdk) private_instance_operation = await private_instance_service.create( CreateInstanceRequest( metadata=ResourceMetadata( name="<VM_name>", parent_id="<project_ID>", ), spec=InstanceSpec( resources=ResourcesSpec( platform="<platform>", preset="<preset>", ), boot_disk=AttachedDiskSpec( attach_mode=AttachedDiskSpec.AttachMode.READ_WRITE, existing_disk=ExistingDisk( id="<boot_disk_ID>", ), ), network_interfaces=[ NetworkInterfaceSpec( name="<network_interface_name>", subnet_id="<subnet_ID>", ip_address=IPAddress(), public_ip_address=PublicIPAddress(), ), ], stopped=<True|False>, ), ), ) await private_instance_operation.wait() print(private_instance_operation)metadata.name: Name of the VM.metadata.parent_id: ID of the project.resources.platformandresources.preset: VM platform and preset.existing_disk.id: ID of the boot disk.nameundernetwork_interfaces: Name of the network interface.subnet_id: ID of the new subnet.stopped: Whether to create the VM in the stopped state,TrueorFalse.
ip_addresstoIPAddress(allocation_id="<allocation_ID>"). If you later delete the VM, you can reuse the allocation for another VM.
-
Determine what CIDR block you need. In the following steps, specify it as
<CIDR_block>. -
Get the ID of the required network:
Set
const customNetworkService = new NetworkService(sdk); const customNetwork = await customNetworkService.getByName( GetNetworkByNameRequest.create({ parentId: "<project_ID>", name: "<network_name>", }), ).result; const networkId = customNetwork.metadata.id;parentIdto the project ID andnameto the network name. The code saves the network ID frommetadata.idtonetworkId. -
Get the ID of this network’s private pool:
Set
const poolNetworkService = new NetworkService(sdk); const poolNetwork = await poolNetworkService.get( GetNetworkRequest.create({ id: "<network_ID>", }), ).result; const privatePoolId = poolNetwork.spec.ipv4PrivatePools.pools[0].id;idto the network ID. As the code readsspec.ipv4PrivatePools.pools[0].id, it saves the ID of the private pool that goes first in the network specification toprivatePoolId. If you need a different pool, specify its index inpools[<index>]. -
Add the CIDR block to the private pool:
Set
const customPoolService = new PoolService(sdk); const customPool = await customPoolService.get( GetPoolRequest.create({ id: "<pool_ID>", }), ).result; customPool.spec.cidrs.push( PoolCidr.create({ cidr: "<CIDR_block>" }), ); const poolUpdateOperation = await customPoolService.update( UpdatePoolRequest.create({ metadata: customPool.metadata, spec: customPool.spec, }), ).result; await poolUpdateOperation.wait();idto the private pool ID andcidrto the CIDR block. The code appends the block to the pool’sspec.cidrsand updates the pool. -
Create a new subnet with this private pool:
Set
const customSubnetService = new SubnetService(sdk); const customSubnetOperation = await customSubnetService.create( CreateSubnetRequest.create({ metadata: { name: "private_subnet", parentId: "<project_ID>", }, spec: { networkId: "<network_ID>", ipv4PrivatePools: { pools: [ { cidrs: [ { cidr: "<CIDR_block>", }, ], }, ], }, }, }), ).result; await customSubnetOperation.wait(); const subnetId = customSubnetOperation.resourceId();parentIdto the project ID,networkIdto the network ID andcidrunderipv4PrivatePoolsto the CIDR block. The code saves the subnet ID tosubnetId. -
(Optional) To assign the VM a specific IP address, create an allocation within this subnet:
Set
const customIpService = new AllocationService(sdk); const customIpOperation = await customIpService.create( CreateAllocationRequest.create({ metadata: { name: "private_allocation", parentId: "<project_ID>", }, spec: { ipSpec: { "$case": "ipv4Private", "ipv4Private": { pool: { "$case": "subnetId", "subnetId": "<subnet_ID>", }, cidr: "<IP_address>", }, }, }, }), ).result; await customIpOperation.wait();parentIdto the project ID andsubnetIdto the subnet ID.cidrunderipv4Privatesets the IP address for the allocation. Make sure that this address is within the subnet’s CIDR block. Withoutcidr, the code creates an allocation with a random IP address from the subnet. To get the allocation ID, usecustomIpOperation.resourceId(). -
Create a VM in the new subnet:
In the code, set the following parameters:
const privateInstanceService = new InstanceService(sdk); const privateInstanceOperation = await privateInstanceService.create( CreateInstanceRequest.create({ metadata: { name: "<VM_name>", parentId: "<project_ID>", }, spec: { resources: { platform: "<platform>", size: { "$case": "preset", "preset": "<preset>", }, }, bootDisk: { attachMode: AttachedDiskSpec_AttachMode.READ_WRITE, type: { "$case": "existingDisk", "existingDisk": { id: "<boot_disk_ID>", }, }, }, networkInterfaces: [ { name: "<network_interface_name>", subnetId: "<subnet_ID>", ipAddress: {}, publicIpAddress: {}, }, ], stopped: <true|false>, }, }), ).result; await privateInstanceOperation.wait(); console.log(privateInstanceOperation);metadata.name: Name of the VM.metadata.parentId: ID of the project.resources.platformandpresetunderresources.size: VM platform and preset.existingDisk.id: ID of the boot disk.nameundernetworkInterfaces: Name of the network interface.subnetId: ID of the new subnet.stopped: Whether to create the VM in the stopped state,trueorfalse.
ipAddressto{ allocationId: "<allocation_ID>" }. If you later delete the VM, you can reuse the allocation for another VM.