Yandex Cloud
Search
Contact UsGet started
  • Blog
  • Pricing
  • Documentation
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • ML & AI
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Customer Stories
    • Gateway to Russia
    • Cloud for Startups
    • Education and Science
  • Blog
  • Pricing
  • Documentation
Yandex project
© 2025 Yandex.Cloud LLC
Yandex Compute Cloud
    • All guides
      • Configuring metadata service parameters
      • Getting VM instance metadata
      • Getting a VM instance identity document
      • Changing VM instance metadata
      • Creating a VM with a custom configuration script
      • Creating a VM with metadata from environment variables
      • Creating a VM instance with access to a Yandex Lockbox secret
    • Viewing operations with resources
  • Yandex Container Solution
  • Access management
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Release notes

In this article:

  • Creating a VM with a custom configuration script
  • Examples
  1. Step-by-step guides
  2. Creating a VM
  3. Creating a VM with a custom configuration script

Creating a VM with a custom configuration script

Written by
Yandex Cloud
Improved by
Danila N.
Updated at May 5, 2025
  • Creating a VM with a custom configuration script
  • Examples

You can create a VM with a preset software configuration by using the user-data key in the VM metadata.

The cloud-init agent running on the VM will process the configuration you set in the user-data key. Cloud-init supports different metadata transmission formats, e.g., cloud-config.

Creating a VM with a custom configuration scriptCreating a VM with a custom configuration script

Warning

In the user-data configuration, you must always set the user login and SSH key, even if you have already specified them under Access in the management console.

To create a VM with a custom configuration script:

Management console
CLI
Terraform
API
  1. In the management console, select the folder where you want to create your VM.

  2. Select Compute Cloud from the list of services.

  3. In the left-hand panel, select Virtual machines.

  4. Click Create virtual machine.

  5. Set the required VM parameters.

  6. Expand the Metadata section and specify:

    • Key: user-data.
    • Value: cloud-config configuration in YAML format. See configuration examples for user-data under Examples.
  7. Click Create VM.

If you do not have the Yandex Cloud CLI yet, install and initialize it.

The folder specified when creating the CLI profile is used by default. To change the default folder, use the yc config set folder-id <folder_ID> command. You can specify a different folder using the --folder-name or --folder-id parameter.

Run this command:

yc compute instance create \
  --name my-sample-instance \
  --zone ru-central1-a \
  --network-interface subnet-name=<subnet_name>,nat-ip-version=ipv4,security-group-ids=<security_group_ID> \
  --create-boot-disk image-folder-id=standard-images,image-family=ubuntu-2204-lts,kms-key-id=<key_ID> \
  --metadata-from-file user-data="<path_to_configuration_file>"

Where:

  • --name: VM name. The naming requirements are as follows:

    • It must be from 2 to 63 characters long.
    • It may contain lowercase Latin letters, numbers, and hyphens.
    • It must start with a letter and cannot end with a hyphen.

    Note

    The VM name is used to generate an internal FQDN, which is set only once, when you create the VM. If the internal FQDN is important to you, make sure to choose an appropriate name for your VM.

  • --zone: Availability zone matching the selected subnet.

  • --network-interface: VM network interface settings:

    • subnet-name: Name of the subnet in the availability zone specified in the --zone parameter.
    • security-group-ids: Security group ID.
  • --create-boot-disk: VM boot disk settings:

    • image-family: Image family, e.g., ubuntu-2204-lts. This option allows you to install the latest version of the OS from the specified family.

    • kms-key-id: ID of the KMS symmetric key to create an encrypted boot disk. This is an optional parameter.

      To create an encrypted disk, you need the kms.keys.user role or higher.

      Warning

      You can specify encryption settings only when creating a disk. You cannot disable or change disk encryption. You also cannot enable encryption for an existing disk.

      If you deactivate the key used to encrypt a disk, image, or snapshot, access to the data will be suspended until you reactivate the key.

      Alert

      If you destroy the key or its version used to encrypt a disk, image, or snapshot, access to the data will be irrevocably lost. For details, see Destroying key versions.

  • --metadata-from-file: user-data key and its value, i.e., path to the cloud-config configuration file in YAML format, e.g., --metadata-from-file user-data="/home/user/metadata.yaml".

    See configuration examples for user-data under Examples.

Note

The commands yc compute instance create | create-with-container | update | add-metadata support substitution of environment variable values into VM metadata. When you execute a Yandex Cloud CLI command, these values, specified in the user-data key in $<variable_name> format, will be substituted into the VM metadata from the environment variables of the environment the command is executed in.

To change such behavior, i.e. to provide a variable name to the VM metadata in $<variable_name> format rather than take the variable value from the CLI command runtime environment, use the two-dollar syntax, e.g., $$<variable_name>.

For more information, see Specifics of providing environment variables in metadata via the CLI.

If you do not have Terraform yet, install it and configure its Yandex Cloud provider.

Add the VM configuration script to the metadata section of the yandex_compute_instance resource in the Terraform configuration file:

resource "yandex_compute_instance" "vm-1" {
  name        = "my-sample-instance"
  ...
  metadata    = {
    user-data = "${file("<path_to_configuration_file>")}"
  }
  ...
}

Where:

  • user-data: Path to the cloud-config configuration file in YAML format, e.g., user-data = "${file("/home/user/metadata.yaml")}".

    See configuration examples for user-data under Examples.

To create a VM, use the create REST API method for the Instance resource and provide the object with the cloud-config YAML configuration under metadata in the request body. For a multiline configuration, use \n as a separator. Here is an example:

{
  "folderId": "b1gvmob95yys********",
  "name": "my-sample-instance",
  "zoneId": "ru-central1-a",
  "platformId": "standard-v3",
  ...
  "metadata": {
    "user-data": "#cloud-config\ndatasource:\n  Ec2:\n    strict_id: false\nssh_pwauth: yes\nusers:\n- name: <username>\n  sudo: 'ALL=(ALL) NOPASSWD:ALL'\n  shell: /bin/bash\n  ssh_authorized_keys:\n  - <public_SSH_key>\nwrite_files:\n  - path: '/usr/local/etc/startup.sh'\n    permissions: '755'\n    content: |\n      #!/bin/bash\n      apt-get update\n      apt-get install -y nginx\n      service nginx start\n      sed -i -- 's/ nginx/ Yandex Cloud - ${HOSTNAME}/' /var/www/html/index.nginx-debian.html\n    defer: true\nruncmd:\n  - ['/usr/local/etc/startup.sh']"
  },
  ...
}

See configuration examples for user-data under Examples.

For more information on how to create a VM, see Creating a VM from a public Linux image.

To make sure the configuration scripts ran successfully, get the serial port output of your VM.

ExamplesExamples

Nginx
Docker
Yandex Cloud CLI
Yandex Unified Agent
Terraform
kubectl
Helm

To install and run an Nginx web server on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/startup.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      apt-get update
      apt-get install -y nginx
      service nginx start
      sed -i -- "s/ nginx/ Yandex Cloud - ${HOSTNAME}/" /var/www/html/index.nginx-debian.html
    defer: true
runcmd:
  - ["/usr/local/etc/startup.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

To install Docker on the new VM and to upload and run a container, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: "ALL=(ALL) NOPASSWD:ALL"
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/docker-start.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # Docker
      echo "Installing Docker"
      sudo apt update -y && sudo apt install docker.io -y
      echo "Grant user access to Docker"
      sudo usermod -aG docker ${USER}
      newgrp docker

    defer: true
  - path: "/usr/local/etc/docker-main.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # Docker run container
      docker pull hello-world:latest
      docker run hello-world

    defer: true
runcmd:
  - [su, <username>, -c, "/usr/local/etc/docker-start.sh"]
  - [su, <username>, -c, "/usr/local/etc/docker-main.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

To install the Yandex Cloud CLI on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/yc-install.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # YC CLI
      echo "Installing Yandex Cloud CLI"
      curl \
        --silent \
        --show-error \
        --location \
        https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash
      VM_ID=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id)

      # Save YC params
      echo "Saving YC params to the ~/.bashrc"
      cat << EOF >> $HOME/.bashrc
    defer: true
runcmd:
  - [su, <username>, -c, "/usr/local/etc/yc-install.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

Note

When creating a VM with Yandex Unified Agent, link it to a service account with the monitoring.editor role for the current folder.

To install Unified Agent on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
runcmd:
  - wget -O - https://monitoring.api.cloud.yandex.net/monitoring/v2/unifiedAgent/config/install.sh | bash

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

To link a service account to a VM when creating it using Terraform, add the following row to the configuration:

resource "yandex_compute_instance" "my-vm" {
  ...
  service_account_id = "ajehka*************"
}

For Unified Agent to send metrics to Yandex Managed Service for Prometheus®, specify the workspace ID in the configuration:

resource "yandex_compute_instance" "my-vm" {
  ...
  metadata    = {
    monitoring_workspaceid = "mon618clr**************"
  }
}

To install Terraform on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/tf-install.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # Install Global Ubuntu things
      sudo apt-get update
      echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
      sudo apt-get install -y unzip python3-pip

      # Install Terraform
      echo "Installing Terraform"
      sudo curl \
        --silent \
        --show-error \
        --location \
        https://hashicorp-releases.yandexcloud.net/terraform/1.8.5/terraform_1.8.5_linux_amd64.zip \
        --output /usr/local/etc/terraform.zip
      sudo unzip /usr/local/etc/terraform.zip -d /usr/local/etc/
      sudo install -o root -g root -m 0755 /usr/local/etc/terraform /usr/local/bin/terraform
      sudo rm -rf /usr/local/etc/terraform /usr/local/etc/terraform.zip /usr/local/etc/LICENSE.txt
    defer: true
runcmd:
  - [su, <username>, -c, "/usr/local/etc/tf-install.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

To install kubectl on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/kubectl-install.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # Install kubectl
      echo "Installing kubectl"
      sudo curl \
        --silent \
        --show-error \
        --location \
        https://dl.k8s.io/release/v1.3.0/bin/linux/amd64/kubectl \
        --output /usr/local/etc/kubectl
      sudo install -o root -g root -m 0755 /usr/local/etc/kubectl /usr/local/bin/kubectl
      sudo rm -rf /usr/local/etc/kubectl
    defer: true
runcmd:
  - [su, <username>, -c, "/usr/local/etc/kubectl-install.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

To install Helm on the new VM, specify the following value for the user-data key:

#cloud-config
datasource:
  Ec2:
    strict_id: false
ssh_pwauth: no
users:
- name: <username>
  sudo: 'ALL=(ALL) NOPASSWD:ALL'
  shell: /bin/bash
  ssh_authorized_keys:
  - <public_SSH_key>
write_files:
  - path: "/usr/local/etc/helm-install.sh"
    permissions: "755"
    content: |
      #!/bin/bash

      # Install Helm
      echo "Installing Helm"
      sudo curl \
        --silent \
        --show-error \
        --location \
        https://get.helm.sh/helm-v3.15.2-linux-amd64.tar.gz \
        --output /usr/local/etc/helm-v3.15.2-linux-amd64.tar.gz
      sudo tar xf /usr/local/etc/helm-v3.15.2-linux-amd64.tar.gz -C /usr/local/etc/
      sudo install -o root -g root -m 0755 /usr/local/etc/linux-amd64/helm /usr/local/bin/helm
      sudo rm -rf /usr/local/etc/helm-v3.15.2-linux-amd64.tar.gz /usr/local/etc/linux-amd64
    defer: true
runcmd:
  - [su, <username>, -c, "/usr/local/etc/helm-install.sh"]

Where:

  • <username>: User login to use when connecting to the VM via SSH.
  • <public_SSH_key>: Contents of the public key file. You need to create a key pair for the SSH connection yourself.

See alsoSee also

Other configuration examples for the user-data key:

  • Creating an instance group connected to a file storage
  • Creating an instance group connected to Yandex Object Storage
  • Recovering VM network interfaces
  • Linking a Yandex Cloud Backup policy to a VM automatically
  • Installing the agent for collecting Unified Agent metrics and logs
  • Installing the agent for collecting metrics in Prometheus format

Was the article helpful?

Previous
Creating a VM from a custom image
Next
Creating a VM with metadata from environment variables
Yandex project
© 2025 Yandex.Cloud LLC