# Cloud-init: What is it and Why it’s Important to Your Cloud Environment

Cloud-init is a proven method of bootstrapping your instances in the cloud
and creating a standard environment for your workloads to run on, providing
standardization and manageability.

This page describes what it is and how it’s implemented.

## Cloud-init and its capabilities

[Cloud-init](https://launchpad.net/cloud-init) is an initialization service that is
installed inside an instance, and cloud-config is a set of scripts that
are executed as soon as the instance is started.

Zadara only provides a cloud-init metadata service.
This service is available at the link-local address `169.254.169.254`.
It provides the VM with basic information about the instance.
The service also provides cloud-init user-data, which users can add.
This user-data allows for additional configurations when creating a new instance.

The Zadara Compute cloud provides the cloud-init metadata to the VM.
The configuration in the OS image determines how this metadata is used
during a VM’s first boot initialization.

Cloud-init runs on Linux workloads. The equivalent for Microsoft Windows
is CloudBase-init, which supports the majority of cloud-config parameters. The
service on the operating system starts early at boot, retrieves metadata that
has been provided from an external provider (metadata) or by direct user data
supplied by the user.

You can pass a regular script of almost any interpreter that you wish to use,
providing that you have that interpreter already installed on your instance.

For example, passing a bash script to almost any instance should succeed,
because most instances have bash installed by default. On the other hand, passing
a Python or Ruby script to cloud-init as a file will most probably not work,
unless you already have Python or Ruby installed in your instance as part of
your image or template.

## Cloud-config Syntax

Cloud-config has its own syntax that is based on
[YAML](http://yaml.org/), a human-readable data
serialization language.
There are a number of basic rules that you should be
aware of when using YAML:

* Indentation with white spaces (not tabs) defines the relationship and structure
  of the resources in the script.
* Members of a list can be identified with the leading dash on the line.
* Blocks of text are indented.
* Text that is to be interpreted as is, should be preceded by a pipe
  character (`|`). For example:
  ```default
  examples:
  - comment: |
      Example 1: (optional) description of the expected behavior of the example
  ```

## Cloud-config Examples

### Users and Groups

When provisioning your instances, a good practice is to ensure that you have
a default group and a user defined for the instance. This allows you to
ensure that you have a standard configuration of all your provisioned instances
and also allows you to comply with requirements as needed.

```default
#cloud-config
users:  - name: strato
          groups: sudo
          shell: /bin/bash
          sudo: ['ALL=(ALL) NOPASSWD:ALL']
          ssh-authorized-keys: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWDAaaaaxcdxd +eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV8 +NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgAaaaaaaffcdc+i1CS0Ku4ld8vndXvr504jV9BM QoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8T jxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4X HDEOjbSMRX user@example.com
```

What the code snippet above does:

The first line, `#cloud-config`, tells cloud-init that this is a cloud-config
file and should be treated as such.

Next, there is a top level object `users` with the following characteristics:

* A new user with the name `strato`
* This user is a member of the sudo group with a bash shell, with privileges in
  the sudoers file that allow the user to run all privileged commands
  without having to provide a password
* Specifies the key to be added to the user’s ~/.ssh/authorized_keys
  file when the user is created

## Injecting Key-Value Pairs

When deploying at scale you are probably already using some kind of configuration
management system such as Puppet, Salt or Chef to customize your instances.
Attempting to manage customization on each instance individually does not scale well.

### How can cloud-config help?

When you provision an instance, you would like to be able to identify the
instance to be provisioned in a certain way.

For example, you would like the instance to be installed as a web server,
to provide static content for your web application. The flow would be as follows:

1. Provision an instance with cloud-config
2. Configure the instance to point to your configuration management server
3. Identify the instance as a web server

This can be accomplished by defining a custom variable as part of your user-data,
which will be parsed by cloud-init and then used further for the provisioning
of the instance.

Following is an abbreviated example (this is not a full solution) of how
this would be accomplished:

```default
#!/bin/sh set -e -x # Standard role defaultrole=web #
# get role from commandline or if absent from hiera
# if [ $# -gt 0 ]; then  role=$1 else  role="`hiera -c
/etc/puppet/hiera.yaml
role $defaultrole 2>&1`" fi # # Run puppet.
# if [ -f /etc/puppet/manifests/$role.pp  ]; then  puppet apply
/etc/puppet/manifests/$role.pp else
echo "/etc/puppet/manifests/$role.pp was not found!"
exit 1 fi
```

Here we have defined the instance with the role of a web server, and instructed
the instance to apply the appropriate modules according to the role for which
the instance was defined. This could also be accomplished by setting specific
metadata on the instance through your cloud platform upon instantiation, and
then configuring the instance to retrieve that information and act upon it.

## Adding Specific Yum Repositories

To install your software, configure a specific yum or apt repository
on the instance so that it will know from where to pull the correct packages.
This can be accomplished by adding the following lines to your cloud-config file:

```default
#cloud-config # # Add yum repository configuration to the system
# # The following example adds the file /etc/yum.repos.d/epel_testing.repo
# which can then subsequently be used by yum for later operations.
yum_repos:
# The name of the repository    epel-testing:
baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch
enabled: false
failovermethod: priority
gpgcheck: true
gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
name: Extra Packages for Enterprise Linux 5 - Testing
```

## Creating a custom image

### Linux

To create your own custom image with its own custom cloud-init
behavior, you’ll need to do the following to prepare the image.

- Install any software packages you want in the final image, including the
  cloud-init package.
- Configure `/etc/cloud/cloud.cfg` or `/etc/cloud/cloud.cfg.d` as
  desired.
- Run `cloud-init clean` to clean or reset cloud-init.
- Manually clean up anything else you don’t want baked into the image, such
  as installers, temporary files, shell history, and so on.
- Shutdown and create an image from the volume.

The cloud-init documentation outlines all of this in more detail.

Cloud-init is a 3rd-party application and standard. This page provides some
basic guidance.

Looking at the default configuration for cloud-init found on Canonical’s
Ubuntu 22.04 image, the user section looks like this:

```yaml
users:
  - default
```

Instead of using cloud-init to create the default user, you can replace it.
For example:

```yaml
users:
  - name: asigra
    lock_passwd: True
    groups: [comma-separated list of groups needed for your usecase]
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    shell: /bin/bash
```

This creates an `asigra` user instead of an `ubuntu` user.

The `lock_passwd` parameter forces users to set a password at their first
sign-on. Initially, they must sign on via SSH using their SSH key, as they
don’t yet have a password.
After signing on via SSH for the first time and setting a password,
they can subsequently sign on to the VM via VNC using that password.

This configuration also grants the `asigra` user password-free sudo
permissions.
It adds them to the groups specified in the `groups` list,
and sets their default shell to `/bin/bash`.

### Windows

For Windows, the steps for creating a custom image are largely the same as
for Linux.

1. Install any software that you need, and apply your customizations.
2. Install Cloudbase-init and create or edit the configuration file
   to suit your needs.
3. To get Windows into a fresh state, clean up installers, event logs,
   and other temporary files.
4. Run `sysprep`, just as you would with any Windows OS image.

#### Key Pairs and Windows Access

For accessing a Windows VM, key pairs are typically not used in
the same way as with Linux VMs.

Instead, after configuring the necessary settings in the cloud-init
configuration, you would likely use Remote Desktop Protocol (RDP) or another
remote access method to connect to the instance.

For further information, see [Get a Windows instance password](key-pair.md#kp-get-windows-instance-password).
