Documentation Index
Fetch the complete documentation index at: https://docs.polystack.tech/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Polystack 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 Polystack metadata service so the same launch flow works for every supported OS.Two capabilities, one mechanism
- 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).
- 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) orCloudbase-Init(Windows) pre-installed. The Polystack public image catalog ships with both. - A network or metadata route from the instance to the Polystack metadata
service (link-local
169.254.169.254over 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 line | Treated as | Runs on |
|---|---|---|
#!/bin/bash (or #!/bin/sh, #!/usr/bin/env python3, etc.) | A shebang script | Linux (cloud-init) |
#cloud-config | Declarative YAML — packages, users, files, run commands | Linux (cloud-init) |
#include | Fetches a script from a URL | Linux (cloud-init) |
Content-Type: multipart/mixed (MIME) | Multiple payloads in one upload | Linux (cloud-init) |
#ps1 or #ps1_sysnative | PowerShell script | Windows (Cloudbase-Init) |
#cmd | Classic Windows command prompt batch | Windows (Cloudbase-Init) |
#cloud-config | Declarative YAML (subset supported) | Windows (Cloudbase-Init) |
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.
- Dashboard
- CLI
Open the launch wizard
Navigate to Compute → Instances and click
Create Instance. Complete the Base Config and
Network Config steps as normal.
Expand Advanced Options
On the System Config step, scroll to the Advanced Options
toggle and turn it on. The User Data textarea becomes
visible.
Paste or upload the script
Paste the script directly into the textarea, or click the upload
icon and choose a local
The Dashboard rejects payloads above the limit before submit.
.sh, .yaml, .ps1, or .cmd file.| Limit | Value |
|---|---|
| Maximum payload size | 16 KB (before base64 encoding) |
| Encoding | UTF-8, ASCII safe |
| Forbidden characters | None — full Unicode allowed inside the script body |
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
cloud-config YAML — declarative bootstrap
cloud-init.yaml
Windows Bootstrap Examples (PowerShell and cmd)
PowerShell script — install IIS and write a marker
bootstrap.ps1
#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
cloud-config on Windows — restricted subset
cloud-init.yaml
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 Polystack through migration or discovery — the same scripting mechanism is available. Choose the path that fits your security and connectivity model.Rebuild with new user-data (Bash or PowerShell)
Rebuild with new user-data (Bash or PowerShell)
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.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.
Re-run bootstrap on an existing instance
Ansible against the instance IP
Ansible against the instance IP
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 Ironcore Deployment Automation already includes the inventory plugin
that pulls instance lists straight from Polystack, so a fresh
shell module handles Bash
payloads on Linux, and win_shell / win_command handle Bash-via-
WSL or PowerShell on Windows.ops-playbook.yaml
ansible-playbook run picks up newly-launched VMs without manual
inventory editing.qemu-guest-agent (hypervisor-side execution)
qemu-guest-agent (hypervisor-side execution)
When an instance has the qemu-guest-agent package installed and
the The same channel supports
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
guest-exec on Windows guests for
PowerShell payloads.Re-run cloud-init on the next boot
Re-run cloud-init on the next boot
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:On the next boot the agent re-fetches user-data from the metadata
service and re-runs the bootstrap. Cloudbase-Init exposes a similar
Linux (cloud-init)
cloudbase-init --reset-service-password style flow.Verification
| Layer | How to check | Expected |
|---|---|---|
| Cloud-init invoked | sudo cloud-init status --long (Linux) | status: done |
| Cloudbase-Init invoked | Inspect cloudbase-init.log | Final line reads Plugins execution done |
| User-data was visible to the guest | curl http://169.254.169.254/openstack/latest/user_data from inside the VM | Returns the exact payload you submitted |
| Script ran | Check the marker file written by your script | File exists and is recent |
| Errors during run | sudo cloud-init analyze show (Linux) or cloudbase-init.log (Windows) | No ERROR lines |
Troubleshooting
The script never ran
The script never ran
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 Polystack public catalog.The script ran but failed silently
The script ran but failed silently
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.Payload too large — 16 KB limit
Payload too large — 16 KB limit
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.PowerShell complains about execution policy
PowerShell complains about execution policy
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.The user-data ran once but I want it to run on every boot
The user-data ran once but I want it to run on every boot
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_serverpermission can submit it. - Do not embed secrets in user-data. The metadata service is reachable by every process inside the guest. Use Polystack 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. Ironcore Deployment Automation’s
--checkmode 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.
