Building VMs with Cloud-Init
NetActuate VMs support cloud-init and bash scripts passed at build time via the build API. Use this to bootstrap configuration, install packages, write files, and run commands automatically when a VM first boots — without requiring post-boot SSH access.
How It Works
When you include script_type and script_content in a VM build request, NetActuate passes the script to the VM via the hypervisor at first boot. The script runs before the VM is reachable via SSH.
The script_content parameter must be base64-encoded. The script_type parameter tells the platform how to interpret the content.
Supported Script Types
| script_type value | Format |
|---|---|
cloud-init | Cloud-init YAML (recommended) |
cloud_init | Alias for cloud-init |
user-data | Alias for cloud-init |
user_data | Alias for cloud-init |
bash | Bash shell script |
Note: Not all OS images support cloud-init. Ubuntu 24.04 LTS and most modern Linux images do. Verify your image supports the script type before using this feature.
Cloud-Init Example
Write your cloud-init YAML, then base64-encode it before passing it to the API.
Cloud-init YAML (before encoding):
#cloud-config
packages:
- nginx
- curl
runcmd:
- systemctl enable nginx
- systemctl start nginx
write_files:
- path: /etc/app/config.env
permissions: '0600'
content: |
APP_ENV=production
Encode and build:
SCRIPT=$(base64 < cloud-init.yaml)
curl -X POST https://vapi2.netactuate.com/api/build \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mbpkgid": 1001,
"location": 12,
"image": 203,
"fqdn": "web01.example.com",
"ssh_key_id": 88,
"script_type": "cloud-init",
"script_content": "'"$SCRIPT"'"
}'
Bash Script Example
#!/bin/bash
apt-get update -y
apt-get install -y nginx
systemctl enable nginx
systemctl start nginx
Encode and pass with "script_type": "bash".
Combining with Secrets Manager
Cloud-init content can reference secrets stored in NetActuate Secrets Manager using template syntax. Substitution happens server-side before the script reaches the VM.
#cloud-config
write_files:
- path: /etc/app/config.env
permissions: '0600'
content: |
DB_PASSWORD=${{secret.DB_PASSWORD}}
API_KEY=${{secret.API_KEY}}
runcmd:
- systemctl restart myapp
See Using Secrets Manager with Cloud-Init for the full workflow including creating secrets.
Using Cloud-Init with Ansible
Pass script_content through the netactuate.compute.node module:
- name: Provision VM with cloud-init
netactuate.compute.node:
auth_token: "{{ auth_token }}"
hostname: "{{ inventory_hostname }}"
plan: "{{ plan }}"
location: "{{ location }}"
image: "Ubuntu 24.04 LTS (20240423)"
script_type: "cloud-init"
script_content: "{{ lookup('file', 'cloud-init.yaml') | b64encode }}"
state: present
Using Cloud-Init with Terraform
resource "netactuate_server" "web" {
hostname = "web01"
plan = "VR8x4x50"
location = "LAX"
image = "5787"
ssh_keys = [var.ssh_key_id]
cloud_config = file("cloud-init.yaml")
}
Related Resources
Need Help?
If you need assistance, visit our support page.