Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1680434
First static frontend version
fedemaleh Jan 9, 2026
8cc2528
Add makefile for unit and tofu tests
fedemaleh Jan 13, 2026
83cb7b6
Testing improvements
fedemaleh Jan 13, 2026
cf3ce0e
Add logs and better integration test setup
fedemaleh Jan 14, 2026
7c5c3fa
Improve integration tests
fedemaleh Jan 16, 2026
030b3ba
Add missing unit tests
fedemaleh Jan 16, 2026
5ef19d3
Azure without integration tests
fedemaleh Jan 19, 2026
b4c346b
Do tofu improvements
fedemaleh Jan 21, 2026
42261a3
First azure apps implementations + unit tests
fedemaleh Jan 21, 2026
48d5e3c
Add tofu tests
fedemaleh Jan 21, 2026
bd04570
Add integration tests + switch traffic and slot features
fedemaleh Jan 22, 2026
fdb3d59
Improve integration tests to use the actual az cli
fedemaleh Jan 23, 2026
56774ee
Update azure-apps provider selector in spec
fedemaleh Jan 26, 2026
6b9d44b
Read azure variables from providers
fedemaleh Jan 27, 2026
c67b3be
Fix azure setup
fedemaleh Jan 27, 2026
827cd40
Fix parameter handling
fedemaleh Jan 27, 2026
7c46e1c
Add free tier machine
fedemaleh Jan 27, 2026
4cd9eff
use australia location
fedemaleh Jan 27, 2026
f947122
Add missing docker server credentials
fedemaleh Jan 27, 2026
f58b56b
Fix integration test + backend setup
fedemaleh Jan 27, 2026
9e62b74
Fix docker setup
fedemaleh Jan 27, 2026
68e19da
Add backend provider
fedemaleh Jan 27, 2026
9c45ddc
Remove unnecesary exec
fedemaleh Jan 27, 2026
06eda24
Fix traffic management
fedemaleh Jan 27, 2026
94634d0
do not execute terra for switch traffic
fedemaleh Jan 27, 2026
2e06a05
fix rollback after switch traffic
fedemaleh Jan 27, 2026
5510ab7
fix rollback after switch traffic
fedemaleh Jan 27, 2026
8b6c5d7
Add metric and logs support
fedemaleh Jan 27, 2026
b78c5b5
Fix blue green image
fedemaleh Jan 28, 2026
890d263
Fix blue green remote state fetching
fedemaleh Jan 28, 2026
441a231
Fix blue green remote state fetching
fedemaleh Jan 28, 2026
1d52b29
Fix switch traffic definition
fedemaleh Jan 28, 2026
00e3124
Fix finalize
fedemaleh Jan 28, 2026
185cc0e
Make telemetry faster
fedemaleh Jan 28, 2026
39ddcc7
Fix integration tests
fedemaleh Jan 28, 2026
d58454b
measure get logs timing
fedemaleh Jan 28, 2026
5676fd9
Fix log date filter
fedemaleh Jan 28, 2026
2321c1a
Log and metric code improvements
fedemaleh Jan 28, 2026
353ecc3
Fix cpu and memory metrics
fedemaleh Jan 28, 2026
37315a5
Metric and logs improvements
fedemaleh Jan 28, 2026
a6639dd
Fix instance paylaod
fedemaleh Jan 28, 2026
cb4690a
Remove sensitive log
fedemaleh Jan 29, 2026
f75fd38
Enable system identity
fedemaleh Jan 29, 2026
649aa98
Fix tofu test
fedemaleh Feb 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ help:
@echo ""
@echo "Options:"
@echo " MODULE=<name> Run tests for specific module (e.g., MODULE=frontend)"
@echo " VERBOSE=1 Show output of passing tests (integration tests only)"
@echo " VERBOSE=1 Show output of passing tests (integration tests only)"
242 changes: 242 additions & 0 deletions azure-apps/deployment/modules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
# Azure App Service Terraform Module

This Terraform module provisions an Azure App Service with:
- Docker container support
- Custom domain with DNS A record
- Free managed SSL certificate
- Deployment slots for blue-green / canary deployments
- Environment variables from JSON configuration

## Architecture

```
┌─────────────────────────────────────────┐
│ Azure DNS Zone │
│ (example.com) │
└──────────────┬──────────────────────────┘
┌──────────────▼──────────────┐
│ A Record / CNAME │
│ api.example.com │
└──────────────┬──────────────┘
┌──────────────▼──────────────┐
│ Custom Domain Binding │
│ + Managed SSL Cert │
└──────────────┬──────────────┘
┌─────────────────────────┴─────────────────────────┐
│ │
┌──────────▼──────────┐ ┌──────────────▼──────────┐
│ Production Slot │ ◄───── Traffic ───────► │ Staging Slot │
│ (90% traffic) │ Splitting │ (10% traffic) │
│ │ │ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ Docker Image │ │ │ │ Docker Image │ │
│ │ myapp:v1.0.0 │ │ │ │ myapp:v1.1.0 │ │
│ └───────────────┘ │ │ └───────────────┘ │
└─────────────────────┘ └─────────────────────────┘
│ │
└─────────────────────────┬─────────────────────────┘
┌──────────────▼──────────────┐
│ App Service Plan │
│ (S1 - Standard) │
└─────────────────────────────┘
```

## Prerequisites

1. Azure CLI installed and authenticated (`az login`)
2. Terraform >= 1.0
3. An existing Azure Resource Group
4. An existing Azure DNS Zone (or you can modify to create one)
5. Docker images pushed to a container registry (ACR, Docker Hub, etc.)

## Quick Start

### 1. Clone and configure

```bash
# Copy the example tfvars
cp terraform.tfvars.example terraform.tfvars

# Edit with your values
vim terraform.tfvars
```

### 2. Set sensitive variables via environment

```bash
# For Azure Container Registry
export TF_VAR_docker_registry_username="your-acr-username"
export TF_VAR_docker_registry_password="your-acr-password"

# Or use Azure managed identity (recommended for ACR)
```

### 3. Deploy

```bash
terraform init
terraform plan
terraform apply
```

## Variables

| Name | Description | Type | Required |
|------|-------------|------|----------|
| `resource_group_name` | Name of the resource group | string | yes |
| `app_name` | Globally unique name for the App Service | string | yes |
| `docker_image` | Docker image with tag (e.g., `myapp:v1.0.0`) | string | yes |
| `dns_zone_name` | Azure DNS zone name | string | yes |
| `dns_zone_resource_group` | Resource group containing DNS zone | string | yes |
| `resource_tags` | Tags to apply to resources | map(string) | no |
| `parameter_json` | JSON string with environment variables | string | no |
| `custom_subdomain` | Subdomain (use `@` for apex) | string | no |
| `docker_registry_url` | Registry URL | string | no |
| `sku_name` | App Service Plan SKU | string | no |
| `enable_staging_slot` | Create staging slot | bool | no |

## Environment Variables (parameter_json)

Pass environment variables as a JSON string:

```hcl
parameter_json = <<EOF
{
"DATABASE_URL": "postgresql://...",
"REDIS_URL": "redis://...",
"API_KEY": "secret-key",
"LOG_LEVEL": "info"
}
EOF
```

Or from a file:

```hcl
parameter_json = file("${path.module}/env.json")
```

## Traffic Management (Canary Deployments)

### Using the script

```bash
# Make executable
chmod +x scripts/traffic-management.sh

# Check current status
./scripts/traffic-management.sh my-app-rg my-awesome-app status

# Route 10% to staging (canary)
./scripts/traffic-management.sh my-app-rg my-awesome-app 10

# Increase to 50%
./scripts/traffic-management.sh my-app-rg my-awesome-app 50

# Full rollout - swap slots
./scripts/traffic-management.sh my-app-rg my-awesome-app swap

# Rollback - swap back
./scripts/traffic-management.sh my-app-rg my-awesome-app swap
```

### Canary Deployment Workflow

```
1. Deploy new version to STAGING slot
└── terraform apply (update docker_image in staging)

2. Test staging directly
└── https://my-awesome-app-staging.azurewebsites.net

3. Gradual traffic shift
└── 5% → 10% → 25% → 50% → 100%

4. Monitor metrics at each step
└── Check error rates, latency, logs

5. If issues: rollback to 0%
└── ./traffic-management.sh my-rg my-app 0

6. If successful: swap slots
└── ./traffic-management.sh my-rg my-app swap
```

## Updating Docker Image

### Update production

```hcl
# In terraform.tfvars
docker_image = "myapp:v1.1.0"
```

```bash
terraform apply
```

### Update staging only (for canary)

Modify the staging slot resource directly or use Azure CLI:

```bash
az webapp config container set \
--resource-group my-app-rg \
--name my-awesome-app \
--slot staging \
--docker-custom-image-name myapp:v1.1.0
```

## Outputs

| Name | Description |
|------|-------------|
| `app_service_default_hostname` | Default Azure hostname |
| `app_service_custom_domain` | Your custom domain |
| `staging_slot_url` | Staging slot URL |
| `app_service_outbound_ips` | IPs for firewall rules |

## Using with Azure Container Registry (ACR)

```hcl
docker_registry_url = "https://myregistry.azurecr.io"
docker_image = "myregistry.azurecr.io/myapp:v1.0.0"
docker_registry_username = "myregistry" # Or use managed identity
docker_registry_password = "access-key"
```

### Better: Use Managed Identity

```hcl
# Add to main.tf
resource "azurerm_role_assignment" "acr_pull" {
scope = data.azurerm_container_registry.acr.id
role_definition_name = "AcrPull"
principal_id = azurerm_linux_web_app.main.identity[0].principal_id
}
```

## Common Issues

### DNS propagation delay

Custom domain binding may fail if DNS hasn't propagated. Wait a few minutes and retry.

### Certificate provisioning

Free managed certificates can take 10-15 minutes to provision after domain binding.

### Slot swap issues

Ensure both slots have the same app settings structure. Use `sticky_settings` for slot-specific values.

## CI/CD Integration

See the `examples/` directory for:
- GitHub Actions workflow
- Azure DevOps pipeline
- GitLab CI configuration
Loading