Creating an Azure App Service Environment with Terraform
Creating an Azure App Service Environment with Terraform
Hey there! So, you're looking to set up a reliable hosting environment for your web apps? Well, you're in the right place. Today, I'm going to walk you through creating an Azure App Service environment using Terraform. Trust me, it's not as scary as it sounds, and I'll break it down into bite-sized pieces.
Prerequisites
Before we dive in, let's make sure you've got all the tools you need:
- Terraform installed (version 1.0.0+) - don't worry if you're new to this, it's pretty straightforward
- Azure CLI configured - if you haven't done this yet, I've been there, it takes about 5 minutes
- An active Azure subscription - can't do much without this one!
Project Structure
First things first, let's set up our Terraform project structure. Nothing fancy here, just a simple folder with a few files:
azure-app-service/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Provider Configuration
Let's kick things off with our provider configuration in main.tf
. This is just telling Terraform that we want to work with Azure:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
Resource Group and App Service Plan
Next up, we'll create a resource group and an App Service Plan. Think of the resource group as a container for all your Azure stuff, and the App Service Plan as the server that'll run your app:
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 for the main event - creating the actual App Service. This is where your app will live. I've included some best practices here that I've learned the hard way (trust me, you'll thank me later):
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. Nothing too exciting, just defining the variables we'll need:
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
. This is just so we can see some useful information after our deployment is done:
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
I've built in several security best practices here (because nobody wants to be on the front page of Hacker News for the wrong reasons):
- TLS Configuration: We're enforcing TLS 1.2 minimum - because it's 2024, and security matters!
- FTPS Disabled: We're disabling FTPS to reduce attack surface - one less thing to worry about
- Managed Identity: We're using system-assigned managed identity - way better than storing secrets
- HTTP/2 Enabled: We've got HTTP/2 for better performance - your users will thank you
- VNet Integration Ready: We're enabling VNet routing for network isolation - because who doesn't love a good network boundary?
Applying the Configuration
Ready to make this happen? Here's how:
- Initialize Terraform:
terraform init
- See what changes will be made:
terraform plan
- Make it so!
terraform apply
Conclusion
And there you have it! You've just deployed an Azure App Service using Terraform. It wasn't so bad, right? This setup gives you a solid foundation that you can build upon for your specific application needs.
I've used this setup for several personal projects and learning experiments, and it's worked great. Feel free to tweak it to match what you're trying to build. Happy deploying!