Using Custom Cloud-Init User Data

evroc's cloud supports cloud-init to configure virtual machines (VMs) on first boot.

Cloud-init is a widely used approach for provisioning and customizing Linux VMs on first boot. It allows for the installation of packages, starting of services, user creation, SSH key configuration, the automatic mounting of Disks, and security hardening. evroc's cloud passes user data directly to the VM, enabling cloud-init to apply the desired configuration during the initial boot process.

All evroc-provided Linux VM images come with cloud-init pre-installed.


Cloud-Init in evroc Cloud

How Is Cloud-Init Data Loaded Onto a VM?

Cloud-init retrieves its configuration from various "datasources". A datasource provides all necessary configuration data, including user data.

evroc's cloud uses the NoCloud datasource, specifically the "Drive with labeled filesystem" method, as documented in the cloud-init NoCloud reference.

This means that evroc attaches a disk labeled cidata (/dev/disk/by-label/cidata) to the VM. Cloud-init mounts this disk and reads two files:

  • user-data – The user-specified cloud-init configuration.
  • meta-data – Additional metadata about the instance.

There is no vendor-data or network-data present.

Example meta-data File

{
    "instance-id": "273dc45b-5674-56b2-a611-a615151d3305",
    "local-hostname": "<VM name>",
    "public-keys": {
      "0": "ssh-ed25519 AAAAC3Nz..."
    }
}

The SSH public keys in this file correspond to those set in the evroc VirtualMachine API under OSSettings.SSH.AuthorizedKeys, or the SSH key specified in the VM creation command using evroc CLI.

The instance-id will change everytime you make a change to the spec of your VM (including stopping and re-starting your VM), but otherwise will not change.

Authoring a cloud-init user data file

The cloud-init documentation explains all the valid formats. All of these formats are supported. Note that this means that in addition to Cloud-config YAML (#cloud-config), this can also be used for shell scripts, Jinja2 templates and mime multi-part cloud config.

For a complete list of available cloud-config modules, refer to the cloud-init module reference.

Creating users with sudo permissions

By default, if you specify custom cloud-init you will not have any users on your VM. it is recommended you create at least one user, and give this user sudo permissions:

#cloud-config
ssh_pwauth: false
users:
  - name: evroc-user
    gecos: evroc VM user
    lock_passwd: true
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups:
      - sudo
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-rsa ...

evroc best practice is to:

  • turn off SSH password authentication altogether using the ssh_pwauth: false option.
  • create a evroc-user with sudo access and to provide your SSH authorized keys directly.

Using meta-data and Injecting SSH keys

If you specify both OSSettings.SSH.AuthorizedKeys and customCloudInitUserData in the VirtualMachine API, you must ensure that the SSH keys are included in your cloud-init configuration. We strongly recommend incorporating the below template.

To dynamically insert SSH keys from the meta-data file, use Jinja2 templating:

## template: jinja
#cloud-config

users:
  - name: evroc-user
{% if public_ssh_keys %}
    ssh_authorized_keys:
{% for pubkey in public_ssh_keys %}
      - {{ pubkey }}
{% endfor %}
{% endif %}

Note: If you fail to do this, then your SSH Authorized Keys will not be applied.

Alternatively, you can skip setting authorizedKeys in the API and define them directly in your cloud-init user data.

Referencing a cloud init userdata file on the API

Once you have constructed a cloud-init userdata file, you need to reference it on the API.

CLI Example

Multi-line YAML formatting can be tricky. The safest way is to load your cloud-config from a file:

  --vm-virtual-resources-ref=general.s  \
  --disk=mybootdisk --boot-from=true  \
  --ssh-authorized-key="ssh-ed25519 AAAAC3NZ..."  \
  --cloud-init-user-data="$(cat cloud-config.txt)"

Alternatively, base64-encode the cloud-config to avoid formatting issues:

  --vm-virtual-resources-ref=general.s \
  --disk=mybootdisk --boot-from=true  \
  --cloud-init-user-data="$(base64 cloud-config.txt)"

Plain Text vs. Base64 Encoding

  • Plain text is human-readable but prone to formatting issues (e.g., special characters, line breaks, incorrect indentation).
  • Base64 encoding avoids formatting problems but requires decoding before debugging. We recommend base64 encoding to ensure seamless transmission over HTTP.

Supported Distributions

The following table shows cloud-init compatibility with evroc images:

ImageCloud-Init VersionStatus
ubuntu.24-04.124.3.1-0ubuntu0~24.04.2✅ VERIFIED
ubuntu-minimal.24-04.124.4-0ubuntu1~24.04.2✅ VERIFIED
ubuntu.22-04.124.3.1-0ubuntu0~22.04.1✅ VERIFIED
opensuse.15-5.121.4-lp155.2.251✅ VERIFIED
opensuse.15-6.123.4-19.el9.0.2✅ VERIFIED
rocky.8-10.123.4-7.el8_10.0.1✅ VERIFIED
rocky.9-5.123.4-19.el9.0.2✅ VERIFIED
sles.15-5.123.3-150100.8.82.3✅ VERIFIED (note package install does not work because SLES does not come with any repositories defined)
sles.15-6.123.3-150100.8.82.3✅ VERIFIED (note package install does not work because SLES does not come with any repositories defined)
sl-micro.6-1.123.3-slfo.1.1_1.3✅ VERIFIED (note package install does not work because SL Micro does not come with any repositories defined)

Troubleshooting Cloud-Init

Logs and Debugging

Cloud-init continues execution even if errors occur. If something goes wrong, SSH into the VM and check:

cat /var/log/cloud-init.log
cat /var/log/cloud-init-output.log

SSH Not Working?

If SSH access fails:

  • Your cloud-config may contain invalid YAML syntax (e.g., incorrect indentation, tabs instead of spaces).
  • Validate your cloud-config using tools in the cloud-init debugging guide.

If you get a "Permission denied(publickey)" error when attempting to login with your public key, then it may be that your SSH authorized key was not correctly added to the VM. Ensure if you specified the SSH Key outside of the cloud init template, that you templated in the SSH key correctly to your cloud init.

If SSH is completely unavailable, contact evroc support. Future updates will expose boot logs directly via the evroc API.

Handling Cloud-Init Configuration Mistakes

Once a VM is created, you cannot update the customCloudInitUserData field. If you make a mistake, do not delete the VM while keeping the boot disk, as this may lead to inconsistent provisioning (for example your boot disk may already contain the /var/lib/cloud/instance/boot-finished file that cloud-init uses to determine if this a first boot or not).

Instead, delete both the VM and its boot disk, then recreate them. This ensures that cloud-init runs properly on the next boot.