Skip to content

Azure Deployment Architecture

Deployment Flow

┌─────────────────────────────────────────────────────────────────┐
│                         Developer                                │
│                                                                   │
│  1. Edit files in website/ folder                               │
│  2. git commit -m "Update website"                              │
│  3. git push origin main                                        │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│                      GitHub Repository                           │
│                   (Stig-Johnny/nutri-e)                         │
│                                                                   │
│  • Detects push to 'main' branch                                │
│  • Checks if website/ folder changed                            │
│  • Triggers workflow: deploy-website.yml                        │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│                    GitHub Actions Runner                         │
│                    (Ubuntu Latest)                               │
│                                                                   │
│  Step 1: Checkout code                                          │
│  Step 2: Login to Azure with service principal                 │
│  Step 3: Upload website/ to Azure Storage                      │
│  Step 4: (Optional) Purge CDN cache                             │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│                    Azure Storage Account                         │
│                  (nutriewebsite.z16.web.core.windows.net)       │
│                                                                   │
│  Resource Group: nutri-e-rg                                      │
│  Location: West Europe                                           │
│  Container: $web (public read access)                           │
│                                                                   │
│  Files:                                                          │
│  ├── index.html                                                 │
│  ├── privacy.html                                               │
│  ├── terms.html                                                 │
│  ├── 404.html                                                   │
│  ├── styles.css                                                 │
│  ├── script.js                                                  │
│  └── images/                                                    │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│                      Live Website                                │
│         https://nutriewebsite.z16.web.core.windows.net         │
│                                                                   │
│  ✅ Publicly accessible                                         │
│  ✅ HTTPS enabled                                               │
│  ✅ Custom 404 page                                             │
│  ✅ Updates in ~30 seconds                                      │
└─────────────────────────────────────────────────────────────────┘

Optional: CDN Layer

┌─────────────────────────────────────────────────────────────────┐
│                      Azure CDN                                   │
│                 (nutri-e.azureedge.net)                         │
│                                                                   │
│  • Global content delivery                                       │
│  • Caching at edge locations                                    │
│  • Custom domain support                                        │
│  • SSL/TLS certificates                                         │
│  • DDoS protection                                              │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│                   Custom Domain                                  │
│                 https://www.nutri-e.com                         │
│                                                                   │
│  CNAME → nutri-e.azureedge.net                                  │
│  ✅ HTTPS with managed certificate                              │
│  ✅ Automatic renewal                                           │
└─────────────────────────────────────────────────────────────────┘

Security Layer

┌─────────────────────────────────────────────────────────────────┐
│                  GitHub Secrets (Encrypted)                      │
│                                                                   │
│  AZURE_CREDENTIALS       → Service Principal JSON               │
│  AZURE_STORAGE_ACCOUNT   → Storage account name                 │
│  AZURE_RESOURCE_GROUP    → Resource group name                  │
│  AZURE_CDN_PROFILE       → CDN profile (optional)               │
│  AZURE_CDN_ENDPOINT      → CDN endpoint (optional)              │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│              Azure Service Principal                             │
│                                                                   │
│  Role: Contributor                                               │
│  Scope: /subscriptions/.../resourceGroups/nutri-e-rg           │
│  Permissions:                                                    │
│    ✅ Read storage account                                      │
│    ✅ Write blobs to $web container                             │
│    ✅ List containers                                           │
│    ❌ Delete resources (restricted)                             │
│    ❌ Modify subscriptions (restricted)                         │
└─────────────────────────────────────────────────────────────────┘

Timeline

0s    Developer pushes to GitHub
├─ 5s    GitHub detects push, checks path filter
├─ 10s   Workflow starts, Ubuntu runner spins up
├─ 15s   Code checked out, Azure CLI installed
├─ 20s   Azure login with service principal
├─ 25s   Files uploaded to $web container
├─ 30s   (Optional) CDN cache purged
└─ 30s   ✅ Website live with updates!

File Structure

nutri-e/
├── .github/
│   └── workflows/
│       └── deploy-website.yml          # GitHub Action workflow
├── website/                             # Source files (deployed)
│   ├── index.html
│   ├── privacy.html
│   ├── terms.html
│   ├── 404.html
│   ├── styles.css
│   ├── script.js
│   └── images/
├── azure-setup.sh                       # Setup automation
├── AZURE_QUICKSTART.md                  # Quick start guide
├── AZURE_DEPLOYMENT.md                  # Full documentation
└── DEPLOYMENT_FLOW.md                   # This file

Monitoring

GitHub Actions

  • View workflow runs: https://github.com/Stig-Johnny/nutri-e/actions
  • Check logs for each step
  • See deployment history

Azure Portal

  • Storage metrics: Transactions, bandwidth, errors
  • Access logs: Who accessed what and when
  • Cost analysis: Daily/monthly spending

Azure CLI

# View recent deployments
az storage blob list \
  --account-name nutriewebsite \
  --container-name '$web' \
  --query '[].{Name:name, LastModified:properties.lastModified}'

# Check storage metrics
az monitor metrics list \
  --resource <storage-resource-id> \
  --metric Transactions

Rollback Procedure

If something goes wrong:

Method 1: Revert GitHub Commit

git revert HEAD
git push origin main
# Automatic redeployment with previous version

Method 2: Redeploy Previous Version

git checkout <previous-commit>
git checkout -b hotfix
git push origin hotfix
# Manually trigger workflow for hotfix branch

Method 3: Manual Upload

az storage blob upload-batch \
  --account-name nutriewebsite \
  --source ./backup/website \
  --destination '$web' \
  --overwrite true

Disaster Recovery

Backup

  • Azure Storage has built-in versioning (can be enabled)
  • Git repository serves as source of truth
  • All versions are in Git history

Recovery

  1. Delete corrupted storage account
  2. Run ./azure-setup.sh to recreate
  3. Push to main branch to redeploy
  4. Update GitHub secrets if needed

Performance Optimization

Without CDN

  • Latency: 50-200ms (depending on user location)
  • Throughput: Limited by Azure Storage limits
  • Caching: Browser cache only

With CDN

  • Latency: 10-50ms (served from edge locations)
  • Throughput: Unlimited (CDN handles traffic)
  • Caching: Edge + browser cache
  • Cost: Lower (reduced bandwidth from storage)

Cost Breakdown

Basic Setup (Storage Only)

Storage:     0.5 GB × $0.02/GB    = $0.01/month
Bandwidth:   10 GB × $0.08/GB     = $0.80/month
Operations:  50K × $0.005/10K     = $0.03/month
                            Total = $0.84/month

With CDN

Storage:     0.5 GB × $0.02/GB    = $0.01/month
CDN Data:    10 GB × $0.06/GB     = $0.60/month
Operations:  50K × $0.005/10K     = $0.03/month
                            Total = $0.64/month
(Cheaper due to reduced storage egress!)

Troubleshooting Quick Reference

Issue Solution
GitHub Action fails authentication Regenerate AZURE_CREDENTIALS
Website not updating Check workflow ran, clear cache
404 on all pages Check files uploaded to $web
Slow performance Enable CDN
High costs Review bandwidth usage, enable CDN
Storage name taken Use unique name in setup script