Boot with cloud-init


Cloud-init is a software package that automates the initialization of servers during system boot. When you deploy a new Linux server from an image, cloud-init gives you the option to set default user data. User data must be written in shell scripts or cloud-config directives using YAML syntax. This method is highly compatible across platforms and fully secure.

Compatibility: This service is supported on all public IONOS Cloud Linux distributions (Debian, CentOS, and Ubuntu). You may submit user data through the DCD or via Cloud API. Existing cloud-init configurations from other providers are compatible with IONOS Cloud.

Limitations: Cloud-init is available on all public images supplied by IONOS Cloud. If you wish to use your own Linux image, please make sure that it is cloud-init supported first. Otherwise, there is no guarantee that the package will function as intended. Windows images are currently out of scope; adding them may be considered at a later stage.

Provisioning: Cloud-init can only be set at initial provisioning. It cannot be applied to instances that have already been provisioned. Settings can't be changed once provisioned.

Laptops: When using a laptop, please scroll down the properties panel, as additional fields are not immediately visible on a small screen.

Supported user data formats

This tutorial demonstrates the use of cloud-config and user-data scripts. However, the cloud-init package supports a variety of formats.

Data FormatDescription


If user-data is base64-encoded, cloud-init determines if it can understand the decoded data as one of the supported types. If it understands the decoded data, it decodes the data and handles it appropriately. If not, it returns the base64 data intact.

User-Data Script

Begins with #!or Content-Type: text/x-shellscript.

The script is run by /etc/init.d/cloud-init-user-scripts during the first boot cycle. This occurs late in the boot process (after the initial configuration actions are performed).

Include File

Begins with #include or Content-Type: text/x-include-url.

The file contains a list of URLs, one per line. Each of the URLs is read, and their content is passed through this same set of rules. The content read from the URL can be MIME-multi-part or plaintext.

Cloud Config data

Begins with #cloud-config or Content-Type: text/cloud-config.

For a commented example of supported configuration formats, see the examples.

Upstart Job

Begins with #upstart-job or Content-Type: text/upstart-job.

This content is stored in a file in /etc/init, and upstart consumes the content as per other upstart jobs.

Cloud Boothook

Begins with #cloud-boothook or Content-Type: text/cloud-boothook.

This content is boothook data. It is stored in a file under /var/lib/cloud and then runs immediately.

This is the earliest hook available. There is no mechanism provided for running it only one time. The boothook must take care of this itself. It is provided with the instance ID in the environment variable INSTANCE_ID. Use this variable to provide a once-per-instance set of boothook data

Configuring user data via DCD

1. In the DCD, create a new virtual instance and attach any storage device to it.

2. Ensure the storage device is selected. Its Inspector pane should be visible on the right.

3. When choosing the Image, you may either use your own or pick one that is supplied by IONOS.

For IONOS supplied images, select No image selected > IONOS Images.

Alternatively, for private images select No image selected > Own Images.

4. Once you choose an image, additional fields will appear in the Inspector pane.

5. A Root password is required for Remote Console access. You may change it later.

6. SSH keys are optional. You may upload a new key or use an existing file. SSH keys can also be injected as user data utilizing cloud-init.

7. You may add a specific key to the Ad-hoc SSH Key field.

8. Under Cloud-init user data, select No configuration and a window will appear.

9. Input your cloud-init data. Either use a bash script or a cloud-config file with YAML syntax. Sample scripts are provided below.

10. To complete setup, return to the Inspector and click Provision Changes. Cloud-init automatically runs at boot, applying the changes requested.

When the DCD returns the message that provisioning has been successfully completed this means the infrastructure is virtually set up. However, bootstrapping, which includes the execution of cloud-init data, may take additional time. This execution time is not included in the success message. Please allow extra time for the tasks to complete before testing.

Using shell scripts

Using shell scripts is an easy way to bootstrap a server. In the example script below, the code creates and configures our CentOS web server.

# Use this for your user data (script from top to bottom)
# install httpd (Linux 2 version)
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello World from $(hostname -f)</h1>" > /var/www/html/index.html

Allow enough time for the instance to launch and run the commands in your script, and then check to see that your script has completed the tasks that you intended.

The above example will install a web server and rewrite the default index.html file. To test if cloud-init bootstrapped your VM successfully, you can open the corresponding IP address in your browser. You should be greeted with a “Hello World” message from your web server.

Using cloud-config directives

Cloud-init images can also be bootstrapped using cloud-config directives. The cloud-init website outlines all supported modules and gives examples of basic directives.



Example 1: Creating a swap partition

The following script is an example of how to create a swap partition with second block storage, using a YAML script:

  - label: mylabel
    device: /dev/vda
    filesystem: ext4
  - label: swap
    device: /dev/vdb
    filesystem: swap
- [ /dev/vda, /, ext4, defaults, 0, 0 ]
- [ /dev/vdb, none, swap, sw, 0, 0 ]

Example 2: Resizing the file system

The following script is an example of how to resize your file system according to the chosen size of the block storage. It will also create a user with an SSH key, using a cloud-config YAML script:

resize_rootfs: True
  - name: pb-user
    gecos: Demo User
    groups: users, admin
    ssh_import_id: None
    lock_passwd: true
      - ssh-rsa AAAA...

Output log files

The cloud-init output log file (/var/log/cloud-init-output.log) captures console output. Depending on the default configuration for logging, a second log file exists under /var/log/cloud-init.log. **** This provides a comprehensive record based on user data.

Configuring user data via API

Cloud API provides enhanced convenience if you want to automate the provisioning and configuration of cloud instances. Cloud-init is configured on the volume resource in Cloud API V6 (or later). Please find the link to the documentation below:

Name: userData

Type: string

Description: The cloud-init configuration for the volume as base64 encoded string. The property is immutable and is only allowed to be set on a new volume creation. It is mandatory to provide either public image or imageAliasthat has cloud-init compatibility in conjunction with this property.

Curl example

curl --include \
     --request POST \
     --user '<user:password>' \
     --header "Content-Type: application/json" \
     --data-binary '{
         "properties": {
             "name": "Server-01",
             "ram": 2048,
             "cores": 1,
             "availabilityZone": "ZONE_1",
             "cpuFamily": "INTEL_SKYLAKE"
         "entities": {
             "volumes": {
                 "items": [ {
                    "properties": {
                      "size": 10,
                      "type": "HDD",
                      "name": "Server-01_HDD",
                      "image": "bf4d1400-b48d-11eb-b9b3-d2869b2d44d9",
                      "imagePassword": "<pAsSW0rD>",
                      "sshKeys": ["<ssh_key>"],
                      "userData": "I2Nsb3VkLWNvbmZpZwoKcGFja2FnZXM6CiAgLSBodHRwZAogIC0gZmlyZXdhbGxkCgpydW5jbWQ6CiAgLSAvYmluL3N5c3RlbWN0bCBlbmFibGUgaHR0cGQKICAtIC9iaW4vc3lzdGVtY3RsIHN0YXJ0IGh0dHBkCiAgLSAvYmluL2ZpcmV3YWxsLW9mZmxpbmUtY21kIC0tYWRkLXBvcnQ9ODAvdGNwCiAgLSAvYmluL3N5c3RlbWN0bCBlbmFibGUgZmlyZXdhbGxkCiAgLSAvYmluL3N5c3RlbWN0bCBzdGFydCBmaXJld2FsbGQKICAtIGxvYWRrZXlzIGRlCgp3cml0ZV9maWxlczoKLSBjb250ZW50OiB8CiAgICA8IURPQ1RZUEUgaHRtbD4KICAgIDxodG1sPgogICAgICA8aGVhZD4KICAgICAgPC9oZWFkPgogICAgICA8Ym9keT4KICAgICAgICA8cD5XZWxjb21lIHRvIHlvdXIgbmV3IHdlYiBzZXJ2ZXIuPC9wPgogICAgICA8L2JvZHk+CiAgICA8L2h0bWw+CiAgcGF0aDogL3Zhci93d3cvaHRtbC9pbmRleC5odG1sCgpmaW5hbF9tZXNzYWdlOiAiVGhlIHN5c3RlbSBpcyBmaW5hbGx5IHVwLCBhZnRlciAkVVBUSU1FIHNlY29uZHMiCg=="
                 } ]
             "nics": {
                 "items": [ {
                    "properties": {
                      "name": "NIC001",
                      "dhcp": true,
                      "lan": 1
                    } ]
        }' \<datacenter_id>/servers

Last updated