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
230
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

AI

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

April 21, 2025
110
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
136
Understanding Generative AI and RAG Benefits
AI

Understanding Generative AI and RAG Benefits

January 12, 2025
96
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.6k
PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis
Azure

PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis

November 2, 2024
501
Automated Monitoring of Azure App Registration Secrets with Automation Accounts and Logic Apps
Azure

Automated Monitoring of Azure App Registration Secrets with Automation Accounts and Logic Apps

October 7, 2024
652
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

My 2020 Review

My 2020 Review

December 31, 2020
238
The Significance of Azure DevSecOps: Best Practices for Securing Your Pipelines

The Significance of Azure DevSecOps: Best Practices for Securing Your Pipelines

August 17, 2023
343
How To Host a React Static Website on Azure

How To Host a React Static Website on Azure

September 27, 2020
1.3k
Microsoft Teams

What’s new in Microsoft Teams

September 4, 2020
304
Migrate and modernize your applications on Azure – Part –1 (Migrate Database)

Migrate and modernize your applications on Azure – Part –1 (Migrate Database)

April 3, 2021
319
Animations with Lottie in Xamarin Forms

Animations with Lottie in Xamarin Forms

April 26, 2020
1.1k
Facebook Twitter LinkedIn Youtube

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
Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet

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

February 3, 2025

Categories

  • AI (2)
  • Apps (1)
  • Azure (63)
  • blazor (2)
  • Blog (91)
  • c# (7)
  • Cloud (65)
  • 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