Cloud-init automatically configures a VPS during its very first boot — creating users, installing packages, running scripts — without requiring you to log in and configure it manually. Most major VPS providers support it natively.
What Cloud-Init Solves
Instead of provisioning a VPS and then manually running through your setup checklist, cloud-init lets you define that entire process as a single configuration file, applied automatically the moment the VPS boots for the first time.
Providing Cloud-Init Data
Most VPS providers offer a "User Data" field during instance creation in their control panel or API — this is where you paste your cloud-init configuration.
Basic Cloud-Init Example
#cloud-config
users:
- name: deploy
groups: sudo
shell: /bin/bash
sudo: ['ALL=(ALL) NOPASSWD:ALL']
ssh_authorized_keys:
- ssh-ed25519 AAAA...your-public-key...
package_update: true
package_upgrade: true
packages:
- nginx
- ufw
- fail2ban
runcmd:
- ufw allow OpenSSH
- ufw allow 'Nginx Full'
- ufw --force enable
- systemctl enable --now fail2ban
- systemctl enable --now nginx
Understanding the Structure
| Section | Purpose |
|---|---|
| users | Create user accounts, set SSH keys, sudo access |
| package_update / package_upgrade | Update package lists and installed packages |
| packages | List of packages to install |
| runcmd | Arbitrary shell commands run once, at first boot |
| write_files | Create files with specific content |
Writing Configuration Files via Cloud-Init
write_files:
- path: /etc/motd
content: |
Welcome to this server.
Managed by cloud-init.
owner: root:root
permissions: '0644'
Disabling Password Authentication from the Start
#cloud-config
ssh_pwauth: false
Setting the Hostname
#cloud-config
hostname: web-server-1
fqdn: web-server-1.yourdomain.com
Combining with a More Complete Hardening Script
runcmd:
- sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
- sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
- systemctl restart ssh
- ufw allow 2222/tcp
- ufw --force enable
This effectively automates much of How to Harden a Fresh Linux VPS in 15 Minutes to run automatically at first boot, with zero manual steps.
Testing Cloud-Init Configuration
After the VPS boots, verify cloud-init actually ran successfully:
sudo cloud-init status
sudo cat /var/log/cloud-init-output.log
Reusing Cloud-Init Configs Across Multiple Servers
Store your cloud-init YAML files in version control, parameterizing anything server-specific (hostname, SSH keys) so the same base template can provision consistent servers repeatedly — a lightweight complement to, or starting point before adopting, full infrastructure-as-code tools like Terraform.
Common Errors
Cloud-init configuration has no effect — verify the exact syntax, especially YAML indentation (which is strict), and confirm the provider actually passed your data as cloud-init user-data rather than a different mechanism.
SSH key doesn't work after boot — verify no formatting issues in the pasted public key, and that it's the full single-line key, not accidentally wrapped across multiple lines.
Best Practices
- Test your cloud-init configuration on a throwaway VPS before using it for production provisioning
- Version control your cloud-init templates alongside other infrastructure code
- Combine with Terraform for a complete, reproducible provisioning + configuration pipeline
Continue Reading
- How to Harden a Fresh Linux VPS in 15 Minutes
- Infrastructure as Code Basics: Managing VPS Config with Terraform
- How to Version Control Your Server Configuration
Browse more articles in DevOps & CI/CD.
