Creating a VM with a custom configuration script
You can create a VM with a preset software configuration by using the user-data
key in the VM metadata.
The cloud-inituser-data
key. Cloud-init
supports different metadata transmission formats, e.g., cloud-config
Creating 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:
-
In the management console
, select the folder to create your VM in. -
Select Compute Cloud from the list of services.
-
In the left-hand panel, select
Virtual machines. -
Click Create virtual machine.
-
Set the required VM parameters.
-
Expand the Metadata section and specify:
- Key:
user-data
. - Value:
cloud-config
configuration in YAML format. See configuration examples foruser-data
under Examples.
- Key:
-
Click Create VM.
If you do not have the Yandex Cloud CLI yet, install and initialize it.
The folder specified in the CLI profile is used by default. You can specify a different folder through 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 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 en 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 thecloud-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 don't have Terraform, install it and configure the 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 thecloud-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.
Examples
To install and run an Nginxuser-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 Dockeruser-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, make sure to 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 install Terraformuser-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 kubectluser-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 Helmuser-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 also
Other configuration examples for the user-data
key: