Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.xloud.tech/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Xloud Compute supports automatic execution of customer-supplied scripts at virtual machine launch time and at any later point during the machine’s lifecycle. The mechanism is the industry-standard cloud-init agent on Linux guests and Cloudbase-Init on Windows guests — both consume the same Xloud metadata service so the same launch flow works for every supported OS.
Two capabilities, one mechanism
  1. At provisioning — the hypervisor executes Bash or PowerShell scripts during virtual machine creation to automate system bootstrapping operations (installing packages, configuring services, joining clusters, registering with monitoring, etc).
  2. On provisioned and discovered instances — the same scripting mechanism can be invoked on already-running and previously-imported virtual machines as part of an operational workflow (re-bootstrap, re-key, rotate credentials, patch in place, run a one-off task).
Prerequisites
  • A guest image with cloud-init (Linux) or Cloudbase-Init (Windows) pre-installed. The Xloud public image catalog ships with both.
  • A network or metadata route from the instance to the Xloud metadata service (link-local 169.254.169.254 over the management network is enabled by default).
  • For post-provisioning execution: SSH (Linux) or WinRM (Windows) reachability from the orchestration host, or an attached qemu-guest- agent channel.

Supported Script Formats

The user-data payload is read once by the agent on first boot. The first line of the payload tells the agent how to interpret the rest.
Header lineTreated asRuns on
#!/bin/bash (or #!/bin/sh, #!/usr/bin/env python3, etc.)A shebang scriptLinux (cloud-init)
#cloud-configDeclarative YAML — packages, users, files, run commandsLinux (cloud-init)
#includeFetches a script from a URLLinux (cloud-init)
Content-Type: multipart/mixed (MIME)Multiple payloads in one uploadLinux (cloud-init)
#ps1 or #ps1_sysnativePowerShell scriptWindows (Cloudbase-Init)
#cmdClassic Windows command prompt batchWindows (Cloudbase-Init)
#cloud-configDeclarative YAML (subset supported)Windows (Cloudbase-Init)
When you need to run more than one script type at first boot — for example a #cloud-config to install packages plus a Bash script to run after — wrap them in a MIME multipart payload. The Dashboard accepts the full multipart blob in the User Data box.

Provisioning a VM with a Script

The user-data input lives in the System Config step of the launch wizard, under Advanced Options → User Data, and is mirrored by the --user-data flag on the CLI.
1

Open the launch wizard

Navigate to Compute → Instances and click Create Instance. Complete the Base Config and Network Config steps as normal.
2

Expand Advanced Options

On the System Config step, scroll to the Advanced Options toggle and turn it on. The User Data textarea becomes visible.
3

Paste or upload the script

Paste the script directly into the textarea, or click the upload icon and choose a local .sh, .yaml, .ps1, or .cmd file.
LimitValue
Maximum payload size16 KB (before base64 encoding)
EncodingUTF-8, ASCII safe
Forbidden charactersNone — full Unicode allowed inside the script body
The Dashboard rejects payloads above the limit before submit.
4

Confirm and launch

Continue to Confirm Config, review, and click Confirm. The script begins executing inside the guest as soon as cloud-init or Cloudbase-Init reaches its final stage — typically within 30–90 seconds of the VM going Active.
Cloud-init logs at /var/log/cloud-init.log (Linux) or C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log (Windows) confirm successful execution.

Linux Bootstrap Examples (Bash and cloud-config)

Bash script — install and start nginx

bootstrap.sh
#!/bin/bash
set -euxo pipefail

# Wait for the package manager lock to clear
while pgrep -a apt > /dev/null; do sleep 2; done

apt-get update
apt-get install -y nginx

systemctl enable --now nginx

# Drop a marker file so monitoring can confirm bootstrap completed
echo "$(date -u +%FT%TZ) cloud-init bootstrap complete" > /var/log/xloud-bootstrap.done

cloud-config YAML — declarative bootstrap

cloud-init.yaml
#cloud-config
package_update: true
package_upgrade: true

packages:
  - nginx
  - curl
  - git

users:
  - name: ops
    groups: sudo
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... ops@xloud

write_files:
  - path: /etc/xloud/site.conf
    permissions: "0644"
    content: |
      backend = production
      region  = ap-south-1

runcmd:
  - systemctl enable --now nginx
  - curl -fsSL https://repo.xloud.tech/setup.sh | bash
  - echo "bootstrap-done" > /var/log/xloud-bootstrap.done

final_message: "Xloud bootstrap finished after $UPTIME seconds"
cloud-config is preferred over raw Bash for routine bootstrapping — it is declarative, idempotent, and the packages: and runcmd: keys read straightforwardly in change reviews. Use Bash only when you need imperative control flow (loops, retries, conditional logic).

Windows Bootstrap Examples (PowerShell and cmd)

PowerShell script — install IIS and write a marker

bootstrap.ps1
#ps1_sysnative
$ErrorActionPreference = "Stop"

# Install the Web Server role with management tools
Install-WindowsFeature -Name Web-Server -IncludeManagementTools

# Replace the default page so health checks see the right banner
Set-Content -Path C:\inetpub\wwwroot\index.html `
  -Value "<h1>Xloud-managed IIS host</h1>" -Encoding UTF8

# Disk-level marker the monitoring agent picks up
$now = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
"$now Xloud bootstrap complete" | Out-File C:\xloud-bootstrap.done -Encoding UTF8
#ps1_sysnative runs the script through the native 64-bit PowerShell on 64-bit Windows guests, avoiding the 32-bit WoW64 redirector. Use #ps1 if you specifically need the 32-bit engine.

Classic command prompt — register the VM with internal DNS

bootstrap.cmd
#cmd
@echo off
nslookup %COMPUTERNAME%.corp.local
nltest /dsregdns
echo Xloud bootstrap complete > C:\xloud-bootstrap.done

cloud-config on Windows — restricted subset

cloud-init.yaml
#cloud-config
users:
  - name: admin
    passwd: ChangeMeAtFirstLogin!
    groups: Administrators

set_hostname: web-01.corp.local

runcmd:
  - powershell -Command "Install-WindowsFeature Web-Server"
Not all cloud-config keys are honored by Cloudbase-Init. users, set_hostname, runcmd, and write_files are well supported. apt-specific keys, systemd unit management, and Linux-only modules are ignored. Test your YAML on a throwaway VM before rolling it out to a production fleet.

Running Scripts on Provisioned or Discovered Instances

For operational workflows that fire after a VM has been provisioned — or on instances that were imported into Xloud through migration or discovery — the same scripting mechanism is available. Choose the path that fits your security and connectivity model.
The Compute API’s rebuild action re-applies a fresh user-data payload on the next boot of an existing instance. The instance keeps its UUID, IP, security groups, and metadata; only the disk image and user-data are re-applied.
Re-run bootstrap on an existing instance
openstack server rebuild <INSTANCE_ID> \
  --image <SAME_IMAGE_ID> \
  --user-data /path/to/new-bootstrap.sh
Works for both Linux and Windows guests. The user-data format is the same as at first launch — Bash, cloud-config, PowerShell, or cmd, identified by the first line of the payload.
The recommended path for ongoing operational workflows. The instance’s floating IP (or fixed IP if the orchestrator runs inside the cloud) is the target. Ansible’s shell module handles Bash payloads on Linux, and win_shell / win_command handle Bash-via- WSL or PowerShell on Windows.
ops-playbook.yaml
- hosts: web-tier
  tasks:
    - name: Rotate the deploy key
      ansible.builtin.shell: |
        sudo /opt/xloud/rotate-key.sh
      when: ansible_os_family != "Windows"

    - name: Rotate the deploy key on Windows hosts
      ansible.windows.win_powershell:
        script: C:\Program Files\Xloud\rotate-key.ps1
      when: ansible_os_family == "Windows"
XAVS Deployment Automation already includes the inventory plugin that pulls instance lists straight from Xloud, so a fresh ansible-playbook run picks up newly-launched VMs without manual inventory editing.
When an instance has the qemu-guest-agent package installed and the hw_qemu_guest_agent=yes property set on its source image, the administrator can send commands directly through the virtio-serial channel — no SSH or WinRM is required. This is the path that satisfies “execute scripts on a discovered VM” when the VM has no public network reachability.
Execute a one-shot command via the guest agent
virsh qemu-agent-command instance-00000abc \
  '{"execute":"guest-exec","arguments":{
     "path":"/bin/sh",
     "arg":["-c","systemctl restart nginx"],
     "capture-output":true}}'
The same channel supports guest-exec on Windows guests for PowerShell payloads.
For situations where the VM already has cloud-init installed and you just want it to re-process its user-data (for example, after editing the metadata via API), connect to the guest and clear the state:
Linux (cloud-init)
sudo cloud-init clean --logs
sudo reboot
On the next boot the agent re-fetches user-data from the metadata service and re-runs the bootstrap. Cloudbase-Init exposes a similar cloudbase-init --reset-service-password style flow.

Verification

LayerHow to checkExpected
Cloud-init invokedsudo cloud-init status --long (Linux)status: done
Cloudbase-Init invokedInspect cloudbase-init.logFinal line reads Plugins execution done
User-data was visible to the guestcurl http://169.254.169.254/openstack/latest/user_data from inside the VMReturns the exact payload you submitted
Script ranCheck the marker file written by your scriptFile exists and is recent
Errors during runsudo cloud-init analyze show (Linux) or cloudbase-init.log (Windows)No ERROR lines

Troubleshooting

The guest image probably has cloud-init or Cloudbase-Init disabled or uninstalled. Boot a fresh VM from the same image, run which cloud-init (Linux) or check for the Cloudbase-Init service in services.msc (Windows). If absent, rebuild the image or pick one from the Xloud public catalog.
Cloud-init swallows non-zero exit codes from the user script by default. Set set -euxo pipefail at the top of a Bash payload and $ErrorActionPreference = "Stop" at the top of a PowerShell payload to force errors to surface. Then re-run with the rebuild action above and check the log files listed in Verification.
The metadata service caps user-data at 16 KB raw (before base64). For larger payloads, host the script on an internal URL and use #include https://repo.internal/bootstrap.sh as the user-data; the agent fetches and executes it inline.
Cloudbase-Init bypasses execution policy when running scripts it fetches from the metadata service, so this is rare. If you see cannot be loaded because running scripts is disabled, the script is being launched by something other than Cloudbase-Init — check Scheduled Tasks or third-party agents that may have been baked into the image.
Cloud-init runs runcmd and shell scripts once per instance ID. For per-boot execution use bootcmd: in #cloud-config, or schedule a systemd unit that fires on boot. On Windows, set the Cloudbase-Init plugin policy to BootStatusPolicy = AlwaysRun in cloudbase-init.conf.

Security Considerations

  • Treat user-data as code, not config. It runs as root on Linux and as Administrator on Windows. Anyone with compute:create_server permission can submit it.
  • Do not embed secrets in user-data. The metadata service is reachable by every process inside the guest. Use Xloud Key Management for secrets and fetch them at runtime over an authenticated channel.
  • Network reachability of the metadata service. Restrict the metadata route in tenant security groups when an instance is moved to a hardened production segment — cloud-init will not need it after first boot.
  • Audit script content. XAVS Deployment Automation’s --check mode renders the playbook diff before execution. Use it for any multi-host operational workflow.

Next Steps

Launch an Instance

Full launch-wizard reference including every System Config field.

Linux VM Guide

Boot, login, and lifecycle for Linux guests.

Windows VM Guide

Cloudbase-Init, RDP setup, and Windows-specific notes.

Instance Snapshots

Capture a known-good state after bootstrap finishes.

Instance Rollback

Revert a bad bootstrap to a clean snapshot.

Instance Tagging

Tag VMs so operational scripts can target them by group.