Deploy HailBytes ASM on Azure via CLI

Programmatic deployment in one shell session. No portal clicks. Works on Azure commercial and Azure Government.

What you’ll do

  1. Accept the marketplace plan terms (one-time, per subscription).
  2. Resolve the latest HailBytes ASM URN for your region.
  3. Launch a hardened VM via az vm create — or use ARM/Bicep if your shop standardizes on IaC.
  4. Bootstrap admin credentials and generate an API key for REST + MCP access.
  5. Connect an MCP-aware client (Claude, Cursor, Windsurf) to the new instance.

Estimated time: 5–8 minutes including image acceptance and the cloud-init bootstrap. Estimated infrastructure cost: ~$175/month for a Standard_D4s_v5 in East US (your mileage will vary by region and SKU).

Prerequisites

  • Azure CLI, signed in with az login and a subscription that allows VM creation and marketplace deployments.
  • SSH public key; the CLI examples use ~/.ssh/id_ed25519.pub.
  • An office IP or VPN CIDR to lock the NSG down to. The CLI examples assume $ALLOW_CIDR.
export RG=hailbytes-asm-rg
export LOCATION=eastus
export VM_NAME=hailbytes-asm
export ALLOW_CIDR=203.0.113.4/32        # your office or VPN
export SSH_KEY=~/.ssh/id_ed25519.pub

az group create --name "$RG" --location "$LOCATION"

Step 1 — Accept marketplace terms

Azure requires explicit per-subscription acceptance of marketplace plan terms before az vm create will pull the image. This is the gotcha that breaks first-time CLI deployments.

# Replace these with the published values when prompted.
export PUBLISHER=hailbytes
export OFFER=hailbytes-asm
export SKU=byol

# View current terms
az vm image terms show \
  --publisher "$PUBLISHER" --offer "$OFFER" --plan "$SKU"

# Accept once per subscription
az vm image terms accept \
  --publisher "$PUBLISHER" --offer "$OFFER" --plan "$SKU"

Acceptance persists at the subscription level, not the resource group, so subsequent VMs in any region under the same subscription will deploy without prompting.

Step 2 — Resolve the latest URN

URN=$(az vm image list \
  --publisher "$PUBLISHER" --offer "$OFFER" --sku "$SKU" \
  --location "$LOCATION" --all \
  --query 'sort_by([], &version)[-1].urn' -o tsv)

echo "Resolved URN: $URN"
# e.g. hailbytes:hailbytes-asm:byol:1.4.0

Pinning to a specific version (e.g. hailbytes:hailbytes-asm:byol:1.4.0) keeps redeploys deterministic. Using :latest always pulls the newest published image.

Step 3 — Launch via az vm create

az vm create \
  --resource-group "$RG" \
  --name "$VM_NAME" \
  --location "$LOCATION" \
  --image "$URN" \
  --size Standard_D4s_v5 \
  --admin-username hailbytes \
  --ssh-key-values "$SSH_KEY" \
  --os-disk-size-gb 100 \
  --os-disk-encryption-set "" \
  --public-ip-sku Standard \
  --nsg-rule SSH \
  --tags product=hailbytes-asm

# Lock the NSG to your CIDR for both 22 and 443
NSG=$(az network nsg list -g "$RG" \
        --query "[?contains(name,'$VM_NAME')].name" -o tsv)

az network nsg rule create -g "$RG" --nsg-name "$NSG" \
  --name allow-ssh --priority 100 \
  --access Allow --direction Inbound --protocol Tcp \
  --source-address-prefixes "$ALLOW_CIDR" \
  --destination-port-ranges 22

az network nsg rule create -g "$RG" --nsg-name "$NSG" \
  --name allow-https --priority 110 \
  --access Allow --direction Inbound --protocol Tcp \
  --source-address-prefixes "$ALLOW_CIDR" \
  --destination-port-ranges 443

# Capture the public IP for later steps
PUBLIC_IP=$(az vm show -d -g "$RG" -n "$VM_NAME" \
  --query publicIps -o tsv)

echo "ASM is bootstrapping at https://$PUBLIC_IP/"

Cloud-init runs the docker-compose stack on first boot; that takes 3–5 minutes. Until you point a domain at the VM and run the included certbot helper, the web UI / MCP endpoint is reachable on a self-signed cert.

Alternative — ARM / Bicep

Same outcome via IaC, parameterized for repeat deployments.

az deployment group create \
  --resource-group "$RG" \
  --template-uri https://hailbytes-marketplace.blob.core.windows.net/asm/azuredeploy.json \
  --parameters \
      vmName="$VM_NAME" \
      adminUsername=hailbytes \
      sshPublicKey="$(cat $SSH_KEY)" \
      vmSize=Standard_D4s_v5 \
      allowedCidr="$ALLOW_CIDR" \
      imageUrn="$URN"

az deployment group show \
  -g "$RG" -n hailbytes-asm \
  --query 'properties.outputs'

The published template uses the same Packer-built image; pinning imageUrn to a known good version keeps redeploys deterministic. For multi-region rollouts, parameterize on $LOCATION and let your CI loop the call.

Step 4 — Bootstrap credentials

ssh hailbytes@$PUBLIC_IP

# Inside the VM:
sudo /opt/hailbytes/bin/hailbytes-asm reset-admin --email admin@example.com
# → prints a one-time login URL

sudo /opt/hailbytes/bin/hailbytes-asm api-key create \
  --name "ci-bootstrap" \
  --description "First key for REST + MCP"
# → prints HAILBYTES_ASM_KEY=...   (save it; shown only once)

The API key works for both the REST API (X-API-Key header) and the MCP server. Keys are SHA-256 hashed at rest; the plaintext is never stored.

Step 5 — Connect MCP

{
  "mcpServers": {
    "hailbytes-asm": {
      "type": "streamable-http",
      "url":  "https://<your-asm-host>/mcp/",
      "headers": { "X-API-Key": "<HAILBYTES_ASM_KEY>" }
    }
  }
}

Confirm the agent can see HailBytes by asking it to “list targets in HailBytes ASM”. Full tool reference: /mcp/.

Azure Government

Same flow on Azure Government. Set the cloud first, then re-run from Step 1.

az cloud set --name AzureUSGovernment
az login
export LOCATION=usgovvirginia   # or usgovtexas, usgovarizona

Image acceptance and URN resolution work identically; the URN is published in the Azure Government marketplace separately. See the security overview for the FedRAMP-aligned posture statement.

Smoke test

# REST
curl -k https://$PUBLIC_IP/api/listTargets/ \
  -H "X-API-Key: $HAILBYTES_ASM_KEY" | jq '.recordsTotal'

# MCP
curl -k -I https://$PUBLIC_IP/mcp/ \
  -H "X-API-Key: $HAILBYTES_ASM_KEY"

Tear-down

# Whole resource group
az group delete --name "$RG" --yes --no-wait

# Or just the deployment created by the ARM/Bicep path
az deployment group delete -g "$RG" -n hailbytes-asm

Get the Free HailBytes ASM Getting Started Guide

A 7-part email series covering everything from your first deployment to advanced configuration and real-world workflows. One email per day, no spam.