Cloud-init, custom images, and one-click apps are three ways to turn a new virtual machine into a usable server, but they move provisioning work to different stages of the VM lifecycle.
Use cloud-init when configuration must be decided at first boot. Use a custom image when many VMs should start from the same tested baseline. Use a one-click app when a prepared application template saves more time than controlling every installation decision. Production teams often combine these models instead of choosing only one.
For Raff Technologies workloads, the provisioning model affects replacement speed, configuration drift, patching, security, recovery, and how confidently a team can recreate a server after failure.
A useful rule is:
Put slow-changing common state in the image, instance-specific state in first-boot automation, ongoing host policy in configuration management, and application releases in CI/CD.
Cloud-init vs custom images vs one-click apps: quick comparison
| Model | Best fit | Main strength | Main trade-off |
|---|---|---|---|
| Cloud-init | Instance-specific first-boot configuration | Flexible launch-time values | Boot-time dependencies and failure risk |
| Custom image | Repeated stable VM baselines | Fast, consistent starting state | Rebuild, patching, and image hygiene |
| One-click app | Common applications and stacks | Fastest path to a usable starting point | Opinionated defaults and less installation control |
| Hybrid | Production fleets and repeatable environments | Separates stable and dynamic state | More than one lifecycle to maintain |
Choose cloud-init when configuration differs by instance or environment.
Choose a custom image when the same operating-system, runtime, security, or dependency baseline will be reused many times.
Choose a one-click app when a maintained template closely matches the workload and the team accepts its defaults.
Choose a hybrid model when the baseline, instance identity, host configuration, and application release change at different speeds.
What is VM provisioning?
VM provisioning is the workflow that turns a newly created virtual machine into a server that is ready for its intended role.
Creating the VM is only the first step. A complete provisioning workflow may also establish:
- operating-system image;
- users and SSH access;
- hostname and machine identity;
- security updates;
- packages and runtimes;
- firewall rules;
- network attachment;
- application dependencies;
- configuration files;
- monitoring and logging;
- application deployment;
- readiness checks;
- recovery configuration.
A useful lifecycle is:
VM creation ↓ Base image ↓ First-boot bootstrap ↓ Host configuration ↓ Application deployment ↓ Readiness verification ↓ Production traffic
The strongest server-provisioning workflows make each stage observable. A VM being powered on should not automatically mean it is ready for users.
A provisioning workflow should separate stable and changing state
Different parts of a server change at different rates.
| Layer | Typical responsibility | Change rate |
|---|---|---|
| Base image | OS, common packages, stable security baseline | Slow |
| First boot | Hostname, SSH keys, registration, environment values | Per VM |
| Host configuration | Ongoing packages, policy, agents | Periodic |
| Application deployment | Application version | Frequent |
| Persistent data | Database, uploads, business state | Continuous |
Trying to put every responsibility into one layer creates coupling.
For example, rebuilding an entire machine image for every application release may be unnecessary when the application changes daily and the operating-system baseline changes monthly. Conversely, installing a large runtime and dozens of packages on every first boot can make replacement slow and fragile when those components rarely change.
The provisioning model should match the lifecycle of the state it owns.
Cloud-init handles first-boot configuration
Cloud-init is a Linux initialization system widely used by cloud images. It reads instance metadata and user data, then performs supported initialization tasks during boot.
Typical cloud-init tasks include:
- creating users;
- adding SSH keys;
- setting hostnames;
- installing packages;
- writing configuration files;
- running bootstrap commands;
- configuring supported storage or networking;
- registering the VM with another system.
A small example looks like this:
#cloud-config package_update: true packages: - nginx - git users: - name: deploy groups: sudo shell: /bin/bash sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: - ssh-ed25519 AAAA...example write_files: - path: /etc/nginx/conf.d/health.conf permissions: '0644' content: | server { listen 80; server_name _; location /health { return 200 'ok'; } } runcmd: - nginx -t - systemctl enable --now nginx
The exact modules and metadata sources available depend on the image and cloud platform.
When cloud-init is the right choice
Cloud-init works best when configuration becomes known at launch time.
Examples include:
- per-instance hostname;
- deployment SSH key;
- environment identifier;
- monitoring registration;
- a small package set;
- bootstrap configuration;
- a pointer to a versioned deployment artifact;
- registration with a configuration-management system.
Because cloud-init configuration is text, it can be versioned, reviewed, generated, and tested alongside infrastructure automation.
It is especially useful when two VMs share the same base image but need different identities or environment-specific values.
Cloud-init should not become the entire deployment platform
Cloud-init is primarily a bootstrap layer, not a complete ongoing configuration-management system.
A large first-boot script can depend on:
- package mirrors;
- DNS;
- Git repositories;
- external APIs;
- secret stores;
- license servers;
- container registries.
Every dependency creates another way for the server to become partially configured.
Prefer a small bootstrap that establishes a known first state and then hands responsibility to the next layer.
A practical sequence is:
- establish identity and access;
- install or enable the minimum bootstrap dependencies;
- retrieve a versioned configuration or artifact;
- register the machine with monitoring/configuration systems;
- expose a readiness signal only after required services succeed.
Use Ansible, another configuration-management system, a deployment pipeline, containers, or application-specific tooling for ongoing changes when those are better fits.
Make first-boot automation idempotent and observable
An idempotent task can be run again without creating duplicate or conflicting state.
For example:
- create a user only if it does not exist;
- install a package only when required;
- replace a configuration file deterministically;
- enable a service rather than starting duplicate processes;
- validate configuration before restart.
Cloud-init failures should also be visible.
Common Linux diagnostic files include:
/var/log/cloud-init.log /var/log/cloud-init-output.log
Exact locations can vary by distribution.
Track provisioning completion separately from VM power state. A deployment gate or health check should confirm that the server is actually ready.
Keep secrets out of reusable cloud-init data
Do not treat user data as a permanent secret store.
Depending on the platform and workflow, bootstrap data may appear in metadata, logs, automation history, support workflows, or copied configuration.
Prefer:
- short-lived credentials;
- secret retrieval after identity is established;
- scoped tokens;
- deployment-time injection;
- rotation after bootstrap when appropriate.
Avoid placing reusable production passwords, private keys, or long-lived API credentials directly into templates that may be copied across servers.
Custom images provide a reusable VM baseline
A custom image is a prepared machine image that can be used as the starting point for new VMs.
A custom image may contain:
- operating-system updates;
- approved packages;
- language runtimes;
- container runtime;
- monitoring agents;
- standard service definitions;
- security configuration;
- common application dependencies.
Instead of downloading and configuring all of that during every boot, the VM starts from an artifact that has already been built and tested.
This makes custom images useful for:
- application fleets;
- worker nodes;
- CI/CD runners;
- standardized developer environments;
- replacement servers;
- hardened baselines;
- repeatable MSP/customer templates.
Custom images trade boot work for image lifecycle work
A custom image can make server provisioning faster and more consistent, but the work does not disappear. It moves into the image pipeline.
An image needs:
- a reproducible build definition;
- patching policy;
- version identifier;
- automated or repeatable tests;
- retirement policy;
- rollback history where appropriate.
Treat images as immutable artifacts. Build a new version instead of manually modifying an old image and continuing to use the same identity.
For example:
web-base-2026-08-15 web-base-2026-09-01 web-base-2026-09-12
A reproducible image pipeline can look like:
Current base OS ↓ Versioned build definition ↓ Packages + hardening ↓ Automated validation ↓ Reusable image ↓ Staging VM ↓ Approved production baseline
The tool can be Packer, scripts, API automation, or another build system. The important requirement is that the image can be recreated without undocumented manual changes.
Custom-image hygiene prevents cloned identity and secrets
Capturing a running server without preparation can clone state that should be unique.
Before finalizing a reusable image, review:
- Secrets — remove API keys, passwords, private certificates, tokens, and environment files that should not be cloned.
- SSH host keys — regenerate per machine where the OS workflow requires it.
- Machine identity — clear or regenerate machine-specific identifiers through the supported OS process.
- Cloud-init state — clean prior instance state if cloud-init should run on the next VM.
- Logs and shell history — remove operational or sensitive history that does not belong in the artifact.
- Network state — remove static addresses, leases, or configuration that should not be duplicated.
- Monitoring identity — make sure every new VM registers as a distinct node.
- Temporary build files — remove caches and artifacts not needed at runtime.
- Patch state — record and test the intended software baseline.
- Image metadata — document version, build source, intended workload, and retirement criteria.
Do not delete identity files blindly. Use the distribution's documented image-preparation process.
Rebuild custom images instead of patching them forever
An image captures the software state from the time it was built.
If the image is never rebuilt, every new VM can recreate old vulnerabilities and obsolete packages very efficiently.
A mature workflow therefore decides:
- what event triggers a rebuild;
- how security updates are incorporated;
- how the image is tested;
- how old versions are retired;
- how quickly a new baseline can replace an affected image.
Rebuild cadence should follow operational risk and the software lifecycle rather than an arbitrary calendar rule.
One-click apps are prepared starting points
A one-click app is a provider-maintained image or deployment template that starts with a common application or stack already prepared.
Typical categories can include:
- CMS platforms;
- automation tools;
- developer stacks;
- container platforms;
- control panels;
- self-hosted applications.
One-click apps reduce initial installation work, but preinstalled does not mean fully managed.
The user may still own:
- OS updates;
- application updates;
- credentials;
- domain and TLS configuration;
- firewall policy;
- backups;
- monitoring;
- plugins/extensions;
- migration;
- application security.
Use one-click apps when the template's architecture matches the workload well enough that maintaining a separate installation process does not create meaningful value.
Review one-click templates before production use
A template may make decisions about:
- directory layout;
- containers;
- database placement;
- exposed ports;
- administrative access;
- update behavior;
- persistence;
- TLS setup.
Review those assumptions before placing customer data or production traffic on the instance.
Also verify the application and operating-system version. A fast deployment is useful only if the resulting stack is current and maintainable.
Cloud-init vs custom image: use lifecycle, not ideology
The choice becomes clearer when you classify state by how often it changes.
| Requirement | Cloud-init | Custom image |
|---|---|---|
| Per-instance hostname | Strong fit | Poor fit |
| Per-instance SSH access | Strong fit | Avoid embedding personal keys |
| Large stable runtime | Possible but slow | Strong fit |
| Security baseline | Possible | Strong fit when rebuilt/tested |
| Dynamic environment values | Strong fit | Poor fit |
| Fast replacement | Depends on boot work | Strong fit |
| Ongoing application release | Weak fit | Usually separate from both |
The hybrid pattern is often strongest:
Reusable image ↓ stable OS/runtime/security baseline Cloud-init ↓ identity + environment-specific bootstrap Configuration management ↓ ongoing host policy CI/CD ↓ application version
This keeps each release cycle independent.
Snapshot vs custom image: they solve different problems
A snapshot is primarily a point-in-time recovery mechanism. A reusable custom image is prepared for clean repeated provisioning.
A snapshot may contain:
- current machine identity;
- current application state;
- logs;
- temporary files;
- credentials;
- workload-specific data.
Those qualities can be desirable for recovery and undesirable for a reusable baseline.
Do not assume that a recovery snapshot should be promoted directly into a long-lived server template without image hygiene and validation.
Use Cloud Snapshots vs Backups for the recovery distinction.
Provisioning and infrastructure as code are separate layers
Infrastructure as code may define:
- VM size;
- operating-system or image selection;
- network attachment;
- storage;
- firewall policy;
- API-driven resource creation.
Cloud-init or the image then configures the operating system inside the resource.
CI/CD may deploy the application after that.
Keeping those layers separate makes failures easier to diagnose:
Infrastructure creation failed? → resource/IaC layer VM exists but host is incomplete? → image/bootstrap/configuration layer Host is healthy but app is broken? → deployment/application layer
Read Infrastructure Automation on Raff for the broader automation model.
Provisioning across development, staging, and production
Development, staging, and production can share a controlled baseline without sharing every credential or capacity decision.
A useful pattern is:
- same approved image family;
- separate environment-specific bootstrap values;
- separate credentials;
- separate databases;
- separate network rules;
- different VM sizes where justified;
- separate deployment approvals.
This reduces environment drift while preserving the boundaries production needs.
Read Staging vs Production vs Development Environments for the environment model.
Provisioning should support replacement, not only creation
The real test of a provisioning workflow is whether the team can replace a server reliably.
A replacement test should answer:
- Can a new VM be created from the intended image?
- Does bootstrap complete without manual intervention?
- Are unique identity and credentials generated correctly?
- Does the server join the expected private network?
- Do monitoring and logging identify it as a new instance?
- Can the application deploy successfully?
- Does the readiness check pass?
- Can traffic be moved to the replacement safely?
- Can the old VM be removed without losing persistent data?
If replacement requires remembering undocumented shell commands, provisioning is not yet reproducible.
Scaling makes provisioning quality more important
A single manually maintained VM can hide inconsistent setup for a long time. Multi-node or autoscaled architectures expose it quickly.
When application nodes are expected to be interchangeable, every replacement should receive the same baseline and become ready through the same observable workflow.
Do not scale a provisioning script that is already unreliable. First make server creation deterministic, move persistent state out of disposable nodes where appropriate, and define readiness.
Use Cloud Autoscaling for VMs and Stateful vs Stateless Applications when the provisioning model will support several replaceable backends.
Security responsibilities differ by provisioning model
| Responsibility | Cloud-init | Custom image | One-click app |
|---|---|---|---|
| Baseline patching | Base image + bootstrap | Image rebuild | Verify template, then maintain |
| Secret handling | Avoid reusable plaintext | Remove before capture | Rotate/review initial credentials |
| Consistency | Depends on execution | High when versioned | Depends on template maintenance |
| Ongoing changes | Separate process | Rebuild or config management | User/service-owner responsibility |
| Failure evidence | Bootstrap logs/status | Image/version inventory | Template + application health |
No provisioning model removes security ownership.
How VM provisioning fits Raff today
Raff VM and Linux VM provide the compute layer for repeatable server workflows. Raff's automation surface includes API-driven provisioning and cloud-init-based bootstrap workflows, while the VM platform also supports current system images and custom-image workflows.
A practical Raff provisioning design can look like:
Raff VM / Linux VM ↓ Current OS or custom image ↓ Cloud-init bootstrap ↓ Host configuration ↓ CI/CD application release ↓ Readiness check
For internal application traffic, attach the required resources to Raff VPC. VPC traffic is private and unmetered, and VPC itself has no separate VPC charge.
Use Data Protection for snapshots and automated backup recovery. Recovery copies are separate from a clean reusable image: their job is to protect recoverable state, not to define the server-provisioning baseline.
For prebuilt application starting points, review the current Raff Marketplace and App Platform options. Treat a prepared application as managed only when the product explicitly includes that operational responsibility.
Raff's current image catalog includes supported Linux distributions such as Ubuntu 24.04, Debian 13, Rocky Linux 9, AlmaLinux 9, CentOS Stream 9, Alpine 3.21, Fedora 42, and openSUSE 15, alongside FreeBSD 14 and custom-image options. Use the current dashboard when the exact available image version matters to automation.