XCP-ng Provider
Read this when you:
- choose
provider: xcp-ng; - set up an XCP-ng VM template for Crabbox;
- debug XAPI credentials, config-drive cloud-init, guest-tools IP discovery, or
- change
internal/providers/xcpng.
cleanup;
Crabbox's xcp-ng provider is a direct SSH-lease provider for Linux VMs on a self-hosted XCP-ng pool. For each lease Crabbox talks directly to the XAPI endpoint, copies the configured template to the selected SR with VM.copy, calls VM.provision, attaches a temporary FAT16 CIDATA config-drive image with per-lease cloud-init SSH access, waits for XCP-ng guest metrics to report the VM IPv4 address, runs the Crabbox Linux bootstrap over SSH, and then uses the normal SSH sync/run/release path.
The provider is direct-only: it talks to XCP-ng straight from the CLI. Xen Orchestra is not required, and the Crabbox coordinator does not provision or broker XCP-ng capacity. XCP-ng supports the ssh, crabbox-sync, and cleanup features on target=linux only.
Crabbox expects a self-hosted XCP-ng pool on dedicated 64-bit x86 server-class hardware for VM workloads. XCP-ng itself can host many guest OS families, including Linux, Windows, and BSD. Crabbox's current xcp-ng adapter is narrower: the normal doctor / warmup / run / ssh / stop / cleanup lease surface provisions Linux templates only. The separate ISO E2E harness documented below extends validation coverage to fresh Linux installers and Windows x86_64/x64 installer media. macOS guests are out of scope on this path; use the Tart provider on Apple hardware when you need macOS VM workflows.
#When to use
Use XCP-ng when:
- your test capacity lives on a private XCP-ng pool on dedicated 64-bit x86
- you want reusable lab infrastructure instead of public-cloud VMs;
- your template already supports cloud-init config drives and XCP-ng guest
server-class hardware;
tools.
Use AWS, Azure, Google Cloud, or Hetzner when you need brokered, cost-capped shared-team leases. Use the Static SSH provider when you already have a running host and do not want Crabbox to clone or delete VMs. Use the Tart provider on Apple hardware when you need macOS guest virtualization.
Provider name:
xcp-ng
There are no aliases.
#Template requirements
The configured template must be a Linux VM template with:
- OpenSSH installed and enabled;
- cloud-init enabled with a NoCloud/config-drive datasource;
- XCP-ng guest tools installed and reporting guest metrics;
- DHCP networking, or an equivalent network config that lets guest metrics
- outbound package access for the Crabbox bootstrap packages;
- a cloud-init user with passwordless
sudo.
report a non-loopback IPv4 address;
For each lease Crabbox:
- copies
xcpNg.templateorxcpNg.templateUuidto the configured SR with - resolves optional network and host placement, then writes Crabbox lease
- if
xcpNg.networkornetworkUuidis set, moves all VIFs on the copied VM - calls
VM.provision; - builds a per-lease FAT16
CIDATAconfig-drive image containing cloud-init - attaches the config drive to the VM;
- starts the VM;
- waits for guest metrics to report an IPv4 address;
- runs the normal Linux SSH bootstrap.
VM.copy;
labels on the copied VM;
to that network;
user-data and metadata;
If the guest tools never report an IPv4 address, or SSH does not come up so the bootstrap can run, provisioning fails and Crabbox attempts to delete both the VM and its config drive.
Because VM.copy creates full disk copies on the selected SR, template disk size and SR placement directly affect warmup and run latency. Crabbox is happiest with a single-NIC template. If you need a custom multi-NIC topology, leave xcpNg.network and networkUuid unset so Crabbox preserves the template's existing network layout.
#Quick start
Store credentials in private config or environment variables, then run a non-mutating doctor check before creating a VM:
export CRABBOX_XCP_NG_API_URL=https://xcp-pool.example.test
export CRABBOX_XCP_NG_USERNAME=crabbox@example.test
export CRABBOX_XCP_NG_PASSWORD='<api-password>'
export CRABBOX_XCP_NG_SR=default-sr
export CRABBOX_XCP_NG_TEMPLATE=crabbox-ubuntu-2404
export CRABBOX_XCP_NG_NETWORK=pool-network
crabbox doctor --provider xcp-ng --json
crabbox warmup --provider xcp-ng --keep --slug xcp-ng-smoke
crabbox run --provider xcp-ng --id xcp-ng-smoke --no-sync -- echo xcp-ng-ok
crabbox ssh --provider xcp-ng --id xcp-ng-smoke
crabbox stop --provider xcp-ng xcp-ng-smoke
crabbox cleanup --provider xcp-ng --dry-run
Keep CRABBOX_XCP_NG_API_URL on an administrator-only management network or VPN, and prefer trusted certificates. Set CRABBOX_XCP_NG_INSECURE_TLS=1 or pass --xcp-ng-insecure-tls only for private lab pools where you control the network and certificate issuance. That only disables certificate verification; the API URL must still use HTTPS.
#Configuration
provider: xcp-ng
target: linux
xcpNg:
apiUrl: https://xcp-pool.example.test
username: crabbox@example.test
password: <api-password>
template: crabbox-ubuntu-2404
templateUuid: ""
sr: default-sr
srUuid: ""
network: pool-network
networkUuid: ""
host: ""
user: crabbox
workRoot: /work/crabbox
insecureTLS: false
apiUrl, username, password, and either sr or srUuid are required for doctor and lifecycle commands. A template name or UUID is required before warmup or run can create a lease. network, networkUuid, and host are optional placement hints. user becomes the cloud-init SSH user, and workRoot becomes the remote workspace root.
When network or networkUuid is set, Crabbox moves all VIFs on the copied VM to the selected network. Use a single-NIC template for Crabbox-managed VMs, or leave the setting unset when the template's network topology should be preserved.
Point apiUrl at the pool master on an administrator-only management network or VPN when possible. Prefer trusted certificates. insecureTLS is a private-lab escape hatch, not a general deployment mode. If apiUrl points at a pool member that returns XAPI HOST_IS_SLAVE during login, Crabbox retries login once against the master address reported by XAPI.
Repository-local crabbox.yaml and .crabbox.yaml files cannot override apiUrl or insecureTLS, so a checkout cannot redirect inherited credentials. Configure those connection-trust settings in user config, an explicit CRABBOX_CONFIG file, or environment variables.
Keep the password in a private config file with 0600 permissions, in an environment variable, or in a secret manager. Do not pass it on argv. Crabbox intentionally has no XCP-ng password command-line flag, so the password does not appear in shell history or process listings.
Environment variables:
CRABBOX_XCP_NG_API_URL
CRABBOX_XCP_NG_USERNAME
CRABBOX_XCP_NG_PASSWORD
CRABBOX_XCP_NG_TEMPLATE
CRABBOX_XCP_NG_TEMPLATE_UUID
CRABBOX_XCP_NG_SR
CRABBOX_XCP_NG_SR_UUID
CRABBOX_XCP_NG_NETWORK
CRABBOX_XCP_NG_NETWORK_UUID
CRABBOX_XCP_NG_GUEST_CIDR
CRABBOX_XCP_NG_HOST
CRABBOX_XCP_NG_USER
CRABBOX_XCP_NG_WORK_ROOT
CRABBOX_XCP_NG_INSECURE_TLS
CRABBOX_XCP_NG_GUEST_CIDR enables bounded active MAC discovery for fresh guests that do not yet report XAPI guest metrics. It must be an IPv4 /24 or narrower range attached to the local runner. Without it, Crabbox may use an existing neighbor-table entry but does not sweep local subnets.
Provider flags mirror the non-secret config fields:
--xcp-ng-api-url
--xcp-ng-username
--xcp-ng-template
--xcp-ng-template-uuid
--xcp-ng-sr
--xcp-ng-sr-uuid
--xcp-ng-network
--xcp-ng-network-uuid
--xcp-ng-host
--xcp-ng-user
--xcp-ng-work-root
--xcp-ng-insecure-tls
#Doctor
crabbox doctor --provider xcp-ng --json is non-mutating. It validates local tools, checks required XCP-ng config, opens a XAPI session, lists Crabbox-managed leases, and reports mutation=false.
When configuration is incomplete, doctor returns a failed provider check with a message naming the missing config or environment variables. That is the right classification for CI and local setup probes: environment_blocked.
#Lifecycle
- Allocate a Crabbox lease ID and friendly slug.
- Resolve the configured template, storage repository, optional network, and
- Copy the template to the selected SR with
VM.copy, label the copied VM as - If
xcpNg.networkornetworkUuidis set, move all VIFs on the copied VM - Call
VM.provisionon the copied VM. - Generate cloud-init user-data and metadata with the per-lease SSH public key.
- Build and attach a FAT16
CIDATAconfig-drive image on the configured - Start the VM and wait for XCP-ng guest metrics to report a non-loopback IPv4
- Wait for SSH, then run the Crabbox Linux bootstrap.
- Sync the checkout and run commands over SSH.
- Touch lease labels during runs; on release, delete the config drive and VM
optional host.
Crabbox-managed, and apply optional host affinity.
to that network.
storage repository.
address.
unless the lease is kept.
This is full-copy provisioning, not a cheap CoW clone path, so SR throughput and template disk size are part of the user-visible provisioning contract.
Cleanup lists XCP-ng inventory and only acts on resources labeled as Crabbox-managed leases. Use crabbox cleanup --provider xcp-ng --dry-run before an actual cleanup sweep.
#Guarded live smoke
The repo includes a guarded smoke helper:
scripts/xcpng-live-smoke.sh --read-only
Read-only mode runs crabbox doctor --provider xcp-ng --json, writes redacted evidence under .crabbox/xcpng-live-smoke/, and does not create or delete VMs.
Mutating smoke requires an explicit gate and a configured template:
CRABBOX_XCP_NG_LIVE_MUTATE=1 scripts/xcpng-live-smoke.sh --mutate
The mutating path runs doctor first, creates one kept warmup lease, runs a minimal command with --no-sync, and then stops that exact lease. A shell trap attempts crabbox stop --provider xcp-ng <lease> on failure after a lease ID is known. If credentials, host access, or template configuration are missing, stop at the read-only doctor output and classify live validation as environment_blocked; do not claim live provisioning success.
The doctor path is non-mutating: it opens a XAPI session, resolves configured placement resources, lists Crabbox-managed leases, and reports mutation=false. Template, SR, network, or host typos fail before doctor reports ready.
#Guarded ISO E2E harness
The repo also includes a separate guarded harness for fresh-installer ISO validation:
scripts/xcpng-iso-e2e-smoke.sh --read-only --os linux --iso ~/Desktop/xcp/ISOs/ubuntu-26.04-live-server-amd64.iso
scripts/xcpng-iso-e2e-smoke.sh --read-only --os windows --iso ~/Desktop/xcp/ISOs/Win11_25H2_English_x64_v2.iso
This harness is intentionally separate from scripts/xcpng-live-smoke.sh. xcpng-live-smoke.sh preserves the normal Linux template-clone contract. xcpng-iso-e2e-smoke.sh is a quarantined acceptance helper for fresh blank VM plus installer media lifecycle. It extends validation coverage for fresh Linux and Windows x86_64/x64 installs on XCP-ng itself, but it does not change the normal provider: xcp-ng lease contract, which remains Linux-only.
Read-only mode:
- loads the same private env file pattern as
xcpng-live-smoke.sh; - validates XCP-ng auth plus placement prerequisites needed for ISO boot;
- resolves the installer ISO as a local file path, VDI name, UUID, or
- writes redacted local evidence under
.crabbox/xcpng-iso-e2e/; and - creates, changes, and deletes no XCP-ng resources.
OpaqueRef;
Mutating mode requires an explicit gate:
CRABBOX_XCP_NG_ISO_E2E_MUTATE=1 scripts/xcpng-iso-e2e-smoke.sh --mutate --os linux --iso ~/Desktop/xcp/ISOs/ubuntu-26.04-live-server-amd64.iso
Fresh ISO VMs do not inherit template VIFs, so mutating ISO runs also require xcpNg.network or xcpNg.networkUuid. These fields remain optional for normal template-based leases, where leaving them unset preserves the template network.
Linux mutating mode now performs the guarded Ubuntu Server acceptance flow:
- generates a per-run NoCloud seed ISO with Ubuntu autoinstall user-data;
- requires a local Ubuntu Server ISO path and remasters it under
- imports temporary installer and answer media into the configured SR when local
- creates a fresh blank VM plus writable install disk, boots the installer,
- proves first boot by running
printf linux-iso-e2e-okover SSH; and - removes the VM, install disk, and temporary imported media unless cleanup is
.crabbox/xcpng-iso-e2e/ to add the required autoinstall kernel argument;
file paths are used;
waits for the installed guest to reboot, and then waits for SSH on first boot;
blocked by the environment.
The wrapper now defaults to --timeout 90m, which is intended for the full Linux install flow. Override it explicitly only when the lab is known to be faster or slower.
Windows mutating mode now extends the shared harness for x86_64/x64 installer media:
- blocks ARM-labelled Windows installer media with
- generates a temporary
Autounattend.xmlISO when--answer-isois not - imports local installer and answer ISO paths into the configured SR when
- creates a fresh secure-boot VM plus writable install disk, boots from the
- waits for first-boot guest metrics and then attempts SSH proof with
- falls back to
source_uncoveredafter first-boot guest metrics when the
windows_requirements_blocked because the current XCP-ng ISO E2E lab is x86_64/x64;
supplied and includes a Crabbox bootstrap PowerShell script that installs OpenSSH with the per-run Crabbox SSH key; the generated answer media selects Windows image index 1 by default, and --answer-iso remains the override path when a different edition or custom answer file is required;
needed;
Windows installer media first, then switches the next boot to the installed disk; the fresh VM uses a 64 GiB install disk, and Windows 11-labelled media also gets a unique vTPM for the Windows 11 hardware requirements (requiring XCP-ng 8.3 or newer);
Write-Output windows-iso-e2e-ok; and
supplied answer media does not guarantee Crabbox SSH bootstrap.
Current classifications:
read_only_passed: config and ISO references resolved without mutation.linux_install_passed: the Linux installer completed, first boot reported awindows_install_passed: the Windows installer completed, first bootwindows_requirements_blocked: the selected Windows installer media or labsource_uncovered: the Windows guest reached first boot and reported guestenvironment_blocked: lab prerequisites, ISO identity, auth, placement, orresource_cleanup_failed: the shared lifecycle reached its target phase buttest_failed: local harness contract failure such as invalid arguments or
guest IPv4, and SSH proof succeeded.
reported a guest IPv4, and SSH proof succeeded.
prerequisites do not match the current x86_64/x64 XCP-ng validation surface.
metrics, but only guest-metrics readiness was available; Crabbox command proof remains uncovered for that answer-media path.
mutation gate blocked the run. For Linux this also includes exact phase blockers such as installer boot arg/remaster failure, guest-metrics timeout, or SSH readiness failure. For Windows this also includes answer-media generation, installer-media import, guest-metrics timeout, and SSH readiness failures after the bootstrap path is enabled.
cleanup left resources behind.
malformed helper output.
Linux mutating summaries use these phase values:
linux_seed_generationlinux_install_disklinux_iso_attachedlinux_installer_bootedlinux_install_completelinux_first_bootlinux_ssh_ok
Windows mutating summaries use these phase values:
windows_answer_generationwindows_install_diskwindows_iso_attachedwindows_setup_startedwindows_install_completewindows_first_bootwindows_command_ok
Every run writes a JSON summary with these stable keys:
classificationmutationosisophasecleanupevidence
Linux mutating mode requires a local Ubuntu Server ISO path and handles the temporary remaster/import steps itself. Existing SR-hosted Ubuntu installer ISOs are read-only validation inputs only unless they were already prepared with the required autoinstall boot argument outside this harness. Keep all .crabbox/xcpng-iso-e2e/ artifacts local; do not commit them.
Windows mutating mode expects x86_64/x64 installer media. ISOs-ARM style Windows media is a valid reference set for other local virtualization surfaces, but this XCP-ng harness treats ARM-labelled Windows installers as windows_requirements_blocked.
#Troubleshooting
xcp-ng configuration is incomplete
Set the missing xcpNg.* config keys or CRABBOX_XCP_NG_* variables. The password belongs in private config or env, never in a command-line flag.
xcp-ng api URL must use https
Use an HTTPS XAPI endpoint on a private management network or VPN. Prefer trusted certificates. insecureTLS permits self-signed certificates but should stay limited to private lab use; it does not allow plain HTTP.
xcp-ng template not found by name / xcp-ng template name is ambiguous
Set xcpNg.templateUuid or CRABBOX_XCP_NG_TEMPLATE_UUID to pin the exact template, or rename templates so the configured name is unique.
xcp-ng sr or sr UUID is required
Set xcpNg.sr, xcpNg.srUuid, CRABBOX_XCP_NG_SR, or CRABBOX_XCP_NG_SR_UUID. The storage repository is needed for both VM placement and config-drive creation.
no guest ipv4 address reported by XCP-ng guest metrics
Confirm XCP-ng guest tools are installed and running in the template, DHCP is available on the selected network, and the guest reports an IPv4 address after boot.