A lightweight, batteries-included Terraform module for deploying an Azure App Service (Linux) with sensible defaults and optional integrations.
What you get:
- Azure App Service Plan (Linux)
- Azure Linux Web App with .NET runtime (version configurable)
- Application Insights (workspace-based if a Log Analytics Workspace ID is provided; classic otherwise)
- Optional diagnostic settings streaming to Log Analytics
- Optional Key Vault (with RBAC), placeholder secrets, and app settings references
- User-assigned managed identity for Key Vault resolution
- Simple naming and tagging
Spin up an opinionated Azure Web App quickly, with:
- Minimal inputs to get running
- Safe defaults that work for most teams
- Opt-in features (Key Vault and LAW) when you need them
Basic example:
locals {
env_name = "dev"
}
module "web_app" {
source = "7Factor/linux-app-service/azurerm"
version = "~> 1.0"
app_name = "orders-api"
resource_name_options = {
# Available template variables are `app_name` and `resource_type`, which must be escaped with a double dollar sign.
# You can use other locals or variables in the string by using a single dollar sign (see below).
# Ex. This `template` will resolve to `acme-rg-orders-api-dev` for a resource group
template = "acme-$${resource_type}-$${app_name}-${local.env_name}"
# Ex. This `template_safe` will resolve to `acmekvordersapidev` for a Key Vault resource.
template_safe = "acme$${resource_type}$${app_name}${local.env_name}"
}
application_stack = {
dotnet_version = "10.0"
}
# Optional: App settings passed directly to the Web App
app_settings = {
ASPNETCORE_URLS = "http://0.0.0.0:8080"
}
# Optional: Link Key Vault secrets and bind to app settings
app_secrets = [
{
name = "Db-ConnectionString"
app_setting_name = "ConnectionStrings__Database"
initial_value = "sample" # optional - defaults to ""
},
{
name = "Api-Key"
app_setting_name = "MyApi__Key"
},
{
name = "Unbound-Secret"
# app_setting omitted; secret is created in Key Vault but not bound to app settings
}
]
# Optional: Centralized logging
# log_analytics_workspace_id = "/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/"
global_tags = {
environment = "dev"
owner = "platform-team"
}
}
After apply:
- If you set
app_secrets, the module creates:- A Key Vault (RBAC-enabled)
- Secrets with the given names (initial values can be set but are defaulted to "", and Terraform ignores future changes to value)
- App settings on the Web App that reference the secrets using non-versioned URIs
- Populate real secret values later via Azure Portal or CI. The Web App will resolve the latest version via its managed identity.
- app_name (string, required)
- Base name for resources (combined with prefix).
-
resource_name_options (object, default: {}): Options to adjust how resource names are generated
- template (string, default:
"$${resource_type}-$${app_name}"): A template string for generating standard resource names. - template_safe (string, default:
"$${resource_type}$${app_name}"): A template string for generating resource names for resource types with restrictive naming requirements (Key Vault and Blob Storage)
- template (string, default:
-
app_settings (map(string), default: {})
- Additional application settings to add to the Web App.
-
app_secrets (list(object), default: [])
- name (string, required): Key Vault secret name.
- app_setting (string, optional): App setting key to bind via Key Vault reference. If omitted, the secret is created but not bound.
- external (bool, default: false): If true, the secret is not created automatically by Terraform and is assumed to have been created elsewhere. If set to
true,initial_valueandtagsare ignored. - initial_value (string, optional): Seed value for first deploy. Subsequent changes are ignored. Populate/rotate via Azure Portal or CI.
- tags (map(string), optional): Tags to apply to an individual secret
-
application_stack (object)
- An application_stack block
-
site_config (object)
- A site_config block, with the following additions:
- https_only (bool, default: null)
- client_affinity_enabled (bool, default: null)
- client_certificate_enabled (bool, default: null)
- client_certificate_mode (string, default: null)
- client_certificate_exclusion_paths (string, default: null)
- virtual_network_subnet_id (string, default: null)
- A site_config block, with the following additions:
-
log_analytics_workspace_id (string, default: null)
- If provided, Application Insights is workspace-based and diagnostic settings send logs/metrics to this workspace.
-
global_tags (map(string), default: {})
- Tags applied to all resources. Often used for environment and owning team.
-
resource_group_name (string, default: null)
- Existing Resource Group name. If not provided, a new RG is created using
location.
- Existing Resource Group name. If not provided, a new RG is created using
-
location (string, default: "eastus2")
- Azure location for resources (ignored if
resource_group_idis provided).
- Azure location for resources (ignored if
-
service_plan_sku (string, default: "B2")
- App Service Plan SKU name (e.g., "B1", "B2", "S1", "P1v3"). If a
service_plan_idis provided, this value is ignored.
- App Service Plan SKU name (e.g., "B1", "B2", "S1", "P1v3"). If a
-
service_plan_id (string, default: null)
- Existing App Service Plan ID. If this is not provided, a new plan will be created.
-
diagnostic_log_category_groups (list(string), default: ["allLogs"])
- List of log category groups to enable for diagnostic settings.
-
diagnostic_log_categories (list(string), default: [])
- List of log categories to enable for diagnostic settings.
-
diagnostic_metric_categories (list(string), default: ["AllMetrics"])
- List of metric categories to enable for diagnostic settings.
-
enable_system_assigned_identity (bool, default: false)
- Enable system-assigned managed identity on the app (in addition to the user-assigned one).
-
key_vault (object, default: {})
- Note: If no
app_secretsare provided, all values in this block are ignored. - sku (string, default: "standard")
- purge_protection_enabled (bool, default: false)
- soft_delete_retention_days (number, default: 7)
- existing_name (string, default: null)
- existing_rg_name (string, default: null)
- Note: If no
-
private_acr_id (string, default: null)
- Optional ID of a private ACR for pulling container images
-
ignore_changes (object, default: {})
- zip_deploy_file (bool, default: false): If true, terraform will ignore any changes to the zip_deploy_file attribute