NEW Bare Metal Servers with 20G Dedicated Unmetered Bandwidth 20G Dedicated Unmetered Servers Read more STATUS

Cloud-init: Configure a Cloud Instance on First Boot

Sep 23, 2026 3 min read

Cloud-init is how a cloud instance normally configures itself on its very first boot. You hand it a block of user data, and the instance creates users, installs packages, writes files and runs commands by itself, without anyone logging in. Set it once, and every fresh boot of the instance (a rebuild included) comes up already configured.

What you can put in it

User data comes in one of two forms, and the first line decides which.

  • A #cloud-config document, which is YAML cloud-init reads natively. Most people use this one. It must be valid YAML and open with exactly that line.
  • A script: any file that starts with a #! shebang, like #!/bin/bash. Cloud-init executes it on first boot.

Anything else gets rejected. The block can be up to 16 KB in total. That's plenty when the setup's job is to hand over to your real configuration management.

A working example

This #cloud-config sets up a login user with your key, installs two packages and starts a service:

#cloud-config
users:
  - name: deploy
    groups: [sudo]
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... you@example.com

package_update: true
packages:
  - nginx
  - ufw

runcmd:
  - ufw allow OpenSSH
  - ufw allow 'Nginx Full'
  - ufw --force enable
  - systemctl enable --now nginx

If you'd rather write a shell script, that works too:

#!/bin/bash
set -euo pipefail
apt-get update && apt-get install -y nginx
systemctl enable --now nginx

Set it in the portal

Find the instance under Virtual Machines, open it and go to the User Data tab. Paste in your #cloud-config or script and save. Validation happens on save, so you hear about a broken document right away and not at boot. The new user data takes effect on the next fresh boot. To apply it to an instance that's already running, rebuild it from the same image.

With the API

You need read to read it and the VMs scope (vms.write) to write it. Check what's there now, then send your document:

curl -s https://api.amoni.app/v1/vms/990204/411/user-data \
  -H "Authorization: Bearer nr_live_..."
# { "success": true, "data": { "user_data": "#cloud-config\n...", "applied_at": "...", "updated_at": "..." } }
curl -s -X PUT https://api.amoni.app/v1/vms/990204/411/user-data \
  -H "Authorization: Bearer nr_live_..." -H "Content-Type: application/json" \
  --data-binary @cloud-config.yaml   # a JSON body { "user_data": "..." } also works

Put the document in the user_data field. Writes are validated. A document that doesn't start with #cloud-config or #! gets 422 with code invalid_format. A #cloud-config that isn't valid YAML gets 422 invalid_yaml along with the parser's message, and anything over 16 KB gets 422 too_large. Since the write checks it, a mistake reaches you before it reaches a rebuild.

Questions we get

  • When does it run? At the instance's first boot, and again at the first boot after a rebuild. Changing it won't re-run it on an instance that's up. Rebuild to apply it.
  • My config was rejected. Read the code: invalid_format means the first line isn't right, invalid_yaml means the YAML won't parse (the message points to where), too_large means you're over 16 KB.
  • Can I use it to add SSH keys? Yes, with ssh_authorized_keys in a #cloud-config. Or pass keys straight in when you rebuild.
  • Does it work on bare metal? No. On bare metal, the equivalent is a post-install script at reinstall time; see install profiles.

Still stuck?

Open a support ticket with the instance and your user data. We can look at how cloud-init handled it on the last boot.

Built for production

Why teams stay with Netrouting

We connect you to the Internet using network engineers (and not order takers) and hardware and infrastructure that is built to last, so we can pick up where you left off when you need us.

  • Expert-Level Support Our staff is available 24 hours a day, 7 days a week to handle network administration and systems management issues as they occur.
  • Scalable Solutions Build whatever depth or breadth your infrastructure needs and then scale as required.
  • Enhanced Security Enable 2-factor authentication and also limit by IP address from the control panel to secure your account.
  • Cost-Efficient Infrastructure You will always receive the best value from your investment as you will be optimized for budget without any compromise on Quality.