How to use cloud-init
¶
cloud-init
is a tool for automatically initializing and customizing an instance of a Linux distribution.
By adding cloud-init
configuration to your instance, you can instruct cloud-init
to execute specific actions at the first start of an instance.
Possible actions include, for example:
Updating and installing packages
Applying certain configurations
Adding users
Enabling services
Running commands or scripts
Automatically growing the file system of a VM to the size of the disk
See the Cloud-init documentation for detailed information.
Note
The cloud-init
actions are run only once on the first start of the instance.
Rebooting the instance does not re-trigger the actions.
cloud-init
support in images¶
To use cloud-init
, you must base your instance on an image that has cloud-init
installed:
All images from the
ubuntu
andubuntu-daily
image servers havecloud-init
support. However, images for Ubuntu releases prior to 20.04 LTS require special handling to integrate properly withcloud-init
, so thatlxc exec
works correctly with virtual machines that use those images. Refer to VMcloud-init
.Images from the
images
remote havecloud-init
-enabled variants, which are usually bigger in size than the default variant. The cloud variants use the/cloud
suffix, for example,images:alpine/edge/cloud
.
Configuration options¶
LXD supports two different sets of configuration options for configuring cloud-init
: cloud-init.*
and user.*
.
Which of these sets you must use depends on the cloud-init
support in the image that you use.
As a rule of thumb, newer images support the cloud-init.*
configuration options, while older images support user.*
.
However, there might be exceptions to that rule.
The following configuration options are supported:
cloud-init.vendor-data
oruser.vendor-data
(see Vendor data)cloud-init.user-data
oruser.user-data
(see User data formats)cloud-init.network-config
oruser.network-config
(see Network configuration)
For more information about the configuration options, see the cloud-init
instance options, and the documentation for the LXD data source in the cloud-init
documentation.
Vendor data and user data¶
Both vendor-data
and user-data
are used to provide cloud configuration data to cloud-init
.
The main idea is that vendor-data
is used for the general default configuration, while user-data
is used for instance-specific configuration.
This means that you should specify vendor-data
in a profile and user-data
in the instance configuration.
LXD does not enforce this method, but allows using both vendor-data
and user-data
in profiles and in the instance configuration.
If both vendor-data
and user-data
are supplied for an instance, cloud-init
merges the two configurations.
However, if you use the same keys in both configurations, merging might not be possible.
In this case, configure how cloud-init
should merge the provided data.
See Merging user data sections for instructions.
How to configure cloud-init
¶
To configure cloud-init
for an instance, add the corresponding configuration options to a profile that the instance uses or directly to the instance configuration.
When configuring cloud-init
directly for an instance, keep in mind that cloud-init
runs only on the first start of the instance.
That means that you must configure cloud-init
before you start the instance.
If you are using the CLI client, create the instance with lxc init
instead of lxc launch
, and then start it after completing the configuration.
To add your configuration:
Write the configuration to a file and pass that file to the lxc config
command.
For example, create cloud-init.yml
with the following content:
#cloud-config
package_upgrade: true
packages:
- package1
- package2
Then run the following command:
lxc config set <instance_name> cloud-init.user-data - < cloud-init.yml
Provide the cloud-init
configuration as a string with escaped newline characters.
For example:
lxc query --request PATCH /1.0/instances/<instance_name> --data '{
"config": {
"cloud-init.user-data": "#cloud-config\npackage_upgrade: true\npackages:\n - package1\n - package2"
}
}'
Alternatively, to avoid mistakes, write the configuration to a file and include that in your request.
For example, create cloud-init.txt
with the following content:
#cloud-config
package_upgrade: true
packages:
- package1
- package2
Then send the following request:
lxc query --request PATCH /1.0/instances/<instance_name> --data '{
"config": {
"cloud-init.user-data": "'"$(awk -v ORS='\\n' '1' cloud-init.txt)"'"
}
}'
Go to the Configuration tab of the instance detail page and select Advanced > Cloud init.
Then click Edit instance and override the configuration for one or more of the cloud-init
configuration options.
YAML format for cloud-init
configuration¶
The cloud-init
options require YAML’s literal style format.
You use a pipe symbol (|
) to indicate that all indented text after the pipe should be passed to cloud-init
as a single string, with new lines and indentation preserved.
The vendor-data
and user-data
options usually start with #cloud-config
.
For example:
config:
cloud-init.user-data: |
#cloud-config
package_upgrade: true
packages:
- package1
- package2
Tip
See How to validate user data for information on how to check whether the syntax is correct.
How to check the cloud-init
status¶
cloud-init
runs automatically on the first start of an instance.
Depending on the configured actions, it might take a while until it finishes.
To check the cloud-init
status, log on to the instance and enter the following command:
cloud-init status
If the result is status: running
, cloud-init
is still working. If the result is status: done
, it has finished.
Alternatively, use the --wait
flag to be notified only when cloud-init
is finished:
root@instance:~#
cloud-init status --wait
.....................................
status: done
How to specify user or vendor data¶
The user-data
and vendor-data
configuration can be used to, for example, upgrade or install packages, add users, or run commands.
The provided values must have a first line that indicates what type of user data format is being passed to cloud-init
.
For activities like upgrading packages or setting up a user, #cloud-config
is the data format to use.
The configuration data is stored in the following files in the instance’s root file system:
/var/lib/cloud/instance/cloud-config.txt
/var/lib/cloud/instance/user-data.txt
Examples¶
See the following sections for the user data (or vendor data) configuration for different example use cases.
You can find more advanced examples in the cloud-init
documentation.
Upgrade packages¶
To trigger a package upgrade from the repositories for the instance right after the instance is created, use the package_upgrade
key:
config:
cloud-init.user-data: |
#cloud-config
package_upgrade: true
Install packages¶
To install specific packages when the instance is set up, use the packages
key and specify the package names as a list:
config:
cloud-init.user-data: |
#cloud-config
packages:
- git
- openssh-server
Set the time zone¶
To set the time zone for the instance on instance creation, use the timezone
key:
config:
cloud-init.user-data: |
#cloud-config
timezone: Europe/Rome
Run commands¶
To run a command (such as writing a marker file), use the runcmd
key and specify the commands as a list:
config:
cloud-init.user-data: |
#cloud-config
runcmd:
- [touch, /run/cloud.init.ran]
Add a user account¶
To add a user account, use the user
key.
See the Including users and groups example in the cloud-init
documentation for details about default users and which keys are supported.
config:
cloud-init.user-data: |
#cloud-config
user:
- name: documentation_example
How to specify network configuration data¶
By default, cloud-init
configures a DHCP client on an instance’s eth0
interface.
You can define your own network configuration using the network-config
option to override the default configuration (this is due to how the template is structured).
cloud-init
then renders the relevant network configuration on the system using either ifupdown
or netplan
, depending on the Ubuntu release.
The configuration data is stored in the following files in the instance’s root file system:
/var/lib/cloud/seed/nocloud-net/network-config
/etc/network/interfaces.d/50-cloud-init.cfg
(if usingifupdown
)/etc/netplan/50-cloud-init.yaml
(if usingnetplan
)
Example¶
To configure a specific network interface with a static IPv4 address and also use a custom name server, use the following configuration:
config:
cloud-init.network-config: |
version: 1
config:
- type: physical
name: eth1
subnets:
- type: static
ipv4: true
address: 10.10.101.20
netmask: 255.255.255.0
gateway: 10.10.101.1
control: auto
- type: nameserver
address: 10.10.10.254