Back to articles
Technology Insight

Mastering Cloud-init: The Definitive Guide to Automating 100 Identical VPS Deployments from Scratch

June 2, 2026

Introduction: The Scale Dilemma in Modern Infrastructure

In the era of cloud computing, agility and consistency are the cornerstones of effective infrastructure management. Imagine a scenario where your organization needs to deploy 100 Virtual Private Servers (VPS) across a cloud provider to support a distributed microservices architecture, a massive scraping cluster, or a localized Content Delivery Network (CDN). Manually configuring these instances—installing packages, setting up user permissions, injecting SSH keys, and configuring firewalls—is no longer just inefficient; it is a critical business risk prone to human error and configuration drift.

This is where Cloud-init becomes indispensable. As the industry-standard multi-distribution method for cross-platform cloud instance initialization, Cloud-init allows you to define exactly what a server should look like before it even boots for the first time. In this comprehensive guide, we will dive deep into Cloud-init, demonstrating how to automate the provisioning of 100 identical, production-ready VPS instances simultaneously from the very moment of creation.

What is Cloud-init and How Does It Work?

Cloud-init is an open-source initialization EDA (Early Deployment Automation) tool originally developed by Canonical, but now universally supported across almost all major cloud providers, including AWS, DigitalOcean, Linode, Vultr, and Google Cloud Platform. It runs during the initial boot sequence of a Linux operating system image.

When you spin up a new VPS, the cloud provider passes metadata and user-data to the instance. Cloud-init consumes this data—typically written in standard, human-readable YAML format—and executes the specified directives. This happens during the early boot stages, categorized into four main phases:

  • Generator Phase: Cloud-init determines if it should run and identifies the data source (the cloud provider's metadata service).
  • Local Phase: Block devices are found and local networking is configured minimally to fetch external metadata if required.
  • Network Phase: Full networking is brought online, and components like user accounts, SSH keys, and package repositories are configured.
  • Config Phase: Runs arbitrary user-defined scripts, software installations, and final automation tasks.
By leveraging these boot phases, Cloud-init transforms a generic, vanilla OS distribution template into a fully customized, secure, and functional node without requiring any manual intervention.

Anatomy of a Production-Grade Cloud-config File

To deploy 100 identical servers, we must create a master configuration script called a cloud-config file. This file must be syntactically perfect YAML and begin with a specific header: #cloud-config. Below is a production-grade template designed to handle user creation, security hardening, package installation, and automated system updates.

#cloud-config
users:
  - name: deploy_admin
    groups: sudo
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJKb... [email protected]

package_update: true
package_upgrade: true

packages:
  - ufw
  - fail2ban
  - docker.io
  - nginx
  - curl
  - htop

write_files:
  - path: /etc/nginx/sites-available/default
    content: |
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
          root /var/www/html;
          index index.html;
          server_name _;
          location / {
              try_files $uri $uri/ =404;
          }
      }
    owner: root:root
    permissions: '0644'

runcmd:
  - systemctl enable docker
  - systemctl start docker
  - ufw allow 22/tcp
  - ufw allow 80/tcp
  - ufw --force enable
  - echo "

VPS Provisioned via Cloud-init

" > /var/www/html/index.html - systemctl restart nginx

Breaking Down the Directives

Let us analyze the key blocks within this configuration to understand how it ensures uniformity across your fleet:

  1. Users and Security: The users block creates a dedicated administrative user, grants passwordless sudo access (essential for automated automation workflows), and injects a public SSH key, ensuring secure passwordless authentication across all 100 nodes.
  2. Package Management: Setting package_update and package_upgrade to true guarantees that every VPS fetches the latest security patches upon creation. The packages array automatically installs vital dependencies like Docker, Nginx, and security tooling like Fail2ban.
  3. File Customization: The write_files module allows you to inject configuration files directly onto the file system before services start, bypassing the need for configuration management tools for simple setups.
  4. Execution Commands: The runcmd array runs arbitrary shell commands at the very end of the boot process, enabling you to configure firewalls (UFW), enable services, and set up your web roots uniformly.

Scaling to 100 Identical VPS: Execution Strategies

Writing the cloud-config script is only half the battle. To scale this across 100 identical instances, you have three primary architectural choices depending on your current infrastructure maturity level.

Option A: Utilizing Cloud Provider APIs or CLIs

Most modern cloud providers feature powerful Command Line Interfaces (CLIs) or REST APIs. Instead of manually clicking through a web dashboard 100 times, you can execute a simple shell loop that references your cloud-config.yaml file.

For instance, using the DigitalOcean CLI (doctl), a loop to provision multiple servers concurrently looks like this:for i in {1..100}; do doctl compute droplet create "vps-cluster-$i" \ --region sgp1 \ --image ubuntu-24-04-x64 \ --size s-2vcpu-4gb \ --user-data-file ./cloud-config.yaml \ --no-wait done

The --no-wait flag is crucial here; it instructs the API to accept the creation request and move to the next iteration immediately, allowing all 100 servers to spin up in parallel.

Option B: Infrastructure as Code (Terraform / OpenTofu)

For production-grade environments, managing infrastructure via a shell loop lacks state tracking. Terraform provides a highly structured approach to scale your Cloud-init deployments seamlessly. Consider the following declarative Terraform block:

resource "digitalocean_droplet" "vps_cluster" {
  count              = 100
  name               = "vps-node-${count.index + 1}"
  region             = "sgp1"
  size               = "s-2vcpu-4gb"
  image              = "ubuntu-24-04-x64"
  user_data          = file("${path.module}/cloud-config.yaml")
}

Running a single terraform apply command will provision all 100 droplets simultaneously, guaranteeing that each node receives the exact same immutable Cloud-init template.

Testing, Troubleshooting, and Best Practices

Deploying at scale means that a single mistake in your Cloud-init script will replicate 100 times. Follow these structural best practices to mitigate deployment failures:

  • Validate Your YAML: Always pass your script through a validator. You can use the local CLI tool: cloud-init schema --config-file cloud-config.yaml to check for syntax errors before deploying.
  • Inspect Log Files: If a node fails to configure correctly, log into a test instance and inspect /var/log/cloud-init-output.log to view stdout and stderr from your runcmd execution blocks.
  • Keep Scripts Idempotent: Ensure commands inside runcmd can be run multiple times safely without failing or breaking system states.

Conclusion

Cloud-init bridges the gap between raw machine initialization and full-scale configuration management tools like Ansible, Puppet, or Chef. By shifting your initial setup tasks—such as updating repositories, configuring firewalls, setting up users, and installing foundational runtimes like Docker—directly into the boot sequence via Cloud-init, you eliminate manual post-deployment tasks entirely.

Using the techniques outlined in this guide, provisioning 100 identical, secured, and operational VPS instances takes no longer than provisioning a single server. Embrace Cloud-init within your deployment workflows to unlock true infrastructure velocity and consistency.

Mastering Cloud-init: The Definitive Guide to Automating 100 Identical VPS Deployments from Scratch | DPTCloud