Azure Provider
Read when:
- choosing
provider: azure; - debugging Azure VM capacity, quotas, images, or SSH readiness;
- changing
internal/providers/azureor the direct Azure provisioning code.
Azure is a managed provider for Linux, native Windows, and Windows WSL2 leases. Azure provisions the VM, public IP, NIC, and OS disk, then Crabbox owns SSH readiness, optional desktop/VNC or WSL2 bootstrap, sync, command execution, results, and cleanup.
#When To Use
Use Azure when the team's cloud capacity lives in an Azure subscription, or when Microsoft tooling, Entra ID, or Azure-specific networking constraints make AWS or Hetzner inappropriate. Use Hetzner for cheaper Linux-only capacity and AWS for macOS targets.
Azure supports direct mode and brokered Linux/native Windows/WSL2 leases. Direct mode uses local Azure credentials. Brokered mode uses the operator-owned Azure service principal configured on the Worker.
#Commands
crabbox warmup --provider azure --class beast
crabbox run --provider azure --class standard -- pnpm test
crabbox warmup --provider azure --target windows --class standard
crabbox warmup --provider azure --target windows --desktop --class standard
crabbox warmup --provider azure --target windows --windows-mode wsl2 --class standard
crabbox warmup --provider azure --desktop --browser
crabbox ssh --provider azure --id blue-lobster
crabbox stop --provider azure blue-lobster
crabbox cleanup --provider azure
--type is exact (e.g. --type Standard_D32ads_v6). Use --class when SKU fallback is desired.
#Config
provider: azure
target: linux
class: beast
azure:
subscriptionId: 00000000-0000-0000-0000-000000000000
tenantId: 00000000-0000-0000-0000-000000000000
clientId: 00000000-0000-0000-0000-000000000000
location: eastus
resourceGroup: crabbox-leases
image: Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest
vnet: crabbox-vnet
subnet: crabbox-subnet
nsg: crabbox-nsg
sshCIDRs: []
network: public
subscriptionId, tenantId, and clientId may be set in config or sourced from environment variables. The client secret is never read from config; it must come from the environment.
Important direct-mode environment:
AZURE_SUBSCRIPTION_ID
AZURE_TENANT_ID
AZURE_CLIENT_ID
AZURE_CLIENT_SECRET
CRABBOX_AZURE_SUBSCRIPTION_ID
CRABBOX_AZURE_TENANT_ID
CRABBOX_AZURE_CLIENT_ID
CRABBOX_AZURE_LOCATION
CRABBOX_AZURE_RESOURCE_GROUP
CRABBOX_AZURE_IMAGE
CRABBOX_AZURE_VNET
CRABBOX_AZURE_SUBNET
CRABBOX_AZURE_NSG
CRABBOX_AZURE_SSH_CIDRS
CRABBOX_AZURE_NETWORK
CRABBOX_AZURE_NETWORK selects the IP used for SSH: public (default) uses the VM public IP, private uses the NIC private IP from the vnet. Use private when connecting through a VPN to the Azure virtual network.
AZURE_* are the standard service principal env vars consumed by DefaultAzureCredential. Crabbox does not read or print the client secret.
Brokered mode uses the same Azure service-principal secrets on the Worker: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_SUBSCRIPTION_ID. Operators own the resource group, vnet, subnet, NSG, and SSH CIDR defaults through CRABBOX_AZURE_* env vars. A lease request may override only azureLocation and azureImage.
Run crabbox doctor --provider azure --target windows before leasing through the broker. The coordinator readiness check reports missing Worker secret names without exposing values, and lease creation fails with provider_not_configured until the required service-principal secrets are present.
#Auth
The simplest setup uses the Azure CLI — no environment variables needed:
az login
crabbox azure login
crabbox warmup --provider azure
crabbox azure login detects the active subscription, validates credentials, and stores subscription ID, tenant ID, and location in user config. After this, DefaultAzureCredential picks up the az login session automatically.
For service-principal setups (CI, automation, shared environments), use environment variables:
If azure.tenantId and azure.clientId (or CRABBOX_AZURE_TENANT_ID / CRABBOX_AZURE_CLIENT_ID) are configured and AZURE_CLIENT_SECRET is set in the environment, Crabbox builds a ClientSecretCredential from those explicit values. Otherwise it falls back to azidentity.NewDefaultAzureCredential, which scans environment, workload identity, managed identity, and CLI credentials in order. The simplest setup is a service principal with the Contributor role scoped to the resource group, configured via:
export AZURE_TENANT_ID=...
export AZURE_CLIENT_ID=...
export AZURE_CLIENT_SECRET=...
export AZURE_SUBSCRIPTION_ID=...
See Authenticate Go apps to Azure services with service principals.
#Lifecycle
- Resolve credentials per the rules above.
- Ensure the shared resource group, virtual network, subnet, and network
- Mint a per-lease SSH key.
- Pick the configured class SKU candidates and try each in order.
- For each lease: create a public IP, NIC, and VM with cloud-init in
- Query Azure Resource SKUs for the VM size. If Azure reports ephemeral OS
- Tag the VM, NIC, and public IP with Crabbox lease metadata.
- Wait for the public IP to allocate, then for SSH readiness.
- When
--desktopis requested on native Windows, run the shared Windows - When
windows.mode=wsl2is requested, run the shared Windows WSL2 - Let core sync and run over SSH.
- On release/cleanup, cascade-delete VM → NIC → public IP → OS disk. The
security group exist. Crabbox first issues Get calls against each resource. If a resource exists without the managed_by=crabbox tag, Crabbox refuses to mutate it and returns an adopt-or-rename error. If a resource exists with the tag, it is left alone (Crabbox does not overwrite tags, address spaces, subnets, or rules on subsequent acquires). If a resource is missing, it is created with Crabbox tags and the configured layout. Inbound SSH rules are derived from azure.sshCIDRs, the configured SSH port, and any fallback ports.
osProfile.customData and the SSH key in osProfile.linuxConfiguration.ssh.publicKeys for Linux. Native Windows uses a Windows Server small-disk Gen2 image, Windows osProfile fields (adminPassword, computerName, and windowsConfiguration), and a non-rebooting Custom Script Extension that runs the initial Crabbox SSH bootstrap saved in C:\AzureData\CustomData.bin.
disk support, use a local ephemeral OS disk. Otherwise use a managed StandardSSD_LRS OS disk.
desktop bootstrap over SSH. That installs TightVNC, configures the generated crabbox Windows login, enables auto-logon, reboots once, and waits for SSH/VNC readiness.
bootstrap over SSH. That enables WSL/VirtualMachinePlatform/HypervisorPlatform, reboots as needed, imports Ubuntu, and waits for the Linux-side crabbox-ready check.
shared infra remains.
#Classes
Default Linux SKUs:
standard Standard_D32ads_v6, Standard_D32ds_v6, Standard_F32s_v2, Standard_D32ads_v5, Standard_D32ds_v5, then D/F 16-vCPU fallbacks
fast Standard_D64ads_v6, Standard_D64ds_v6, Standard_F64s_v2, Standard_D64ads_v5, Standard_D64ds_v5, then D/F 48-vCPU and 32-vCPU fallbacks
large Standard_D96ads_v6, Standard_D96ds_v6, Standard_D96ads_v5, Standard_D96ds_v5, then D/F 64-vCPU and 48-vCPU fallbacks
beast Standard_D192ds_v6, Standard_D128ds_v6, then D/F 96-vCPU and 64-vCPU fallbacks
Default native Windows and WSL2 SKUs:
standard Standard_D2ads_v6, Standard_D2ds_v6, Standard_D2ads_v5, Standard_D2ds_v5, then Standard_D2as_v6
fast Standard_D4ads_v6, Standard_D4ds_v6, Standard_D4ads_v5, Standard_D4ds_v5, then Standard_D4as_v6
large Standard_D8ads_v6, Standard_D8ds_v6, Standard_D8ads_v5, Standard_D8ds_v5, then Standard_D8as_v6
beast Standard_D16ads_v6, Standard_D16ds_v6, Standard_D16ads_v5, Standard_D16ds_v5, then Standard_D8ads_v6
Class-based provisioning falls back across the candidate list when Azure rejects a SKU for capacity or quota (SkuNotAvailable, QuotaExceeded, AllocationFailed, OverconstrainedAllocationRequest). Spot leases fall back to on-demand when capacity.fallback starts with on-demand. Explicit --type is exact. The default Linux candidates mirror the AWS Linux class table's vCPU scale. The default Windows candidates mirror the AWS native Windows class table's vCPU scale. Azure native Windows support covers SSH, sync, run, and optional desktop/VNC. Azure WSL2 support covers SSH, sync, run, and actions hydration through the POSIX WSL contract.
#Capabilities
- SSH: yes.
- Crabbox sync: yes.
- Native Windows: yes for SSH, sync, run, and desktop/VNC.
- Windows WSL2: yes for SSH, sync, run, and actions hydration.
- Desktop: Linux and native Windows.
- Browser / code: Linux only on Azure.
- Tailscale: Linux managed leases.
- Actions hydration: yes, Linux and Windows WSL2 leases.
- Coordinator: yes, brokered Linux/native Windows/WSL2 leases.
#Gotchas
- Azure VM names are constrained to 1-64 characters and cannot contain
- Windows computer names are limited to 15 characters. Crabbox keeps the VM
- The first acquire in an empty subscription pays the cost of creating the
- Shared Azure network resources are regional. If
crabbox-nsgor - If you already have a resource group / vnet / NSG with the configured
crabbox stop --provider azure <name>will only act on VMs that carry- The default SSH NSG rule allows
0.0.0.0/0whenazure.sshCIDRsis - Azure costs are not hardcoded in Crabbox. Set
CRABBOX_COST_RATES_JSON - Azure native Windows uses Custom Script Extension because Windows custom
- Azure does not provide managed macOS through this provider. Use AWS or
- Direct-mode cleanup is best effort. Use
crabbox cleanup --provider azure
underscores. The leaseProviderName helper substitutes underscores for dashes; if you customize naming, keep that constraint in mind.
resource name stable and derives a shorter Windows computerName.
shared resource group, vnet, and NSG. Subsequent acquires only create per-lease resources.
crabbox-vnet already exists in westcentralus, a later acquire configured for eastus must either set azure.location: westcentralus to reuse that shared infra or use different azure.vnet / azure.subnet / azure.nsg names for the new region.
names, Crabbox will refuse to mutate them unless they carry managed_by=crabbox as a tag. Either tag them to adopt, choose different names in azure.* config, or let Crabbox create dedicated resources.
crabbox=true (and either no provider tag or provider=azure). A manually-named VM in the resource group will not be deleted by Crabbox.
empty. Set explicit CIDRs for any production-adjacent setup.
when you need exact Azure cost guardrails.
data is saved to disk but not executed by Azure provisioning. Keep that extension path non-rebooting; Windows desktop/VNC setup runs later over SSH.
provider: ssh for macOS targets.
to sweep expired direct leases.
Related docs: