Cloud-init, custom images, and one-click apps solve the same broad problem in different ways: turning a new virtual machine into a usable environment.
Use cloud-init when each server needs configuration at first boot. Use a custom image when many servers need the same tested baseline. Use a one-click app when deployment speed matters more than controlling every installation decision. Most production teams eventually combine these approaches instead of relying on only one.
The right provisioning model affects deployment speed, consistency, security patching, rollback, and how much configuration your team must maintain.
Cloud-init vs custom images vs one-click apps: quick answer
| Model | Best for | Main advantage | Main trade-off |
|---|---|---|---|
| Cloud-init | Dynamic first-boot configuration | Flexible and easy to version | Boot-time failures and longer provisioning |
| Custom image | Repeated identical baselines | Fast, consistent deployments | Image maintenance and rebuild discipline |
| One-click app | Fast evaluation and common stacks | Minimal setup effort | Less control and more opinionated defaults |
| Hybrid model | Production fleets and multiple environments | Speed plus environment-specific configuration | More components to maintain |
A practical decision rule is:
- Choose cloud-init when values differ by environment or instance.
- Choose a custom image when software changes less often than servers are created.
- Choose a one-click app when you want a supported starting point and can accept its defaults.
- Choose a hybrid model when you need both a hardened baseline and deployment-time customization.
What VM provisioning includes
VM provisioning is more than creating a server record. A usable environment may require:
- operating-system selection
- users and SSH keys
- package installation
- security updates
- firewall rules
- application dependencies
- configuration files
- service startup
- monitoring agents
- log rotation
- backup configuration
- application deployment
The provisioning model decides which of these actions happen before the VM exists, during its first boot, or after it joins the environment.
A useful way to separate responsibilities is:
Image layer ↓ operating system and stable baseline First-boot layer ↓ instance-specific configuration Configuration layer ↓ ongoing state and updates Deployment layer ↓ application releases
Trying to force every responsibility into one layer usually creates fragile automation.
Cloud-init: configuration at first boot
Cloud-init is an initialization system used by many Linux cloud images. It reads instance metadata and user-provided configuration, then performs tasks during the early boot process.
Common cloud-init tasks include:
- creating users
- adding SSH keys
- installing packages
- writing files
- setting hostnames
- running commands
- configuring storage or networking where supported
A simple configuration may look 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/app.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 data sources available depend on the operating-system image and cloud platform.
What cloud-init is good at
Cloud-init is strongest when configuration must be decided at launch time.
Examples include:
- assigning an environment-specific hostname
- adding deployment SSH keys
- selecting a package repository
- registering the VM with monitoring
- writing environment-specific configuration
- attaching the instance to a deployment workflow
- installing a small set of current packages
Because the configuration is text, it can be stored in version control, reviewed, tested, and generated through automation.
Cloud-init limitations
It is primarily a first-boot tool
Cloud-init is not a complete long-term configuration-management system.
It can prepare a server, but ongoing changes may be better handled by:
- Ansible
- Salt
- Puppet
- Chef
- deployment pipelines
- container images
- application-specific management tools
Using cloud-init for every future change can make state difficult to understand.
Provisioning time grows with the script
Downloading packages, compiling dependencies, and configuring large application stacks during boot can delay readiness.
A new VM should not appear healthy until cloud-init and the required services complete successfully.
External dependencies can fail
First-boot configuration may depend on:
- package mirrors
- Git repositories
- DNS
- secret stores
- external APIs
- license servers
A temporary failure can leave the VM partially configured.
Debugging is different from interactive setup
Cloud-init runs early and non-interactively. Commands that work in a shell may fail because of environment variables, network timing, missing paths, package locks, or service startup order.
Common diagnostic locations include:
/var/log/cloud-init.log /var/log/cloud-init-output.log
The exact locations may vary by distribution.
Cloud-init best practices
Keep first-boot logic small
Use cloud-init for bootstrap tasks rather than an entire platform installation when possible.
A strong pattern is:
- configure identity and access
- install a small bootstrap dependency
- retrieve a versioned configuration or artifact
- start the next automation layer
Make tasks idempotent
A task is idempotent when running it again does not create duplicate or conflicting state.
For example, prefer commands that check whether a file, package, user, or service already exists.
Do not place long-lived secrets directly in reusable files
User-data may be visible in platform metadata, logs, automation history, or support workflows depending on the environment.
Prefer short-lived credentials, secret-store retrieval, or post-provisioning injection with appropriate access controls.
Validate syntax before deployment
YAML indentation errors and shell quoting mistakes can break a complete launch.
Test cloud-init configurations on disposable VMs before production use.
Define readiness separately from VM power state
A running VM is not necessarily a configured VM.
Use a health check, completion marker, or deployment status that confirms the required services are ready.
Custom images: a prebuilt server baseline
A custom image is a reusable machine image created from a prepared system or through an image-building pipeline.
The image can contain:
- operating-system updates
- standard users and packages
- monitoring agents
- security configuration
- language runtimes
- container runtime
- application dependencies
- approved baseline settings
New VMs begin from that baseline instead of repeating every installation step at boot.
What custom images are good at
Custom images fit workloads where the same server baseline is created repeatedly.
Examples include:
- autoscaled application nodes
- CI/CD runners
- standardized development environments
- worker fleets
- security-hardened server baselines
- managed-service customer templates
The primary benefit is consistency. Every node begins from the same tested artifact.
Custom images can also reduce deployment time because package installation and large dependency setup happen during image creation rather than during every VM boot.
Custom-image limitations
Images become stale
An image contains the software versions and security state from the moment it was built.
Without a rebuild schedule, new VMs may start with outdated packages and known vulnerabilities.
Changes require a new version
Treat images as immutable artifacts. Instead of modifying one image in place, build and test a new version.
A simple naming model may be:
web-base-2026-07-01 web-base-2026-07-15 web-base-2026-08-01
Keep enough history for rollback, but remove obsolete images according to a retention policy.
Hidden machine identity can be cloned
A server copied directly into an image may contain identity and state that should not be duplicated.
Examples include:
- SSH host keys
- machine IDs
- cloud-init instance state
- temporary credentials
- shell history
- logs
- DHCP leases
- application tokens
- monitoring-agent identity
Image preparation must remove or regenerate machine-specific data.
Custom-image hygiene checklist
Before capturing or finalizing an image, review:
- Secrets — remove API keys, passwords, private certificates, tokens, and environment files.
- SSH host keys — regenerate on first boot where appropriate.
- Machine identity — clear values such as
/etc/machine-idaccording to the distribution’s supported process. - Cloud-init state — clean previous instance data if the image will run cloud-init again.
- Logs and shell history — remove operational and sensitive history.
- Temporary files — clear package caches and build artifacts that do not belong in the image.
- Network state — remove static addresses or leases that should not be cloned.
- Monitoring identity — ensure every new VM registers as a unique node.
- Updates — apply and test the intended patch level.
- Documentation — record image version, build source, package versions, and intended use.
The cleanup commands differ by operating system. Follow the distribution’s documented image-preparation process rather than deleting identity files blindly.
Build images through a pipeline
Manual image creation is suitable for experiments but becomes difficult to audit at scale.
A stronger production workflow is:
Base OS image ↓ Versioned build script ↓ Security and package installation ↓ Automated tests ↓ Image capture ↓ Staging deployment ↓ Approved production image
Tools such as Packer or custom automation can make image creation repeatable where supported by the platform.
The important outcome is not the tool name. It is having a build definition that can recreate the image without relying on undocumented manual steps.
One-click apps: a prepared application starting point
A one-click app is a platform-provided image or deployment template that includes an operating system and a common application stack.
Depending on platform availability, examples may include:
- Docker
- WordPress
- n8n
- database tools
- control panels
- development stacks
One-click apps reduce initial installation work. They do not remove operational responsibility.
After deployment, the user may still need to manage:
- application updates
- operating-system patches
- backups
- domain and TLS configuration
- admin credentials
- firewall rules
- plugins and extensions
- monitoring
- data migration
What one-click apps are good at
One-click apps work well for:
- evaluation
- prototypes
- internal tools
- common self-hosted software
- teams that want a known initial structure
- users who prefer platform defaults over manual installation
They can also reduce setup errors when the template is actively maintained and documented.
One-click app limitations
The defaults may not match production requirements
A template may choose:
- a specific directory layout
- a container setup
- a database location
- a firewall policy
- an update mechanism
- a default administrator path
Review those choices before placing customer data or production traffic on the system.
Maintenance ownership can be unclear
Understand which parts the platform maintains and which parts you maintain.
A preinstalled application is not automatically a managed application service.
Templates can age
Confirm the application and operating-system versions before deployment. Update them according to the vendor’s supported process.
Migration may still require manual work
A one-click deployment creates a destination. It does not automatically move an existing database, uploads, DNS, plugins, email configuration, or external integrations.
Decision framework
Choose cloud-init when
- server configuration varies by environment
- values must be assigned at launch
- the setup can complete reliably during boot
- the team is comfortable testing and debugging automation
- the base image is already close to the desired state
Avoid putting large, slow, or fragile installation workflows entirely into cloud-init.
Choose custom images when
- many servers need the same baseline
- startup time matters
- consistency is more important than per-instance variation
- the team can maintain a rebuild and patching process
- the image can be tested as an immutable artifact
Do not use custom images as permanent archives of manually modified servers.
Choose one-click apps when
- a common application must be launched quickly
- the platform template matches the intended use
- the team accepts the template’s architecture
- the environment will be reviewed and hardened after deployment
Do not assume one-click means fully managed, automatically backed up, or production-secure.
Use a hybrid model when
A common production pattern is:
- Custom image for the operating-system and security baseline
- Cloud-init for instance identity and environment-specific configuration
- Configuration management for ongoing server state
- CI/CD for application releases
- One-click app only where its maintained template genuinely reduces work
Example:
Hardened base image ↓ Cloud-init adds hostname, SSH keys, monitoring registration ↓ Configuration management applies environment policy ↓ CI/CD deploys application version
This separates stable configuration from values that change per server or per release.
Provisioning and infrastructure as code
Provisioning models and infrastructure as code are related but not identical.
Infrastructure as code may define:
- VM size
- network attachment
- storage
- firewall policy
- load balancer configuration
Cloud-init or an image then prepares the operating system inside the resource.
Read Infrastructure Automation on Raff for the wider workflow across scripts, APIs, and infrastructure tooling.
Provisioning across environments
Development, staging, and production should share a controlled baseline without sharing every secret or capacity decision.
A practical model is:
- same image family
- different environment-specific cloud-init values
- separate credentials
- separate networks
- separate databases
- different VM sizes where justified
Read Dev, Staging, and Production Environments for environment-boundary decisions.
Provisioning and backups solve different problems
A custom image or provisioning script helps recreate a server baseline. It does not protect current application data.
Backups and snapshots may protect:
- databases
- uploads
- application state
- configuration changes
- recovery points
A useful recovery plan combines:
- reproducible infrastructure
- reproducible server configuration
- protected persistent data
- documented restore steps
Read Cloud Server Backup Strategies before treating an image as a backup.
Security responsibilities by model
| Responsibility | Cloud-init | Custom image | One-click app |
|---|---|---|---|
| Patch baseline | Script or base image | Image rebuild | Verify template, then maintain |
| Secret handling | Avoid reusable plaintext | Remove before capture | Rotate defaults and review setup |
| Consistency | Depends on execution | High when versioned | Depends on template version |
| Ongoing updates | Separate process required | Rebuild and replace | User or service owner responsibility |
| Auditability | Strong when versioned | Strong with build pipeline | Depends on template documentation |
No provisioning model removes the need for security ownership.
Testing a provisioning workflow
A provisioning workflow should pass more than a boot test.
Validate:
- user and SSH access
- package installation
- service startup
- firewall rules
- DNS and network access
- storage mounts
- logging
- monitoring registration
- time synchronization
- application health
- reboot behavior
- secret retrieval
- backup configuration
Test repeated creation and deletion, not only one successful VM.
For custom images, test the image after a clean launch. For cloud-init, test both successful execution and failure recovery. For one-click apps, review the initial credentials, exposed ports, and update path.
Observability and failure handling
Provisioning failures should be visible to operators.
Track:
- creation request
- VM power state
- cloud-init completion
- application health
- image version
- configuration version
- deployment version
Do not route production traffic to a node merely because the VM exists.
A load balancer health check or deployment gate should confirm that the intended service is ready.
How this applies on Raff
Raff provides Linux VMs, snapshots, APIs, and application-oriented product paths that can support different provisioning workflows.
The exact availability and behavior of cloud-init user data, custom-image creation, snapshot-based reuse, and one-click applications should be confirmed in the current Raff dashboard and product documentation before designing automation around them.
A safe Raff planning approach is:
- use a current Linux image as the starting baseline
- use first-boot automation only when the dashboard and selected image support it
- use snapshots for recovery according to their documented behavior
- treat a reusable custom-image workflow as available only after confirming the platform operation
- review current application templates instead of relying on an older
/products/raff-appsassumption - use the live pricing page for current VM and storage costs
This prevents a guide from promising a provisioning feature that may differ by product, image, or current platform release.
Common mistakes
Installing everything during first boot
Large installation scripts increase launch time and failure risk.
Capturing secrets inside an image
Every VM created from that image may inherit the same credentials.
Treating snapshots and images as interchangeable
A snapshot may be designed primarily for recovery, while a reusable image is designed for clean repeated deployment. Confirm platform behavior.
Never rebuilding images
An old image can recreate old vulnerabilities at high speed.
Assuming a one-click app is managed
Preinstalled software still requires patching, backups, monitoring, and secure configuration unless the product explicitly includes management.
Mixing application releases into the base image unnecessarily
If the application changes daily but the operating-system baseline changes monthly, separate those release cycles.
Ignoring provisioning failure states
A powered-on VM can still be incomplete or unsafe to receive traffic.
Provisioning checklist
Before choosing a model, answer:
- Which settings are stable across every server?
- Which values change per instance or environment?
- How quickly must a replacement node become ready?
- Who rebuilds and patches the image?
- Where are secrets retrieved?
- How is provisioning tested?
- What indicates successful completion?
- How are failed nodes removed or retried?
- Which data must survive server replacement?
- Does the current platform support the required workflow?
Conclusion
Cloud-init, custom images, and one-click apps are not competing versions of the same feature. They move configuration work to different stages.
Cloud-init is best for dynamic first-boot values. Custom images are best for consistent, frequently reused baselines. One-click apps are best for fast deployment of common stacks when their defaults fit the workload.
For production systems, a hybrid approach is often the most maintainable: build a tested baseline, keep instance-specific configuration small, manage ongoing changes separately, and protect persistent data with a real backup strategy.