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 the standard way a cloud instance configures itself the first time it boots. You give it a block of user data, and the instance creates users, installs packages, writes files and runs commands on its own, with no manual login. Set it once and every fresh boot of the instance, including after a rebuild, arrives already set up.

What you can put in it

User data takes one of two forms, and it must begin with the right first line.

  • A #cloud-config document: YAML that cloud-init understands directly. This is the usual choice. It has to be valid YAML and start with that exact first line.
  • A script: any file beginning with a #! shebang, such as #!/bin/bash. Cloud-init runs it on first boot.

Anything else is rejected. The whole block is limited to 16 KB, which is plenty for setup that hands off to your real configuration management.

A working example

This #cloud-config creates a login user with your key, installs a couple of 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

A shell script works too when you would rather script it:

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

Set it in the portal

Open the instance from Cloud and go to its User Data tab. Paste your #cloud-config or script and save. It is validated as you save, so a broken document is caught then rather than at boot. The user data applies on the next fresh boot; to apply it now to a running instance, rebuild from the same image.

With the API

Reading needs read; writing needs the VMs scope (vms.write). Read what is set, then write 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

Send the document as the user_data field. It is validated on write: a document that does not start with #cloud-config or #! answers 422 with code invalid_format; a #cloud-config that is not valid YAML answers 422 invalid_yaml with the parser's message; over 16 KB answers 422 too_large. Because writing validates, you find out about a mistake before a rebuild does.

Questions we get

  • When does it run? On the instance's first boot, and on the first boot after a rebuild. Editing it does not re-run it on a running instance; rebuild to apply.
  • My config was rejected. Read the code: invalid_format means the first line is wrong, invalid_yaml means the YAML does not parse (the message says where), too_large means over 16 KB.
  • Can I use it to add SSH keys? Yes, with ssh_authorized_keys in a #cloud-config. You can also pass keys directly on a rebuild.
  • Does it work on bare metal? No. Bare-metal servers use post-install scripts on reinstall instead; see install profiles.

Still stuck?

Open a support ticket with the instance and your user data, and we can check how cloud-init consumed 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.