
Decide which Linux configuration belongs in a reusable image and which belongs in cloud-init, with first-boot stages, schema checks, security boundaries, and release tests.
September 24, 2026
Bake shared, expensive, and security-sensitive state into the image. Keep identity and small site-specific values in cloud-init. Test both the reusable artifact and a launched instance.
cloud-init is first-boot configuration management for an image that already exists. Its current project documentation describes initialization of networking, storage, SSH keys, packages, and other instance state across public cloud, private cloud, and bare-metal provisioning systems. That breadth does not turn it into an installer or an image compiler.
| Configuration | Preferred phase | Reason |
|---|---|---|
| Kernel, bootloader, filesystem | Image build | They must exist before cloud-init can run. |
| Large package sets | Image build | Avoid repeating downloads and package failure on every launch. |
| Security baseline | Image build | Scan and test one reviewed artifact before release. |
| Hostname and instance identity | cloud-init | Values differ for each launched instance. |
| SSH authorized keys | cloud-init | The platform can inject the operator or workload identity. |
| Small site-specific files | cloud-init | They bind a reusable image to one region, role, or environment. |
#cloud-config
hostname: edge-01
ssh_pwauth: false
users:
- default
- name: ops
groups: [adm, sudo]
lock_passwd: true
ssh_authorized_keys:
- "ssh-ed25519 AAAA... operator@example"
package_update: true
packages:
- prometheus-node-exporter
write_files:
- path: /etc/openfactory/site.conf
permissions: "0644"
content: |
region=eu-central
runcmd:
- [systemctl, enable, --now, prometheus-node-exporter]
final_message: "cloud-init finished after $UPTIME seconds"The first line must identify cloud-config. Do not place plain-text credentials in user data. Platform metadata services and serial output can expose more than an application owner expects, and a copied launch template can spread one credential across a fleet. Inject public keys and retrieve runtime secrets through the platform's approved secret path.
The official user-data validation guide provides a static schema command:
cloud-init schema -c cloud-config.yml --annotateAfter launch, wait with cloud-init status --wait. Then read the status result and logs before running machine checks. A reachable SSH port can coexist with unfinished final-stage package work, so an early probe can produce a false failure or accept a partially configured host.
This split keeps a failed instance customization from hiding a broken image, and keeps a good image from masking a bad cloud-config file. OpenFactory fits on the reusable side by building and booting the Linux artifact before it receives site-specific launch data.
No. cloud-init runs inside an existing image. It discovers a data source and applies instance configuration during boot stages.
Small, instance-specific additions can fit. Large or release-critical package sets are usually better in the image so they are downloaded, scanned, and tested once before launch.
Run cloud-init schema against the file, then launch a disposable instance and wait for cloud-init status. Static validation cannot prove repository, network, or command behavior.
Compare first-boot configuration with Autoinstall, Preseed, and Kickstart.
See how an installer document differs from ordinary cloud-config.
Compare two image build workflows before adding instance data.
Build and test the reusable layer for fleets, labs, and cloud targets.
OpenFactory's free flow is for browsing. Persistent VMs, SSH access, snapshots, your own ISO, and fleet deployment live on a paid plan.