20 KiB
🚀 Deployment Prerequisites Guide
Complete guide for setting up MS Azure, MS Entra, Cloudflare, and all other services required for production deployment.
📋 Table of Contents
- Azure Setup
- MS Entra (Azure AD) Configuration
- Cloudflare Configuration
- Stripe Configuration
- Environment Variables
- Pre-Deployment Checklist
- Post-Deployment Verification
1. Azure Setup
1.1 Prerequisites
- Azure subscription with Contributor or Owner role
- Azure CLI installed and configured
- Bicep CLI installed (optional, for local validation)
- PowerShell 7+ (for deployment scripts)
1.2 Initial Azure Configuration
Login to Azure
# Login to Azure
az login
# Verify subscription
az account show
# Set default subscription (if multiple)
az account set --subscription "Your Subscription ID"
Create Resource Group
# Create resource group for production
az group create \
--name rg-miraclesinmotion-prod \
--location eastus2
# Verify resource group
az group show --name rg-miraclesinmotion-prod
1.3 Required Azure Services
The infrastructure deployment will create:
- Azure Static Web Apps (Standard SKU) - Frontend hosting
- Azure Functions (Premium EP1) - Backend API
- Azure Cosmos DB - Database
- Azure Key Vault - Secrets management
- Azure Application Insights - Monitoring
- Log Analytics Workspace - Logging
- Azure SignalR - Real-time communications
- Storage Account - Function app storage
1.4 Deploy Infrastructure
# Navigate to infrastructure directory
cd infrastructure
# Deploy production infrastructure
az deployment group create \
--resource-group rg-miraclesinmotion-prod \
--template-file main-production.bicep \
--parameters main-production.parameters.json \
--parameters stripePublicKey="pk_live_YOUR_KEY" \
--parameters customDomainName="miraclesinmotion.org" \
--parameters enableCustomDomain=true
# Note: Replace pk_live_YOUR_KEY with your actual Stripe public key
1.5 Get Deployment Outputs
# Get deployment outputs
az deployment group show \
--resource-group rg-miraclesinmotion-prod \
--name deployment-name \
--query properties.outputs
Important Outputs:
staticWebAppName- Static Web App resource namestaticWebAppUrl- Default URL for Static Web AppfunctionAppName- Function App resource namekeyVaultName- Key Vault resource nameappInsightsName- Application Insights resource name
2. MS Entra (Azure AD) Configuration
2.1 Create App Registration
Using Azure Portal
-
Navigate to Azure Portal → Microsoft Entra ID → App registrations
-
Click + New registration
-
Configure:
- Name:
Miracles In Motion Web App - Supported account types:
Accounts in any organizational directory and personal Microsoft accounts - Redirect URI:
- Type:
Single-page application (SPA) - URI:
https://miraclesinmotion.org(production) - URI:
https://YOUR_STATIC_WEB_APP.azurestaticapps.net(staging)
- Type:
- Name:
-
Click Register
Using Azure CLI
# Create app registration
az ad app create \
--display-name "Miracles In Motion Web App" \
--sign-in-audience "AzureADMultipleOrgs" \
--web-redirect-uris "https://miraclesinmotion.org" "https://www.miraclesinmotion.org"
# Get app registration ID
APP_ID=$(az ad app list --display-name "Miracles In Motion Web App" --query "[0].appId" -o tsv)
echo "App ID: $APP_ID"
2.2 Configure Authentication
- In the app registration, go to Authentication
- Enable ID tokens (used for implicit and hybrid flows)
- Add redirect URIs:
https://miraclesinmotion.orghttps://www.miraclesinmotion.orghttps://YOUR_STATIC_WEB_APP.azurestaticapps.net
- Under Implicit grant and hybrid flows, enable:
- ✅ ID tokens
- Save changes
2.3 Configure API Permissions
- Go to API permissions
- Click + Add a permission
- Select Microsoft Graph
- Add the following Delegated permissions:
User.Read- Read user profileUser.ReadBasic.All- Read all users' basic profilesemail- View users' email addressopenid- Sign users inprofile- View users' basic profile
- Click Add permissions
- Click Grant admin consent (if you have admin rights)
2.4 Create Client Secret (Optional - for server-side flows)
# Create client secret (valid for 24 months)
az ad app credential reset \
--id $APP_ID \
--display-name "Miracles In Motion Secret" \
--years 2
# Save the secret value immediately - it won't be shown again!
2.5 Configure App Roles
-
Go to App roles → + Create app role
-
Create roles:
-
Display name:
Admin- Allowed member types:
Users/Groups - Value:
Admin - Description:
Administrator access to all features
- Allowed member types:
-
Display name:
Volunteer- Allowed member types:
Users/Groups - Value:
Volunteer - Description:
Volunteer access to assigned tasks
- Allowed member types:
-
Display name:
Resource- Allowed member types:
Users/Groups - Value:
Resource - Description:
Resource provider access
- Allowed member types:
-
-
Save each role
2.6 Assign Users to Roles
# Get user object ID
USER_ID=$(az ad user show --id "user@domain.com" --query "id" -o tsv)
# Get app role ID (Admin role)
ROLE_ID=$(az ad app show --id $APP_ID --query "appRoles[?value=='Admin'].id" -o tsv)
# Assign user to role
az ad app assignment create \
--app-id $APP_ID \
--principal-id $USER_ID \
--role-id $ROLE_ID
2.7 Configure Static Web App Authentication
- Navigate to Static Web App → Authentication
- Click Add identity provider
- Select Microsoft
- Configure:
- App registration: Select your app registration
- App ID: Your app registration ID
- App secret setting name:
MICROSOFT_CLIENT_SECRET(optional)
- Save
Using Azure CLI
# Get Static Web App resource ID
SWA_ID=$(az staticwebapp show \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod \
--query "id" -o tsv)
# Configure Microsoft identity provider
az staticwebapp identity assign \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod
# Note: Static Web Apps authentication is configured via Azure Portal
# or through the staticwebapp.config.json file
2.8 Update staticwebapp.config.json
The staticwebapp.config.json file should include authentication configuration:
{
"routes": [
{
"route": "/api/*",
"allowedRoles": ["anonymous", "authenticated"]
},
{
"route": "/admin/*",
"allowedRoles": ["Admin"]
},
{
"route": "/volunteer/*",
"allowedRoles": ["Volunteer", "Admin"]
},
{
"route": "/*",
"rewrite": "/index.html"
}
],
"auth": {
"identityProviders": {
"azureActiveDirectory": {
"registration": {
"openIdIssuer": "https://login.microsoftonline.com/{tenantId}/v2.0",
"clientIdSettingName": "AZURE_CLIENT_ID",
"clientSecretSettingName": "AZURE_CLIENT_SECRET"
}
}
}
},
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/api/*", "/admin/*"]
}
}
2.9 Store Configuration in Key Vault
# Store Azure AD configuration in Key Vault
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "azure-client-id" \
--value "$APP_ID"
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "azure-client-secret" \
--value "YOUR_CLIENT_SECRET"
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "azure-tenant-id" \
--value "$(az account show --query tenantId -o tsv)"
3. Cloudflare Configuration
3.1 Prerequisites
- Cloudflare account
- Domain registered and added to Cloudflare
- DNS management access
3.2 Add Domain to Cloudflare
- Log in to Cloudflare Dashboard
- Click Add a site
- Enter your domain:
miraclesinmotion.org - Select a plan (Free plan is sufficient for basic needs)
- Cloudflare will scan your existing DNS records
3.3 Update Nameservers
- Copy the nameservers provided by Cloudflare
- Update your domain registrar with these nameservers
- Wait for DNS propagation (24-48 hours)
3.4 Configure DNS Records
Add CNAME Records
- Go to DNS → Records
- Add the following records:
| Type | Name | Content | Proxy | TTL |
|---|---|---|---|---|
| CNAME | www | YOUR_STATIC_WEB_APP.azurestaticapps.net | ✅ Proxied | Auto |
| CNAME | @ | YOUR_STATIC_WEB_APP.azurestaticapps.net | ✅ Proxied | Auto |
Note: Replace YOUR_STATIC_WEB_APP with your actual Static Web App name.
Verify DNS Configuration
# Check DNS records
dig miraclesinmotion.org
dig www.miraclesinmotion.org
# Check Cloudflare proxy status
curl -I https://miraclesinmotion.org
# Look for "CF-Cache-Status" header
3.5 Configure SSL/TLS
- Go to SSL/TLS → Overview
- Select Full (strict) encryption mode
- Enable Always Use HTTPS
- Enable Automatic HTTPS Rewrites
3.6 Configure Page Rules
- Go to Rules → Page Rules
- Create rules:
Rule 1: Force HTTPS
- URL:
*miraclesinmotion.org/* - Settings:
- Always Use HTTPS: ✅ On
- SSL: Full (strict)
Rule 2: Cache Static Assets
- URL:
*miraclesinmotion.org/assets/* - Settings:
- Cache Level: Cache Everything
- Edge Cache TTL: 1 month
3.7 Configure Security Settings
- Go to Security → Settings
- Configure:
- Security Level: Medium
- Challenge Passage: 30 minutes
- Browser Integrity Check: On
- Privacy Pass Support: On
3.8 Configure Firewall Rules
- Go to Security → WAF → Custom rules
- Create rules to block malicious traffic:
Rule: Block Bad Bots
- Expression:
(http.user_agent contains "bot" and not http.user_agent contains "Googlebot") - Action: Block
Rule: Rate Limiting
- Expression:
(http.request.uri.path contains "/api/") - Action: Challenge
- Rate: 100 requests per minute
3.9 Configure Speed Optimization
- Go to Speed → Optimization
- Enable:
- ✅ Auto Minify (JavaScript, CSS, HTML)
- ✅ Brotli compression
- ✅ Rocket Loader (optional)
- ✅ Mirage (optional, for mobile)
3.10 Configure Analytics
- Go to Analytics → Web Analytics
- Enable Web Analytics for your domain
- Add the tracking script to your application (optional)
3.11 Configure Custom Domain in Azure
After DNS is configured:
# Add custom domain to Static Web App
az staticwebapp hostname set \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod \
--hostname "miraclesinmotion.org"
az staticwebapp hostname set \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod \
--hostname "www.miraclesinmotion.org"
Note: Azure will automatically provision SSL certificates for custom domains.
3.12 Verify Cloudflare Configuration
# Test DNS resolution
nslookup miraclesinmotion.org
nslookup www.miraclesinmotion.org
# Test HTTPS
curl -I https://miraclesinmotion.org
# Test Cloudflare headers
curl -I https://miraclesinmotion.org | grep -i "cf-"
# Expected headers:
# CF-Cache-Status: DYNAMIC
# CF-Ray: [unique-id]
# Server: cloudflare
4. Stripe Configuration
4.1 Create Stripe Account
- Go to Stripe Dashboard
- Create account or log in
- Complete account verification
4.2 Get API Keys
- Go to Developers → API keys
- Copy:
- Publishable key (starts with
pk_live_) - Secret key (starts with
sk_live_) - Keep this secret!
- Publishable key (starts with
4.3 Configure Webhooks
- Go to Developers → Webhooks
- Click + Add endpoint
- Configure:
- Endpoint URL:
https://miraclesinmotion.org/api/webhooks/stripe - Events to send: Select relevant events:
payment_intent.succeededpayment_intent.payment_failedcharge.succeededcharge.failed
- Endpoint URL:
- Copy the Webhook signing secret (starts with
whsec_)
4.4 Store Stripe Secrets in Key Vault
# Store Stripe keys in Key Vault
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "stripe-publishable-key" \
--value "pk_live_YOUR_KEY"
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "stripe-secret-key" \
--value "sk_live_YOUR_KEY"
az keyvault secret set \
--vault-name YOUR_KEY_VAULT_NAME \
--name "stripe-webhook-secret" \
--value "whsec_YOUR_SECRET"
4.5 Update Function App Settings
# Get secrets from Key Vault
STRIPE_SECRET=$(az keyvault secret show \
--vault-name YOUR_KEY_VAULT_NAME \
--name "stripe-secret-key" \
--query "value" -o tsv)
# Update Function App settings
az functionapp config appsettings set \
--name YOUR_FUNCTION_APP_NAME \
--resource-group rg-miraclesinmotion-prod \
--settings "STRIPE_SECRET_KEY=@Microsoft.KeyVault(SecretUri=https://YOUR_KEY_VAULT_NAME.vault.azure.net/secrets/stripe-secret-key/)"
5. Environment Variables
5.1 Create Environment File Template
Create .env.production file:
# Azure Configuration
AZURE_STATIC_WEB_APP_URL=https://miraclesinmotion.org
AZURE_FUNCTION_APP_URL=https://YOUR_FUNCTION_APP.azurewebsites.net
AZURE_CLIENT_ID=your-azure-client-id
AZURE_TENANT_ID=your-azure-tenant-id
# Stripe Configuration
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_KEY
STRIPE_SECRET_KEY=sk_live_YOUR_KEY
STRIPE_WEBHOOK_SECRET=whsec_YOUR_SECRET
# Cosmos DB Configuration
COSMOS_DATABASE_NAME=MiraclesInMotion
COSMOS_ENDPOINT=https://YOUR_COSMOS_ACCOUNT.documents.azure.com:443/
# Application Insights
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=YOUR_KEY
# Key Vault
KEY_VAULT_URL=https://YOUR_KEY_VAULT_NAME.vault.azure.net/
# SignalR
SIGNALR_CONNECTION_STRING=Endpoint=https://YOUR_SIGNALR.service.signalr.net;AccessKey=YOUR_KEY;
# Custom Domain
CUSTOM_DOMAIN=miraclesinmotion.org
5.2 Update Static Web App Configuration
# Set environment variables for Static Web App
az staticwebapp appsettings set \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod \
--setting-names "VITE_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_KEY" \
"AZURE_CLIENT_ID=your-azure-client-id" \
"AZURE_TENANT_ID=your-azure-tenant-id"
6. Pre-Deployment Checklist
6.1 Azure Checklist
- Azure subscription created and active
- Resource group created
- Infrastructure deployed via Bicep
- All Azure resources created successfully
- Key Vault configured with secrets
- Application Insights configured
- Static Web App created
- Function App created and configured
- Cosmos DB database and containers created
- RBAC permissions configured
6.2 MS Entra Checklist
- App registration created
- Redirect URIs configured
- API permissions granted
- App roles created (Admin, Volunteer, Resource)
- Users assigned to roles
- Client ID and Tenant ID recorded
- Client secret created (if needed)
- Static Web App authentication configured
6.3 Cloudflare Checklist
- Domain added to Cloudflare
- Nameservers updated at registrar
- DNS records configured (CNAME for www and @)
- SSL/TLS set to Full (strict)
- Always Use HTTPS enabled
- Page rules configured
- Firewall rules configured
- Security settings configured
- Speed optimization enabled
- Custom domain added to Azure Static Web App
6.4 Stripe Checklist
- Stripe account created and verified
- API keys obtained (publishable and secret)
- Webhook endpoint configured
- Webhook signing secret obtained
- Secrets stored in Key Vault
- Function App configured with Stripe keys
6.5 Application Checklist
- Environment variables configured
- staticwebapp.config.json updated
- Authentication flow tested
- API endpoints tested
- Stripe integration tested
- Monitoring configured
- Logging configured
7. Post-Deployment Verification
7.1 Verify Azure Resources
# Check Static Web App status
az staticwebapp show \
--name YOUR_STATIC_WEB_APP_NAME \
--resource-group rg-miraclesinmotion-prod
# Check Function App status
az functionapp show \
--name YOUR_FUNCTION_APP_NAME \
--resource-group rg-miraclesinmotion-prod
# Check Cosmos DB status
az cosmosdb show \
--name YOUR_COSMOS_ACCOUNT \
--resource-group rg-miraclesinmotion-prod
7.2 Verify Authentication
- Navigate to
https://miraclesinmotion.org - Click "Sign In"
- Verify Microsoft authentication flow
- Verify user roles are assigned correctly
- Test role-based access control
7.3 Verify Cloudflare
# Test DNS resolution
dig miraclesinmotion.org
dig www.miraclesinmotion.org
# Test HTTPS
curl -I https://miraclesinmotion.org
# Verify Cloudflare headers
curl -I https://miraclesinmotion.org | grep -i "cf-"
7.4 Verify Stripe Integration
- Test donation flow on the website
- Verify webhook events are received
- Check Stripe dashboard for transactions
- Verify payment processing
7.5 Verify Monitoring
- Check Application Insights for telemetry
- Verify logs are being collected
- Set up alerts for critical issues
- Test error tracking
7.6 Performance Testing
# Test page load times
curl -w "@curl-format.txt" -o /dev/null -s https://miraclesinmotion.org
# Test API response times
curl -w "@curl-format.txt" -o /dev/null -s https://miraclesinmotion.org/api/donations
8. Troubleshooting
8.1 Common Issues
Authentication Not Working
- Verify app registration redirect URIs
- Check Static Web App authentication configuration
- Verify user roles are assigned
- Check browser console for errors
DNS Not Resolving
- Verify nameservers are updated
- Wait for DNS propagation (24-48 hours)
- Check Cloudflare DNS records
- Verify CNAME records point to correct Azure endpoint
SSL Certificate Issues
- Verify Cloudflare SSL mode is "Full (strict)"
- Check Azure Static Web App custom domain configuration
- Wait for SSL certificate provisioning (can take up to 24 hours)
Stripe Webhook Not Working
- Verify webhook endpoint URL is correct
- Check webhook signing secret
- Verify Function App is receiving webhook events
- Check Function App logs for errors
8.2 Support Resources
- Azure Documentation: https://docs.microsoft.com/azure
- MS Entra Documentation: https://docs.microsoft.com/azure/active-directory
- Cloudflare Documentation: https://developers.cloudflare.com
- Stripe Documentation: https://stripe.com/docs
9. Next Steps
After completing all prerequisites:
- Deploy the application using the deployment script
- Verify all functionality
- Set up monitoring and alerts
- Configure backup and disaster recovery
- Set up CI/CD pipeline
- Schedule regular security audits
- Set up performance monitoring
10. Security Best Practices
- Never commit secrets to source control
- Use Key Vault for all secrets
- Enable MFA for all Azure accounts
- Regularly rotate API keys and secrets
- Monitor for suspicious activity
- Keep dependencies updated
- Use HTTPS everywhere
- Implement rate limiting
- Regular security audits
- Follow principle of least privilege
Last Updated: January 2025 Maintained by: Miracles In Motion Development Team