Creating an Azure App Service Environment with Terraform
Creating an Azure App Service Environment with Terraform
As a DevOps engineer, one of the most common tasks is setting up reliable and secure hosting environments for web applications. Today, I'll walk you through creating an Azure App Service environment using Terraform, complete with all the necessary components for a production-ready setup.
Prerequisites
Before we begin, make sure you have:
- Terraform installed (version 1.0.0+)
- Azure CLI configured
- An active Azure subscription
Project Structure
First, let's set up our Terraform project structure:
azure-app-service/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Provider Configuration
Let's start with our provider configuration in main.tf
:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
Resource Group and App Service Plan
Next, we'll create a resource group and an App Service Plan:
resource "azurerm_resource_group" "main" {
name = var.resource_group_name
location = var.location
tags = {
Environment = var.environment
Managed_By = "Terraform"
}
}
resource "azurerm_service_plan" "main" {
name = "${var.project_name}-plan"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
os_type = "Linux"
sku_name = var.sku_name
tags = {
Environment = var.environment
Managed_By = "Terraform"
}
}
App Service Configuration
Now, let's create the App Service with some best practices configurations:
resource "azurerm_linux_web_app" "main" {
name = "${var.project_name}-app"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
service_plan_id = azurerm_service_plan.main.id
site_config {
application_stack {
node_version = "18-lts"
}
always_on = true
ftps_state = "Disabled"
http2_enabled = true
minimum_tls_version = "1.2"
vnet_route_all_enabled = true
}
app_settings = {
"WEBSITE_RUN_FROM_PACKAGE" = "1"
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
"WEBSITE_NODE_DEFAULT_VERSION" = "~18"
"NODE_ENV" = var.environment
}
identity {
type = "SystemAssigned"
}
logs {
application_logs {
file_system_level = "Information"
}
http_logs {
file_system {
retention_in_days = 7
retention_in_mb = 35
}
}
}
tags = {
Environment = var.environment
Managed_By = "Terraform"
}
}
Variables Configuration
Here's our variables.tf
file:
variable "project_name" {
type = string
description = "The name of the project"
}
variable "environment" {
type = string
description = "The environment (dev, staging, prod)"
}
variable "location" {
type = string
description = "The Azure region to deploy to"
default = "eastus2"
}
variable "resource_group_name" {
type = string
description = "The name of the resource group"
}
variable "sku_name" {
type = string
description = "The SKU name for the App Service Plan"
default = "P1v2"
}
Output Configuration
And finally, our outputs.tf
:
output "app_service_name" {
value = azurerm_linux_web_app.main.name
}
output "app_service_default_hostname" {
value = "https://${azurerm_linux_web_app.main.default_hostname}"
}
output "app_service_identity_principal_id" {
value = azurerm_linux_web_app.main.identity[0].principal_id
}
Security Considerations
In this configuration, we've implemented several security best practices:
- TLS Configuration: We enforce TLS 1.2 minimum
- FTPS Disabled: We disable FTPS to reduce attack surface
- Managed Identity: We use system-assigned managed identity
- HTTP/2 Enabled: We enable HTTP/2 for better performance
- VNet Integration Ready: We enable VNet routing for network isolation
Applying the Configuration
To use this configuration:
- Initialize Terraform:
terraform init
- Create a
terraform.tfvars
file:
project_name = "myproject"
environment = "production"
location = "eastus2"
resource_group_name = "myproject-rg"
sku_name = "P1v2"
- Plan and apply:
terraform plan
terraform apply
Conclusion
This Terraform configuration creates a production-ready Azure App Service environment with security best practices, monitoring, and proper resource organization. The configuration is modular and can be easily customized for different environments or requirements.
Remember to always review the generated plan before applying it to your infrastructure, and consider adding additional security measures like VNet integration, Azure Front Door, or Web Application Firewall depending on your specific needs.
Feel free to reach out if you have any questions or need clarification on any part of this setup!