What is Cloud-Init?

August 16, 2021

Introduction

Cloud instances are based on default cloud images. Since each instance uses a template operating system, it is up to the user to configure and set up a unique instance using user data.

Instead of configuring each after it runs up, there is an open source tool which automates the initialization- cloud-init.

What is cloud-init?

What Is cloud-init?

Cloud-init is a service used for customizing Linux-based operating systems in the cloud. It allows you to customize virtual machines provided by a cloud vendor by modifying the generic OS configuration on boot. Canonical initially developed cloud-init for Ubuntu but expanded to most major Linux and FreeBSD operating systems. Today, it officially supports 8 Unix OSs - Ubuntu, Arch Linux, CentOS, Red Hat, FreeBSD, Fedora, Gentoo Linux, and openSUSE.

Cloud-init is supported for the following Linux distros.

The service is used as an industry standard for early-stage initialization of a VM once it has been provisioned. Therefore, it allows you to set up a VM to work as needed on first boot.

Most vendors have the service preinstalled on Unix OS images. When creating a virtual machine using the cloud vendor dashboard, you will most likely have a cloud-init or user data section to specify the wanted configuration.

Cloud-init is used to install packages, configure users and security, write files, and do other tasks you want automatically handled on the first or subsequential boots.

How Does cloud-init Work?

Cloud-init is a service that sets up your VM instance with the wanted configuration and software ready to use. The service starts at boot and uses the metadata provided by the cloud provider or the direct user.

It does so by executing scripts, most commonly from the cloud-config file. Therefore, to change any default settings, you need to edit the cloud-config file on your VM image. This is a YAML file that follows basic YAML syntax rules, such as:

  • Relationships between items are defined by indentations with whitespaces.
  • A pipe character (|) before a text indicates it should be interpreted as is.
  • Text blocks are indented.
  • A leading dash (-) identifies members of a list.
  • A colon (:) + space + value is used to create associative array entries.

You can add the cloud-config file:

  1. In the control plane interface, when selecting additional options. The provider will have a cloud-init or User data option where you can paste the configuration file.
  2. Through a file in the JSON object in an API request.
How does cloud-init work.

cloud-init Capabilities

The cloud-init service is used for a variety of things, including:

  • Adding users and groups.
  • Writing out arbitrary files.
  • Adding YUM repositories.
  • Running commands on first boot.

To learn the syntax used for each capability, read the subsections below.

Add Users and Groups Using cloud-init

To add users and groups to a VM during provisioning, use the following syntax in your cloud-config file:

#cloud-config
# Add groups to the system.
groups:
  - group_name: [member1,member2]
# Add users to the system.
users:
 - default
 - name: User’s login name.
   gecos: User’s real name.
   primary_group: The primary group the user belongs to. If omitted, a new group is created under the user’s name.
   groups: Additional groups to which you want to add the user.
   selinux_user: The SELinux user for the user's login. If omitted, the system selects the default SELinux user.
   expiredate: 'year-month-day' - Data when the user’s account should be disabled.
   ssh_import_id: SSH IDs which you want to import.
   lock_passwd: Use true or false to define whether you want to lock the password to disable password login. By default, the value is set to true.
   inactive: 'x' - The number of days until the account is disabled after a password expires.
   passwd: The hash of the password you want to use.
   ssh_authorized_keys: Add keys to user’s authorized keys file:
      - <ssh pub key 1>
      - <ssh pub key 2>
   system: Use true or false to define the new user as a system user.
   sudo: Use sudo rule string(s) to define the user privileges. The user has no privileges by default, but it can accept one or multiple sudo rule strings. For example, add ALL=(ALL) NOPASSWD:ALL to give the user unrestricted access. To prevent sudo access, type: False.
  - snapuser: Specify the email for your Ubuntu SSO account to allow snap to import a username and public keys into the system.

You don’t need to include all the options when adding a new user. The configurations listed above apply only if the user is new. If the user already exists, the system only modifies the following options:

  • plain_text_passwd
  • hashed_passwd
  • lock_passwd
  • sudo
  • ssh_authorized_keys
  • ssh_redirect_user

Writing Out Arbitrary Files

You can write out arbitrary files using the yaml configuration syntax. The content can be encoded (base64 or gzip) and specified in plain text or binary. Before the data is written to the defined path, it is decoded. The module supports all distros and has a frequency module of once-per-instance.

Note: If working with binary data, make sure to use the !!!binary yaml option.

To write out arbitrary files with cloud-init, use the following syntax:

#cloud-config
# Write out arbitrary files
write_files:
  path: The file path to which the content is added.
  content: The content you want to add to the path.
  owner: The user/group that has ownership. By default, the owner is root:root.
  permissions: The permission of the specified path, defined with the appropriate octal string. The default permission is ‘0644’.
  append: Use true or false to choose whether to append the specified content to an existing file if the path provided exists. The default value is false.

Adding YUM Repositories

You may need to configure a yum repository to ensure you are using the correct packages to install the wanted software. Use cloud-init to add yum repository configurations to the system. The configuration file is added to /etc/yum.repos.d.

To add a yum repository configuration, use the syntax:

yum_repos:
  <repo_name>:
            baseurl: Repository URL.
            name: Repository name.
            enabled: true/false
            + any other repository configuration option

Running Commands on First Boot

To run arbitrary commands early in the boot process, you can use the bootcmd or runcmd module.

bootcmd run specific commands on every boot, after running a boothook. It supports all distros and accepts commands specified as lists or strings. The syntax is:

bootcmd: 
   - array of (array of string)/(string)

For instance:

bootcmd:
  - echo 192.168.1.130 us.archive.ubuntu.com >> /etc/hosts
  - [cloud-init-per, once, mymkfs, mkfs, /dev/vdb ]

runcmd runs a command only on first boot. It can execute commands specified as lists or strings. All the commands have to be in the yaml syntax (therefore, make sure to quote any problematic characters). The syntax is:

runcmd: 
   - array of (array of string)/(string)

Like in the following example:

runcmd:
 - [ ls, -l, / ]
 - [ sh, -xc, "echo $(date) ': hello world!'" ]
 - [ sh, -c, echo "=========hello world'=========" ]
 - ls -l /root

Note: Make sure not to write files to /tmp from cloud-init. Instead, use /run/somedir.

Configure SSH Keys

You can manage SSH configuration using cloud-init.

Authorized keys are SSH keys stored in the user's home directory, in .ssh/authorized_keys. They define which keys can connect to that specific user account on the system. Add the public keys as a list when configuring a user using ssh_authorized_key:

ssh_authorized_keys:
  - ssh_pub_key_1
  - ssh_pub_key_2

The listed keys will belong to the configured user or the first one defined in the user's module.

If you already have pre-generated private SSH keys, you can store them on the server. Cloud-init supports RSA, DSA, and ECDS public key cryptosystems. Make sure to pay attention to formatting when adding the SSH keys - use line breaks, blocks, pipe keys, and always specify the BEGINING PRIVATE KEY and END PRIVATE KEY.


ssh_keys:
  rsa_private: |
    -----BEGIN RSA PRIVATE KEY-----
    your_rsa_private_key
    -----END RSA PRIVATE KEY-----

  rsa_public: your_rsa_public_key

Set Up a Locale

To set up and apply a system locale system wide, utilize the cc_locale module. Use the following configuration shema to define the:

locale: What you want to configure as the system's locale.
locale_configfile: The path to the file where you want to write the locale configuration.

Define the Hostname

With cloud-init, you can set the hostname and FQDN (fully qualified domain name). There are several ways to do so:

  • Specify the full domain name using the fqdn key.
  • Define the hostname using the hostname key.
  • Use the hostname key to define fqdn (not recommended).
  • Use both the the hostname key and the fqdn key.

The configuration keys for defining the hostname include:

preserve_hostname: Use true or false to set whether to preserve the host name or allow altering. 
prefer_fqdn_over_hostname: Use true or false to set whether to force the use of FQDN in all distros.
fqdn: FQDN
hostname: FQDN/hostname

Conclusion

Use the cloud-init package to seamlessly initialize your cloud instances with the configuration and software set up and ready to use. Add users and groups, write out arbitrary files, add yum repositories or run commands on first boot with the help of this powerful tool.

Was this article helpful?
YesNo
Sofija Simic
Sofija Simic is an experienced Technical Writer. Alongside her educational background in teaching and writing, she has had a lifelong passion for information technology. She is committed to unscrambling confusing IT concepts and streamlining intricate software installations.
Next you should read
How to Deploy a Bare Metal Cloud Server
March 23, 2021

This article shows how to deploy a new Bare Metal Cloud server in nine simple steps. Follow the instructions...
Read more
Bare Metal Cloud GitHub Actions
May 6, 2021

GitHub Actions is a platform for software development workflow automation with a built-in CI/CD tool...
Read more
Kubernetes for Multi-Cloud and Hybrid Cloud Portability
May 6, 2021

Hybrid and multi-cloud strategies became popular due to the competitive advantages, such as lack of vendor lock-in...
Read more
12 Best Cloud Databases
May 20, 2021

This article deals with the key features of cloud databases, their benefits over traditional on-premises databases...
Read more