Skip to main content

Using Secrets Manager with Cloud-Init

NetActuate Secrets Manager integrates with cloud-init to inject secret values into VM configuration at build time. Secrets are resolved server-side — the plaintext value is never stored in the API request, job queue, or build logs.

How It Works

Store sensitive values in Secrets Manager. Reference them in your cloud-init YAML using template syntax. When you submit a build request, NetActuate resolves all secret references before passing the script to the VM.

Step 1: Create a Secret

Create secrets via Platform > Secrets in the portal, or via the API:

curl -X POST https://vapi2.netactuate.com/api/secrets/lists/{secretList}/values \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"secret_key": "DB_PASSWORD",
"secret_value": "s3cur3-p4ssw0rd"
}'

Secret keys must be unique across all secret lists in your account.

Step 2: Reference Secrets in Cloud-Init

Use the template syntax in your cloud-init YAML:

#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

The syntax is ${{secret.KEY_NAME}} — double curly braces with a dot separator. The key name is case-sensitive and must match exactly what you stored in Secrets Manager.

Note: Secret references only work inside script_content. They are not resolved in other API parameters.

Step 3: Build the VM

Base64-encode the cloud-init YAML and submit the build request:

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": "app01.example.com",
"ssh_key_id": 88,
"script_type": "cloud-init",
"script_content": "'"$SCRIPT"'"
}'

NetActuate resolves all secret references before sending the script to the hypervisor.

Security Model

  • Secret values are never stored in the API request payload
  • Substitution happens on NetActuate infrastructure before VM delivery
  • The resolved script is passed directly to the hypervisor
  • Secret values do not appear in build logs or job queues

Using with Ansible

- name: Provision VM with secrets in 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('template', 'cloud-init.yaml.j2') | b64encode }}"
state: present

The cloud-init template can contain secret references — NetActuate resolves them, not Ansible.

Need Help?

If you need assistance, visit our support page.