Deploy a complete Azure Virtual Desktop environment with Azure Image Builder support - fully automated with Terraform following AVD Accelerator best practices.
This Terraform configuration deploys a comprehensive, production-ready AVD environment with the following architecture:
graph TB
%% User Access Layer
subgraph "User Access"
USER[π€ End Users]
CLIENT[π₯οΈ AVD Client / Browser]
end
%% Azure Virtual Desktop Control Plane
subgraph "AVD Control Plane (rg-avd-services)"
WS[π AVD Workspace<br/>ws-avd-prod]
HP[π’ Host Pool<br/>hp-avd-prod<br/>Pooled/Personal]
DAG[π± Desktop App Group<br/>dag-avd-prod]
SP[βοΈ Scaling Plan<br/>sp-avd-prod<br/>Auto Scale]
end
%% Session Hosts
subgraph "Session Hosts (rg-avd-session-hosts)"
subgraph "Existing VNet"
subgraph "AVD Subnet"
SH1[π₯οΈ Session Host 1<br/>avd-sh-1]
SH2[π₯οΈ Session Host 2<br/>avd-sh-2]
SH3[π₯οΈ Session Host 3<br/>avd-sh-3]
end
end
end
%% Shared Services
subgraph "Shared Services (rg-avd-shared-services)"
%% Storage
SA[πΎ Storage Account<br/>stfslogixavdprod001<br/>FSLogix Profiles]
FS[π File Share<br/>fslogix-profiles]
%% Key Vault
KV[οΏ½οΏ½ Key Vault<br/>kv-avd-prod-001<br/>VM Passwords & Secrets]
%% Monitoring
LAW[π Log Analytics<br/>law-avd-prod<br/>Centralized Logging]
%% Image Builder
GAL[ποΈ Compute Gallery<br/>gal_avd_prod]
IMG[πΌοΈ Custom Image<br/>avd-win11-22h2<br/>Win11 + FSLogix]
AIB[βοΈ Azure Image Builder<br/>Custom Image Creation]
MSI[π Managed Identity<br/>AIB Service Identity]
end
%% Azure AD / Active Directory
subgraph "Identity"
AAD[βοΈ Azure AD<br/>or<br/>π’ Active Directory]
end
%% Connections - User Flow
USER --> CLIENT
CLIENT --> WS
WS --> DAG
DAG --> HP
HP --> SH1
HP --> SH2
HP --> SH3
%% Session Host Dependencies
SH1 --> FS
SH2 --> FS
SH3 --> FS
SA --> FS
SH1 --> AAD
SH2 --> AAD
SH3 --> AAD
SH1 --> IMG
SH2 --> IMG
SH3 --> IMG
%% Scaling
SP --> HP
%% Image Builder Flow
AIB --> GAL
GAL --> IMG
MSI --> AIB
%% Monitoring & Security
HP --> LAW
WS --> LAW
SH1 --> LAW
SH2 --> LAW
SH3 --> LAW
SH1 -.-> KV
SH2 -.-> KV
SH3 -.-> KV
%% RBAC for Storage
SH1 -.-> SA
SH2 -.-> SA
SH3 -.-> SA
%% Styling
classDef userAccess fill:#e1f5fe,stroke:#01579b,stroke-width:2px
classDef avdControl fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
classDef sessionHost fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px
classDef sharedServices fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef identity fill:#fce4ec,stroke:#880e4f,stroke-width:2px
class USER,CLIENT userAccess
class WS,HP,DAG,SP avdControl
class SH1,SH2,SH3 sessionHost
class SA,FS,KV,LAW,GAL,IMG,AIB,MSI sharedServices
class AAD identity
Component | Resource Name | Purpose |
---|---|---|
π’ Host Pool | hp-avd-prod |
Central AVD resource managing session hosts |
π₯οΈ Session Hosts | avd-sh-1,2,3 |
Windows 11 VMs with AVD agents |
οΏ½οΏ½ Key Vault | kv-avd-prod-001 |
Secure storage for VM passwords |
πΎ Storage Account | stfslogixavdprod001 |
FSLogix profile storage with RBAC |
π Log Analytics | law-avd-prod |
Centralized monitoring and diagnostics |
ποΈ Compute Gallery | gal_avd_prod |
Custom image storage and versioning |
βοΈ Image Builder | AIB Template | Automated custom image creation |
βοΈ Scaling Plan | sp-avd-prod |
Intelligent auto-scaling during business hours |
- π§ Azure Image Builder Integration: Automated custom image creation with Windows 11 + FSLogix
- π Existing Network Support: Works seamlessly with your hub-spoke architecture
- π Security First: Key Vault integration, RBAC, network restrictions, and managed identities
- οΏ½οΈ Private Endpoints: Optional private endpoint deployment for maximum security isolation
- οΏ½π Auto Scaling: Built-in scaling plans for intelligent cost optimization
- π Full Observability: Log Analytics with comprehensive diagnostic settings
- β‘ Domain Flexibility: Supports both Azure AD and Active Directory Domain Services
- π AVD Accelerator Aligned: Follows Microsoft's recommended best practices
- Azure CLI and Terraform installed
- Owner permissions on target Azure subscription
- Existing virtual network (or modify to create new one)
# 1. Clone and navigate
git clone https://github.com/travishankins/terraform-avd-deployment.git
cd terraform-avd-deployment
# 2. Login to Azure
az login
az account set --subscription "<your-subscription-id>"
# 3. Customize configuration (choose one option):
# Option A: Standard deployment with network restrictions
cp terraform.tfvars terraform.tfvars.local
# Edit terraform.tfvars.local with your specific values
# Option B: High-security deployment with private endpoints
cp terraform.tfvars.private-endpoints terraform.tfvars.local
# Edit terraform.tfvars.local with your specific values
# 4. Deploy infrastructure
terraform init
terraform plan -var-file="terraform.tfvars.local"
terraform apply -var-file="terraform.tfvars.local"
# 5. Build custom image (if enabled)
# The image template will be created, trigger build via:
# az image builder run --name <template-name> --resource-group <rg-name>
Variable | Description | Default |
---|---|---|
location |
Azure region | "East US" |
prefix |
Resource name prefix | "avd" |
use_existing_network |
Use existing VNet | true |
enable_private_endpoints |
Deploy services behind private endpoints | false |
enable_image_builder |
Create AIB resources | false |
session_host_count |
Number of session hosts | 2 |
domain_join_type |
"AzureAD" or "ActiveDirectory" |
"AzureAD" |
# For existing network
use_existing_network = true
existing_vnet_name = "vnet-hub-prod"
existing_vnet_rg_name = "rg-network-prod"
existing_subnet_name = "snet-avd-session-hosts"
# Enable custom image creation
enable_image_builder = true
aib_build_timeout = 120
aib_vm_size = "Standard_D2s_v3"
# Custom image configuration
use_custom_image = true
For maximum security, enable private endpoints to isolate all Azure services from public internet access:
# Enable private endpoints for all supported services
enable_private_endpoints = true
private_endpoint_subnet_name = "snet-private-endpoints"
create_private_dns_zones = true # Automatically create private DNS zones
# Services secured with private endpoints:
# - Storage Account (Blob & File endpoints)
# - Key Vault
# - Compute Gallery
# - Log Analytics (future enhancement)
Prerequisites for Private Endpoints:
- Dedicated subnet for private endpoints (
snet-private-endpoints
) - Network security group rules allowing private endpoint traffic
- DNS resolution configured (automatically handled if
create_private_dns_zones = true
)
Example network setup:
# Your VNet should have these subnets:
# - snet-avd-session-hosts (for session host VMs)
# - snet-private-endpoints (for private endpoints)
.
βββ main.tf # Main infrastructure resources
βββ variables.tf # Variable definitions
βββ outputs.tf # Resource outputs
βββ versions.tf # Provider version constraints
βββ terraform.tfvars # Default variable values
βββ terraform.tfvars.private-endpoints # Example config with private endpoints
βββ .gitignore # Git ignore rules
βββ README.md # This file
The repository includes example configurations for different security postures:
terraform.tfvars
: Standard deployment with network restrictionsterraform.tfvars.private-endpoints
: Enhanced security with private endpoints
Recommended approach:
- Copy one of the example files to
terraform.tfvars.local
- Customize
terraform.tfvars.local
with your specific values - Use
terraform.tfvars.local
for deployment (this file is automatically ignored by git)
Quick deployment options:
# Standard security deployment
terraform apply -var-file="terraform.tfvars"
# High-security deployment with private endpoints
terraform apply -var-file="terraform.tfvars.private-endpoints"
# Custom deployment (after copying and editing)
terraform apply -var-file="terraform.tfvars.local"
The scaling plan is configured with intelligent business hours scaling:
- Ramp Up (8:00 AM): Prepare hosts for the day
- Peak Hours (9:00 AM - 6:00 PM): Maximum availability
- Ramp Down (6:00 PM): Graceful user logout with 30-min warning
- Off Peak (8:00 PM): Minimal hosts for cost optimization
domain_join_type = "ActiveDirectory"
domain_name = "contoso.com"
domain_ou_path = "OU=AVD,DC=contoso,DC=com"
domain_join_username = "avdjoin"
domain_join_password = "SecurePassword123!"
- Host Pool: Connection and session metrics
- Session Hosts: CPU, memory, disk usage
- Storage Account: FSLogix profile performance
- Image Builder: Build success/failure logs
- Image Build Failures: Check AIB logs in Log Analytics
- Domain Join Issues: Verify credentials and OU path
- Storage Access: Ensure RBAC assignments completed
- Network Connectivity: Verify subnet and NSG rules
After deployment, key information is available via outputs:
# Get workspace information
terraform output workspace_name
terraform output workspace_id
# Get storage details
terraform output file_share_url
terraform output storage_account_name
# Get registration token (sensitive)
terraform output -raw host_pool_registration_token
- VM passwords stored in Key Vault
- Registration tokens automatically rotate every 29 days
- Storage access restricted via network rules and RBAC
- Image Builder uses managed identity with least privilege
- Diagnostic logs sent to Log Analytics for monitoring
When enable_private_endpoints = true
, the following security enhancements are applied:
Network Isolation:
- All Azure services are accessible only through private IP addresses
- Public internet access is completely disabled for protected services
- Traffic flows entirely within your virtual network
Services Protected:
- Storage Account: Both Blob and File endpoints secured
- Key Vault: All secret access through private network only
- Compute Gallery: Custom image access via private endpoints
- Private DNS: Automatic DNS resolution for private endpoints
Zero Trust Architecture:
- No data leaves your virtual network perimeter
- Eliminates attack surface from public internet
- Compliance with strict security requirements (PCI DSS, HIPAA, etc.)
# Remove all resources (using your customized configuration)
terraform destroy -var-file="terraform.tfvars.local"
# Alternative: Use specific configuration files directly
# terraform destroy -var-file="terraform.tfvars"
# terraform destroy -var-file="terraform.tfvars.private-endpoints"
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Create an issue for bug reports
- Check Azure AVD documentation
- Review AVD Accelerator for additional patterns
Built with β€οΈ following Azure Virtual Desktop best practices