Backends¶
Each of network, system, and user (see Configuration)
is applied by one of three kinds of backend: built-in, none, or
custom.
The built-in backends try to detect changes made to the cloud-init data by
keeping a copy of the data from the last run in
/var/lib/cloud-init-pve/cloud-init-data.yaml, and only apply a given piece
of configuration if it actually changed since then. This is what protects
local changes made to the target config files: if the cloud-init data for,
say, an SSH key hasn't changed, cloud-init-pve doesn't touch
authorized_keys again.
Network¶
Backend choice: network.backend — systemd (built-in, default) or
none.
cloud-init-pve configures the network by creating or updating entries in
/etc/systemd/network: a .link file renames each interface to match the
cloud-init name, matched by mac_address, and a .network file applies
that interface's subnets (static addresses, gateways, or DHCP).
DNS is configured in /etc/systemd/resolved.conf, under [Resolve]'s
DNS= and Domains=.
Selecting this backend also makes sure systemd-networkd.service is
enabled and running (systemctl enable --now), on every run, regardless
of whether anything actually changed — nothing else guarantees networkd is
even enabled (Debian's default network stack may be ifupdown or
NetworkManager instead), so writing .link/.network files it never
picks up would otherwise fail silently.
Custom backend¶
The script is invoked once, with all interfaces and nameservers passed as environment variables:
| Variable | Description |
|---|---|
CI_BACKEND |
network |
CI_DNS_SERVERS |
Space-separated list of nameservers. |
CI_DNS_SEARCH |
Space-separated list of search domains. |
CI_INTERFACE_n_MAC_ADDRESS |
MAC address used to match this interface. |
CI_INTERFACE_n_NAME |
The interface's target name (cloud-init's name field). |
CI_INTERFACE_n_IPV4_TYPE |
The subnet's cloud-init type (e.g. static, dhcp). Only set if this interface has an IPv4 subnet. |
CI_INTERFACE_n_IPV4_ADDRESS |
The static IPv4 address. Only set for a static subnet. |
CI_INTERFACE_n_IPV4_CIDR |
The IPv4 prefix length (e.g. 24), derived from IPV4_NETMASK. Only set for a static subnet. |
CI_INTERFACE_n_IPV4_GATEWAY |
The IPv4 gateway address. Only set if a gateway was configured for this subnet. |
CI_INTERFACE_n_IPV4_NETMASK |
The IPv4 netmask, as a dotted-quad (e.g. 255.255.255.0). Only set for a static subnet. |
CI_INTERFACE_n_IPV6_TYPE |
The subnet's cloud-init type (e.g. static6, dhcp6). Only set if this interface has an IPv6 subnet. |
CI_INTERFACE_n_IPV6_ADDRESS |
The static IPv6 address. Only set for a static6 subnet. |
CI_INTERFACE_n_IPV6_CIDR |
The IPv6 prefix length (e.g. 64), derived from IPV6_NETMASK. Only set for a static6 subnet. |
CI_INTERFACE_n_IPV6_GATEWAY |
The IPv6 gateway address. Only set if a gateway was configured for this subnet. |
CI_INTERFACE_n_IPV6_NETMASK |
The IPv6 netmask, as a decimal prefix length (e.g. 64). Only set for a static6 subnet. |
You'll find one set of CI_INTERFACE_n_* variables per configured network
interface, n starting at 0.
System¶
Backend choice: system.backend — builtin (default) or none.
- FQDN: written to
/etc/hostnameand/etc/hosts. - Package upgrade: on Debian-based systems, runs
apt-get update && apt-get dist-upgrade -y.
Both are only applied on the first run, per Cloud-Init Data.
These two are applied by separate calls into the backend — -stage=boot
for the FQDN, -stage=final for the package upgrade — since only the
package upgrade needs a working network. See
Running via systemd for why, and for the example units that
invoke cloud-init-pve this way; running with no -stage flag does both
in one call, same as a single combined invocation always did.
Custom backend¶
The script is invoked separately for each half, and only when that half
has something to do — once with CI_FQDN on the first run (if fqdn is
set), and once with CI_PACKAGE_UPGRADE=true when the package upgrade
hasn't run yet (if package_upgrade is set) — each time with:
| Variable | Description |
|---|---|
CI_BACKEND |
system |
CI_FQDN |
The FQDN to apply (cloud-init's fqdn field). Only set on the FQDN invocation. |
CI_PACKAGE_UPGRADE |
Always true. Only set on the package-upgrade invocation. |
User¶
Backend choice: user.backend — builtin (default) or none.
Checks whether the target user (the cloud-init user field, or
user.default-user from the config file) exists, creating it with
useradd if not. If the username/UID changes between runs, the previous
user is not removed.
If the password changed since the last run, it's updated via chpasswd.
If the SSH authorized keys changed since the last run, the new entries are
appended to the user's authorized_keys. A key already present is never
added again, even under a different comment — only its type and
base64-encoded material are compared, so ssh-ed25519 AAAA... alice@laptop
and ssh-ed25519 AAAA... alice@desktop count as the same key.
Custom backend¶
| Variable | Description |
|---|---|
CI_BACKEND |
user |
CI_USER |
The target username (the cloud-init user field, or the template's default user). |
CI_PASSWORD |
The already-hashed (crypt) password, as Proxmox VE writes it — see Cloud-Init Data. |
CI_SSH_AUTHORIZED_KEYS |
Newline-separated list of authorized keys. |