openclaw/docs/platforms/azure/deploy-guide.md
xuhaodev bb575c400e feat: Add Azure OpenAI support with configuration and fetch wrapper
- Introduced Azure OpenAI provider configuration in `azure-openai-provider.ts`.
- Implemented global fetch wrapper to handle Azure API versioning.
- Added new session files for Azure OpenAI interactions.
- Created initial configuration files for cron jobs and device management.
- Established Docker Compose setup for Azure OpenAI deployment.
- Updated main session management with new skills and context handling.
- Added environment variable resolution for Azure OpenAI configuration.
2026-01-29 12:39:24 +08:00

11 KiB

Deploying Moltbot to Azure Web App for Containers

This guide covers deploying Moltbot gateway to Azure Web App for Containers with Azure OpenAI as the LLM provider.

Prerequisites

  • Azure CLI installed and authenticated (az login)
  • Docker (for local testing, optional)
  • An Azure subscription with permissions to create resources

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                     Azure Web App                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Container (Node.js)                     │   │
│  │  ┌─────────────────────────────────────────────┐    │   │
│  │  │           Moltbot Gateway                    │    │   │
│  │  │  - Control UI (WebSocket)                    │    │   │
│  │  │  - Agent runtime                             │    │   │
│  │  └─────────────────────────────────────────────┘    │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Azure OpenAI                             │
│  - GPT-5.2, GPT-5.2-codex, etc.                               │
└─────────────────────────────────────────────────────────────┘

Step 1: Create Azure Resources

1.1 Create Resource Group

RESOURCE_GROUP="moltbot-rg"
LOCATION="eastus2"

az group create --name $RESOURCE_GROUP --location $LOCATION

1.2 Create Azure Container Registry (ACR)

ACR_NAME="moltbotreg"  # Must be globally unique

az acr create \
  --resource-group $RESOURCE_GROUP \
  --name $ACR_NAME \
  --sku Basic \
  --admin-enabled true

1.3 Create Azure OpenAI Resource

OPENAI_NAME="moltbot-openai"

az cognitiveservices account create \
  --name $OPENAI_NAME \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --kind OpenAI \
  --sku S0

Deploy a model (e.g., gpt-5.2):

az cognitiveservices account deployment create \
  --name $OPENAI_NAME \
  --resource-group $RESOURCE_GROUP \
  --deployment-name "gpt-5.2" \
  --model-name "gpt-5.2" \
  --model-version "2024-07-18" \
  --model-format OpenAI \
  --sku-capacity 10 \
  --sku-name Standard

Get the endpoint and key:

# Endpoint
az cognitiveservices account show \
  --name $OPENAI_NAME \
  --resource-group $RESOURCE_GROUP \
  --query properties.endpoint -o tsv

# Key
az cognitiveservices account keys list \
  --name $OPENAI_NAME \
  --resource-group $RESOURCE_GROUP \
  --query key1 -o tsv

1.4 Create App Service Plan

APP_SERVICE_PLAN="moltbot-plan"

az appservice plan create \
  --name $APP_SERVICE_PLAN \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --is-linux \
  --sku B1

1.5 Create Web App

WEB_APP_NAME="moltbot-app"  # Must be globally unique

az webapp create \
  --resource-group $RESOURCE_GROUP \
  --plan $APP_SERVICE_PLAN \
  --name $WEB_APP_NAME \
  --deployment-container-image-name "${ACR_NAME}.azurecr.io/moltbot-azure:latest"

Step 2: Configure the Dockerfile

Create Dockerfile.azure in the repository root:

FROM node:22-bookworm

# Install bun for faster builds
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable

WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml ./
COPY patches ./patches

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source and build
COPY . .
RUN pnpm build

# Prune dev dependencies
RUN pnpm prune --prod

ENV NODE_ENV=production

# Create config directory and bake in Azure-specific config
# IMPORTANT: trustedProxies is required for Azure's internal proxy
RUN mkdir -p /home/node/.moltbot && \
  echo '{"gateway":{"controlUi":{"allowInsecureAuth":true},"trustedProxies":["169.254.0.0/16"]},"agents":{"defaults":{"model":{"primary":"azure-openai/gpt-5.2"}}}}' > /home/node/.moltbot/moltbot.json && \
    chown -R node:node /home/node/.moltbot

USER node

EXPOSE 18789

CMD ["node", "dist/index.js", "gateway", "--bind", "lan", "--port", "18789", "--allow-unconfigured"]

Key Configuration Notes

Setting Purpose
allowInsecureAuth: true Control UI uses token-only auth (skips device pairing). Security downgrade; prefer HTTPS + pairing when possible.
trustedProxies: ["169.254.0.0/16"] Trust Azure's internal proxy for X-Forwarded-* headers
--bind lan Bind to all interfaces (required for container networking)
--allow-unconfigured Start without requiring pre-configured channels

Step 3: Build and Push Container Image

az acr build \
  --registry $ACR_NAME \
  --image moltbot-azure:latest \
  --file Dockerfile.azure \
  .

3.2 Alternative: Build Locally and Push

# Login to ACR
az acr login --name $ACR_NAME

# Build
docker build -t ${ACR_NAME}.azurecr.io/moltbot-azure:latest -f Dockerfile.azure .

# Push
docker push ${ACR_NAME}.azurecr.io/moltbot-azure:latest

Step 4: Configure Web App

4.1 Connect ACR to Web App

# Get ACR credentials
ACR_USERNAME=$(az acr credential show --name $ACR_NAME --query username -o tsv)
ACR_PASSWORD=$(az acr credential show --name $ACR_NAME --query passwords[0].value -o tsv)

# Configure container settings
az webapp config container set \
  --resource-group $RESOURCE_GROUP \
  --name $WEB_APP_NAME \
  --docker-custom-image-name "${ACR_NAME}.azurecr.io/moltbot-azure:latest" \
  --docker-registry-server-url "https://${ACR_NAME}.azurecr.io" \
  --docker-registry-server-user $ACR_USERNAME \
  --docker-registry-server-password $ACR_PASSWORD

4.2 Configure Environment Variables

# Generate a secure gateway token
GATEWAY_TOKEN=$(openssl rand -hex 16)

az webapp config appsettings set \
  --resource-group $RESOURCE_GROUP \
  --name $WEB_APP_NAME \
  --settings \
    WEBSITES_PORT=18789 \
    MOLTBOT_STATE_DIR=/home/node/.moltbot \
    MOLTBOT_CONFIG_PATH=/home/node/.moltbot/moltbot.json \
    CLAWDBOT_GATEWAY_TOKEN=$GATEWAY_TOKEN \
    AZURE_OPENAI_API_KEY="<your-azure-openai-key>" \
    AZURE_OPENAI_DEPLOYMENT_NAME="gpt-5.2" \
    AZURE_OPENAI_ENDPOINT="https://<your-resource>.openai.azure.com/" \
    AZURE_OPENAI_API_VERSION="2024-08-01-preview"

echo "Gateway Token: $GATEWAY_TOKEN"

4.3 Enable WebSockets and Always On

az webapp config set \
  --resource-group $RESOURCE_GROUP \
  --name $WEB_APP_NAME \
  --web-sockets-enabled true \
  --always-on true

4.4 Set Startup Command

az webapp config set \
  --resource-group $RESOURCE_GROUP \
  --name $WEB_APP_NAME \
  --startup-file 'node dist/index.js gateway --bind lan --port 18789 --allow-unconfigured'

Step 5: Deploy and Verify

5.1 Restart the Web App

az webapp restart --resource-group $RESOURCE_GROUP --name $WEB_APP_NAME

5.2 Check Logs

# Stream logs
az webapp log tail --resource-group $RESOURCE_GROUP --name $WEB_APP_NAME

# Or download logs
az webapp log download \
  --resource-group $RESOURCE_GROUP \
  --name $WEB_APP_NAME \
  --log-file /tmp/webapp-logs.zip

5.3 Verify Deployment

Look for these indicators in the logs:

[gateway] agent model: azure-openai/gpt-5.2
[gateway] listening on 0.0.0.0:18789

If you see warnings about untrusted proxy headers, the trustedProxies config is not applied correctly.

5.4 Access Control UI

Open in browser:

https://<your-app-name>.azurewebsites.net/?token=<your-gateway-token>

Troubleshooting

Problem: "pairing required" Error

Cause: The gateway doesn't recognize the connection as authorized.

Solutions:

  1. Ensure dangerouslyDisableDeviceAuth: true is in the config
  2. Ensure trustedProxies includes 169.254.0.0/16
  3. Access with the token: ?token=<your-token>

Problem: "Proxy headers detected from untrusted address"

Cause: Azure's internal proxy IP is not trusted.

Solution: Add "trustedProxies": ["169.254.0.0/16"] to gateway config.

Problem: Container Crash Loop

Check logs for:

  • Cannot find module - Startup command is malformed
  • SyntaxError - Config JSON is invalid
  • Port binding errors - Ensure WEBSITES_PORT=18789

Common fix: Verify appCommandLine is set correctly:

az webapp config show -g $RESOURCE_GROUP -n $WEB_APP_NAME --query appCommandLine

If it shows "" (empty quotes), the image CMD won't be used. Set it explicitly:

az webapp config set -g $RESOURCE_GROUP -n $WEB_APP_NAME \
  --startup-file 'node dist/index.js gateway --bind lan --port 18789 --allow-unconfigured'

Problem: Azure OpenAI Not Working

Verify:

  1. Model deployment name matches config (e.g., gpt-5.2)
  2. API key is correct
  3. Endpoint URL format: https://<resource>.openai.azure.com/
  4. API version is supported (e.g., 2024-08-01-preview)

Problem: 503 Service Unavailable

Causes:

  • Container still starting (wait 1-2 minutes)
  • Container crashing (check logs)
  • Port mismatch (verify WEBSITES_PORT)

Environment Variables Reference

Variable Required Description
WEBSITES_PORT Yes Port the container listens on (18789)
MOLTBOT_STATE_DIR Yes Directory for runtime state
MOLTBOT_CONFIG_PATH Yes Path to config JSON file
CLAWDBOT_GATEWAY_TOKEN Yes Token for Control UI authentication
AZURE_OPENAI_API_KEY Yes Azure OpenAI API key
AZURE_OPENAI_ENDPOINT Yes Azure OpenAI endpoint URL
AZURE_OPENAI_API_VERSION Yes API version (e.g., 2024-08-01-preview)

Security Recommendations

  1. Use Managed Identity instead of API keys where possible
  2. Restrict network access with Azure Private Endpoints
  3. Enable HTTPS Only in Web App settings
  4. Rotate gateway tokens periodically
  5. Use Azure Key Vault for secrets in production

Updating the Deployment

To deploy a new version:

# Rebuild image
az acr build --registry $ACR_NAME --image moltbot-azure:latest --file Dockerfile.azure .

# Restart to pull new image
az webapp restart --resource-group $RESOURCE_GROUP --name $WEB_APP_NAME

Cleanup

To remove all resources:

az group delete --name $RESOURCE_GROUP --yes --no-wait