Achraf Ben Alaya
No Result
View All Result
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy
SUBSCRIBE
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy
No Result
View All Result
Achraf Ben Alaya
No Result
View All Result
ADVERTISEMENT
Home Blog Cloud Azure

Step-by-Step Guide: Azure Front Door + Storage Account Static Website + Custom Domain with Terraform

achraf by achraf
March 11, 2025
in Azure, Blog, Cloud
9 min read
0
0
SHARES
526
VIEWS
Share on FacebookShare on Twitter

In this post, we will use Terraform to deploy a static website on Azure, leveraging Azure Storage and Azure Front Door. To keep things simple, I will be deploying everything from my local machine. However, in a real-world scenario, I would store the Terraform state in an Azure Storage Account, create a service principal (SPN), and set up federation with my GitHub repository where my code is hosted. But for now, the goal is to demonstrate how to set up Azure Front Door with an Azure Storage Account that has static website hosting enabled.

Step 1: Create the Storage Account with Terraform

The first step is to create a resource group and an Azure Storage Account. For redundancy and performance, I will use Read-Access Geo-Redundant Storage (RAGRS). This setup ensures that if the primary region becomes unavailable, the data can still be accessed from the secondary region, improving availability.

To learn more about RAGRS, check out Microsoft’s documentation.

Building the First Part of the Infrastructure

resource "azurerm_resource_group" "rg_demo_static_website" {
  name     = "rg-demo-static-website-002"
  location = "francecentral" # Update with the actual location of your resource group
  tags = {
    environment = "Dev"
  }
}


# This resource creates an Azure Storage Account with the specified configurations.
# - `name`: The name of the storage account.
# - `resource_group_name`: The name of the resource group where the storage account will be created.
# - `location`: The location/region where the storage account will be created.
# - `account_tier`: The performance tier of the storage account (Standard or Premium).
# - `account_replication_type`: The replication strategy for the storage account (e.g., LRS, GRS, RAGRS, ZRS).
# - `account_kind`: The kind of storage account (e.g., Storage, StorageV2, BlobStorage).
# - `infrastructure_encryption_enabled`: Whether infrastructure encryption is enabled for the storage account.
# - `tags`: A map of tags to assign to the storage account.

# This resource configures a static website for the specified Azure Storage Account.
# - `storage_account_id`: The ID of the storage account to enable the static website on.
# - `index_document`: The name of the index document for the static website.
# - `error_404_document`: (Optional) The name of the custom 404 error document for the static website.

resource "azurerm_storage_account" "storage_staticwebtorageachraf002" {
  name                              = "staticwebtorageachraf002"
  resource_group_name               = azurerm_resource_group.rg_demo_static_website.name
  location                          = azurerm_resource_group.rg_demo_static_website.location
  account_tier                      = "Standard"
  account_replication_type          = "RAGRS"
  account_kind                      = "StorageV2"
  infrastructure_encryption_enabled = true
  tags = {
    environment = "Dev"
  }
}

resource "azurerm_storage_account_static_website" "static_website02" {
  storage_account_id = azurerm_storage_account.storage_staticwebtorageachraf002.id
  #error_404_document = "customnotfound.html"
  index_document = "index.html"
}

Once the Terraform deployment is complete, our storage account is created with static website hosting enabled. Azure automatically creates a new container called $web, where we will store our website files. For now, I will place a simple index.html file in this folder.




Step 2: Deploy Azure Front Door with Terraform

Now that we have our storage account ready, the next step is to deploy Azure Front Door Standard. But before jumping into the deployment, let’s briefly understand what Azure Front Door is and why it’s useful.

What is Azure Front Door?

Azure Front Door is a globally distributed service that enhances website performance, security, and availability. Here are some key benefits:

  1. Global Load Balancing
    • Distributes traffic across multiple backends (App Services, VMs, AKS, etc.).
    • Ensures high availability by routing traffic to the healthiest/closest backend.
  2. Performance Acceleration
    • Uses smart routing to reduce latency and improve response times.
    • Supports caching for static content (available in Azure Front Door Standard/Premium).
  3. Security Enhancements
    • Includes a Web Application Firewall (WAF) to protect against DDoS, SQL injection, and XSS attacks.
    • Provides TLS termination for secure HTTPS connections.
    • Offers bot protection to filter malicious traffic.
  4. URL-Based Routing & Redirection
    • Routes requests based on path, hostname, or query parameters.
    • Supports HTTP to HTTPS redirection and domain changes.
  5. High Availability & Failover
    • Automatically fails over to the nearest available backend.
    • Uses health probes to monitor backend status in real time.

For more details, check out Microsoft’s documentation.


resource "azurerm_cdn_frontdoor_profile" "fqdn_profile" {
  name                     = "achrafbenalayastaticwebsite008"
  resource_group_name      = azurerm_resource_group.rg_demo_static_website.name
  response_timeout_seconds = 16
  sku_name                 = "Standard_AzureFrontDoor"
}

resource "azurerm_cdn_frontdoor_endpoint" "web_endpoint" {
  name                     = "web"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fqdn_profile.id
}

resource "azurerm_cdn_frontdoor_rule_set" "rule_set" {
  name                     = "caching"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fqdn_profile.id
}


resource "azurerm_cdn_frontdoor_origin_group" "origin_group_web" {
  name                     = "web"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fqdn_profile.id

  load_balancing {
    additional_latency_in_milliseconds = 0
    sample_size                        = 16
    successful_samples_required        = 3
  }
  health_probe {
    interval_in_seconds = 100
    path                = "/index.html"
    protocol            = "Http"
    request_type        = "HEAD"
  }
}

resource "azurerm_cdn_frontdoor_origin" "web_origin" {
  depends_on                     = [azurerm_storage_account.storage_staticwebtorageachraf002]
  name                           = "web"
  cdn_frontdoor_origin_group_id  = azurerm_cdn_frontdoor_origin_group.origin_group_web.id
  enabled                        = true
  certificate_name_check_enabled = false
  host_name                      = azurerm_storage_account.storage_staticwebtorageachraf002.primary_web_host
  origin_host_header             = azurerm_storage_account.storage_staticwebtorageachraf002.primary_web_host

  http_port  = 80
  https_port = 443
  priority   = 1
  weight     = 1000
}


resource "azurerm_cdn_frontdoor_rule" "cache_rule" {
  depends_on = [
    azurerm_cdn_frontdoor_origin_group.origin_group_web,
    azurerm_cdn_frontdoor_origin.web_origin
  ]
  name                      = "static"
  cdn_frontdoor_rule_set_id = azurerm_cdn_frontdoor_rule_set.rule_set.id
  order                     = 1
  behavior_on_match         = "Stop"


  conditions {
    url_file_extension_condition {
      operator     = "Equal"
      match_values = ["css", "js", "ico", "png", "jpeg", "jpg", ".map"]
    }
  }
  actions {
    route_configuration_override_action {
      compression_enabled = true
      cache_behavior      = "HonorOrigin"
    }
  }
}


resource "azurerm_cdn_frontdoor_route" "default_route" {
  name                            = "default"
  cdn_frontdoor_endpoint_id       = azurerm_cdn_frontdoor_endpoint.web_endpoint.id
  cdn_frontdoor_origin_group_id   = azurerm_cdn_frontdoor_origin_group.origin_group_web.id
  cdn_frontdoor_origin_ids        = [azurerm_cdn_frontdoor_origin.web_origin.id]
  cdn_frontdoor_rule_set_ids      = [azurerm_cdn_frontdoor_rule_set.rule_set.id]
  enabled                         = true
  cdn_frontdoor_custom_domain_ids = [azurerm_cdn_frontdoor_custom_domain.ihelpyoutodo_domain.id]
  forwarding_protocol             = "MatchRequest"
  https_redirect_enabled          = true
  patterns_to_match               = ["/*"]
  supported_protocols             = ["Http", "Https"]
  link_to_default_domain          = false
}



resource "azurerm_cdn_frontdoor_custom_domain" "ihelpyoutodo_domain" {
  name                     = "yourdomain"
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fqdn_profile.id
  host_name                = "www.yourdomain.com"

  tls {
    certificate_type    = "ManagedCertificate"
    minimum_tls_version = "TLS12"
  }
}


resource "azurerm_cdn_frontdoor_custom_domain_association" "domain_association" {
  cdn_frontdoor_custom_domain_id = azurerm_cdn_frontdoor_custom_domain.ihelpyoutodo_domain.id
  cdn_frontdoor_route_ids        = [azurerm_cdn_frontdoor_route.default_route.id]
}

After deploying Azure Front Door, the next step is to configure a custom domain to serve our website.


Step 3: Configure a Custom Domain

To configure a custom domain, we need to make some changes in our DNS provider (in my case, GoDaddy). The first step is to add a TXT record in the domain’s DNS settings to validate the domain in Azure.

Ps : After you add the Text record , you need also to add 3 cname record that point to your front door default root that end with : .azurefd.net else you will have this error

Domain Validation Process

All domains added to Azure Front Door must be validated. This ensures protection against accidental misconfigurations and prevents domain spoofing. In some cases, Azure prevalidates the domain if it’s already verified by another Azure service. Otherwise, you must manually validate the domain following Azure’s verification steps.

One feature I really appreciate is that Azure Front Door can automatically manage TLS certificates for both subdomains and apex domains. With managed certificates:

  • You don’t need to create, store, or manually install certificates.
  • Azure automatically renews certificates, preventing downtime due to expired SSL certificates.

Note: The process of generating, issuing, and installing a managed TLS certificate can take several minutes to an hour, sometimes longer.

Once the domain is validated, you’ll see a status of Approved, and the TLS certificate will be deployed.

Final Step: Accessing the Website

Now that everything is set up, we can visit our website using our custom domain, benefiting from Azure’s global load balancing, caching, and security features!


Conclusion

In this tutorial, we successfully deployed a static website on Azure using Terraform. We:

  • Created a Storage Account with static website hosting enabled.
  • Deployed Azure Front Door to provide global load balancing, security, and performance improvements.
  • Configured a custom domain and enabled managed TLS certificates.

This setup ensures high availability, security, and performance while keeping things simple with Terraform automation. Let me know if you have any questions or if you’d like a deeper dive into any of these steps!

ShareTweet
Previous Post

Protected: AZ-500 : Microsoft Certified: Azure Security Engineer Associate

Next Post

Model Context Protocol (MCP): The Future of AI Integration

Related Posts

Azure

Honored to be recognized as a Microsoft Azure MVP for 2025-2026

July 20, 2025
55
AI

Model Context Protocol (MCP): The Future of AI Integration

April 21, 2025
205
Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet
Azure

Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet

February 3, 2025
165
Understanding Generative AI and RAG Benefits
AI

Understanding Generative AI and RAG Benefits

January 12, 2025
125
Azure Communication Services Email Sending Simplified: From Setup to Execution and Monitoring
Azure

Azure Communication Services Email Sending Simplified: From Setup to Execution and Monitoring

December 8, 2024
1.9k
PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis
Azure

PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis

November 2, 2024
633
Next Post

Model Context Protocol (MCP): The Future of AI Integration

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Terraform

Certifications

Microsoft certified trainer (MCT)

Recommended

How to setup nginx reverse proxy && load balancer for aspnet core apps with Docker and azure kubernetes service (AKS)

How to setup nginx reverse proxy && load balancer for aspnet core apps with Docker and azure kubernetes service (AKS)

November 23, 2022
889
Reading Excel file in Azure Web Apps

Reading Excel file in Azure Web Apps

December 1, 2020
1.8k

How To host a Next.js app on Azure

October 5, 2020
1.6k
Configure postman / newman API tests in Azure DevOps

Configure postman / newman API tests in Azure DevOps

October 25, 2021
3.5k
Create a Linux VM with infrastructure in Azure using Terraform

Create a Linux VM with infrastructure in Azure using Terraform

August 30, 2020
2.3k
Migration from Asp.Net Core 3.1 to 5.0 and publish to azure

Migration from Asp.Net Core 3.1 to 5.0 and publish to azure

November 12, 2020
841
Facebook Twitter LinkedIn Youtube

Honored to be recognized as a Microsoft Azure MVP for 2025-2026

July 20, 2025

Model Context Protocol (MCP): The Future of AI Integration

April 21, 2025

Step-by-Step Guide: Azure Front Door + Storage Account Static Website + Custom Domain with Terraform

March 11, 2025

Categories

  • AI (2)
  • Apps (1)
  • Azure (64)
  • blazor (2)
  • Blog (91)
  • c# (7)
  • Cloud (66)
  • Courses (3)
  • Dapr (4)
  • docker (4)
  • Games (1)
  • General Tips & Fix (1)
  • Home (1)
  • Kubernetes Service (AKS) (1)
  • motivation (2)
  • Motivation (3)
  • News (9)
  • Resume (1)
  • sql (4)
  • Terrafrom (1)
  • Tricks, Tips and Fixes (4)
  • xamarin (5)
No Result
View All Result
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy