Deploy to Azure

This guide covers deploying your Agility CMS .NET application to Azure App Service, including one-click deployment, manual deployment, and CI/CD setup.

One-Click Deployment

The fastest way to deploy is using our Azure Resource Manager (ARM) templates.

Deploy Blazor Starter

Deploy to Azure

Deploy MVC Starter

Deploy to Azure

Deployment Parameters

ParameterRequiredDefaultDescription
webAppNameYes-Globally unique name (becomes yourname.azurewebsites.net)
instanceGuidYes-Agility CMS Instance GUID
securityKeyYes-Security key for preview mode
fetchAPIKeyYes-Live content API key
previewAPIKeyYes-Preview content API key
localesNoen-usComma-separated locale codes
channelNameNowebsiteAgility sitemap channel
skuNoB1App Service Plan SKU

SKU Requirements

SKUWebSocketsAlwaysOnRecommended For
F1 (Free)NoNoNot supported
D1 (Shared)NoNoNot supported
B1YesYesDevelopment/Testing
S1YesYesProduction
P1V2+YesYesHigh-traffic production

Important: The Blazor starter requires WebSockets for Interactive Server components. Choose B1 or higher.

What Gets Deployed

The ARM template creates:

  • Linux App Service running .NET 10
  • App Service Plan with your chosen SKU
  • WebSockets enabled (required for Blazor Interactive Server)
  • AlwaysOn enabled (keeps the app warm)
  • HTTP/2 enabled (better performance)
  • TLS 1.2 minimum (security)
  • Git deployment from the repository

Manual Deployment

Using Visual Studio Code

  1. Install Extensions

    • Azure App Service extension
    • Azure Resources extension
  2. Build for Release

    dotnet publish -c Release -o ./publish
    
  3. Deploy

    • Right-click the publish folder
    • Select "Deploy to Web App..."
    • Choose your subscription and App Service
    • Confirm deployment

Using Visual Studio

  1. Right-click the project in Solution Explorer
  2. Select Publish
  3. Choose Azure > Azure App Service (Linux)
  4. Select or create an App Service
  5. Click Publish

Using Azure CLI

# Login to Azure
az login

# Create resource group
az group create --name myResourceGroup --location eastus

# Create App Service Plan
az appservice plan create \
  --name myAppServicePlan \
  --resource-group myResourceGroup \
  --sku B1 \
  --is-linux

# Create Web App
az webapp create \
  --name myAgilityApp \
  --resource-group myResourceGroup \
  --plan myAppServicePlan \
  --runtime "DOTNET|10.0"

# Configure settings
az webapp config appsettings set \
  --name myAgilityApp \
  --resource-group myResourceGroup \
  --settings \
    AppSettings__InstanceGUID=your-guid \
    AppSettings__SecurityKey=your-key \
    AppSettings__FetchAPIKey=defaultlive.your-key \
    AppSettings__PreviewAPIKey=defaultpreview.your-key

# Enable WebSockets (required for Blazor)
az webapp config set \
  --name myAgilityApp \
  --resource-group myResourceGroup \
  --web-sockets-enabled true

# Deploy code
az webapp deployment source config-local-git \
  --name myAgilityApp \
  --resource-group myResourceGroup

# Push to deploy
git remote add azure <deployment-url>
git push azure main

Using GitHub Actions

Create .github/workflows/azure-deploy.yml:

name: Deploy to Azure

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.0.x'

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: |
          cd Agility.NET.Blazor.Starter
          dotnet restore
          npm install

      - name: Build
        run: |
          cd Agility.NET.Blazor.Starter
          dotnet publish -c Release -o ./publish

      - name: Deploy to Azure
        uses: azure/webapps-deploy@v3
        with:
          app-name: ${{ secrets.AZURE_APP_NAME }}
          publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
          package: ./Agility.NET.Blazor.Starter/publish

Setup:

  1. Go to Azure Portal > Your App Service > Deployment Center
  2. Download the publish profile
  3. Add it as a GitHub secret named AZURE_PUBLISH_PROFILE
  4. Add your app name as AZURE_APP_NAME

Post-Deployment Configuration

1. Configure Environment Variables

In Azure Portal:

  1. Go to your App Service
  2. Navigate to Settings > Environment variables
  3. Add application settings:
NameValue
AppSettings__InstanceGUIDYour instance GUID
AppSettings__SecurityKeyYour security key
AppSettings__FetchAPIKeyYour live API key
AppSettings__PreviewAPIKeyYour preview API key
AppSettings__Localesen-us (or your locales)
AppSettings__ChannelNamewebsite
AppSettings__CacheInMinutes5
  1. Click Save and confirm restart

2. Configure Webhooks

Set up cache invalidation in Agility CMS:

  1. Go to Settings > Webhooks in Agility CMS
  2. Click Add Webhook
  3. Configure:
    • Name: Azure Cache Invalidation
    • URL: https://your-app.azurewebsites.net/api/revalidate
    • Events: Content Published, Page Published
  4. Save the webhook

3. Configure Preview URLs

Enable content preview:

  1. Go to Settings > Preview URLs in Agility CMS
  2. Add a preview URL:
    • Name: Azure Preview
    • URL: https://your-app.azurewebsites.net{path}?agilitypreviewkey={previewkey}
  3. Save

4. Custom Domain (Optional)

  1. Go to Settings > Custom domains in Azure Portal
  2. Click Add custom domain
  3. Enter your domain name
  4. Add the required DNS records
  5. Add an SSL certificate (free managed certificate available)

Monitoring and Troubleshooting

Enable Application Insights

az webapp config appsettings set \
  --name myAgilityApp \
  --resource-group myResourceGroup \
  --settings APPLICATIONINSIGHTS_CONNECTION_STRING=your-connection-string

View Logs

Log Stream (real-time):

az webapp log tail --name myAgilityApp --resource-group myResourceGroup

In Azure Portal:

  1. Go to your App Service
  2. Navigate to Monitoring > Log stream

Common Issues

502 Bad Gateway

  • Check application logs for startup errors
  • Verify .NET version matches your app
  • Ensure all environment variables are set

SignalR/WebSocket Errors (Blazor)

  1. Verify WebSockets are enabled:

    az webapp config show --name myAgilityApp --resource-group myResourceGroup \
      --query webSocketsEnabled
    
  2. Enable if needed:

    az webapp config set --name myAgilityApp --resource-group myResourceGroup \
      --web-sockets-enabled true
    

Content Not Loading

  1. Verify API keys are correct
  2. Check Agility CMS has published content
  3. Verify ChannelName matches your sitemap

Slow Cold Starts

Enable AlwaysOn to prevent cold starts:

az webapp config set --name myAgilityApp --resource-group myResourceGroup \
  --always-on true

Scaling

Vertical Scaling (Scale Up)

Change to a larger SKU:

az appservice plan update --name myAppServicePlan \
  --resource-group myResourceGroup \
  --sku S1

Horizontal Scaling (Scale Out)

Add more instances:

az appservice plan update --name myAppServicePlan \
  --resource-group myResourceGroup \
  --number-of-workers 3

Auto-Scaling

Configure auto-scale rules in Azure Portal:

  1. Go to your App Service Plan
  2. Navigate to Settings > Scale out
  3. Configure rules based on CPU, memory, or HTTP queue length

Cost Optimization

Development/Testing

  • Use B1 SKU (~$13/month)
  • Scale down when not in use
  • Use deployment slots for staging

Production

  • Use S1 or higher for production workloads
  • Enable CDN for static assets
  • Use Azure Front Door for global distribution

Free Tier Limitations

The F1 (Free) tier does not support:

  • WebSockets (required for Blazor Interactive Server)
  • AlwaysOn (causes cold starts)
  • Custom domains with SSL

Security Checklist

  • Environment variables set (not in code)
  • HTTPS enforced
  • TLS 1.2 minimum
  • API keys are not exposed
  • Webhook endpoint is secured
  • Application Insights enabled for monitoring

Next Steps