A lightweight, batteries-included Terraform module for deploying Azure Functions on Linux with sensible defaults and optional integrations.
What you get:
- Azure Function App (Linux), either:
- Dedicated/App Service Plan, or
- Flex Consumption plan (preview GA-ready pattern)
- Backing Storage Account and Blob Container (or use existing)
- 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 and/or ACR access
- Optional ACR pull role assignment for containerized functions (non-flex)
- Simple naming and tagging
Spin up an opinionated Azure Function App quickly, with:
- Minimal inputs to get running
- Safe defaults that work for most teams
- Opt-in features (Key Vault, LAW, ACR) when you need them
- Works with both dedicated plan and Flex Consumption
locals {
env_name = "dev"
}
module "function_app" {
source = "7Factor/function-app/azurerm"
version = "~> 1.0"
app_name = "orders-worker"
resource_name_options = {
# Available template variables are `app_name` and `resource_type`, escaped with $$
# You can use other locals or variables using a single $
# Example: resolves to acme-rg-orders-worker-dev for a resource group
template = "acme-$${resource_type}-$${app_name}-${local.env_name}"
# Example: resolves to acmekvordersworkerdev for a Key Vault
template_safe = "acme$${resource_type}$${app_name}${local.env_name}"
}
# Choose a runtime
application_stack = {
runtime_name = "dotnet-isolated"
runtime_version = "8.0"
}
# Optional: App settings passed directly to the Function App
app_settings = {
FUNCTIONS_WORKER_PROCESS_COUNT = "2"
AzureWebJobsStorage__account = "ref-only"
}
# Optional: Define Key Vault secrets and bind them 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"
# Not bound to app settings (created/managed in KV only)
}
]
# Optional: Centralized logging
# log_analytics_workspace_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-observability/providers/Microsoft.OperationalInsights/workspaces/law-observability"
global_tags = {
environment = "dev"
owner = "platform-team"
}
}
module "function_app_flex" {
source = "7Factor/function-app/azurerm"
version = "~> 1.0"
app_name = "orders-flex"
use_flex_consumption = true
application_stack = {
runtime_name = "python"
runtime_version = "3.11"
}
flex_settings = {
maximum_instance_count = 20
instance_memory_in_mb = 2048
}
app_settings = {
FUNCTIONS_WORKER_PROCESS_COUNT = "1"
}
global_tags = {
environment = "dev"
}
}
module "function_app_container" {
source = "7Factor/function-app/azurerm"
version = "~> 1.0"
app_name = "orders-container"
application_stack = {
runtime_name = "custom" # container-based
docker_image_name = "myrepo/orders-func"
docker_image_tag = "1.2.3"
docker_registry_url = "myregistry.azurecr.io"
docker_registry_username = "acr-username" # or omit when using ACR + managed identity pull
docker_registry_password = "acr-password" # use a secret store/CI variable in real setups
}
# Grant AcrPull to the app’s user-assigned identity
private_acr_id = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ContainerRegistry/registries/<acr-name>"
global_tags = {
environment = "dev"
}
}
After apply:
- If you set app_secrets, the module creates:
- A Key Vault (RBAC-enabled) unless you point to an existing one
- Secrets with the given names (initial values default to "", and Terraform ignores future changes to value)
- App settings on the Function App that reference the secrets using non-versioned URIs
- Populate real secret values later via Azure Portal or CI. The Function App will resolve the latest version via its managed identity.
- If you set private_acr_id (and use a non-flex plan), the module creates a user-assigned identity and grants AcrPull on your ACR.
- app_name (string, required)
- Base name for resources (combined with template).
- resource_name_options (object, default: {})
- template (string, default: "$${resource_type}-$${app_name}")
- template_safe (string, default: "$${resource_type}$${app_name}")
- app_settings (map(string), default: {}) Additional application settings added to the Function App.
- app_secrets (list(object), default: [])
- name (string, required): Key Vault secret name.
- app_setting_name (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, Terraform will not create the secret; it is assumed to already exist.
- initial_value (string, optional): Seed value for first deploy. Subsequent changes are ignored.
- tags (map(string), optional): Tags to apply to an individual secret.
- application_stack (object)
- For dedicated plan: optional but recommended.
- For flex consumption:
runtime_nameandruntime_versionare required. - Supports:
node,dotnet,dotnet-isolated,powershell,python,java,custom(custom typically for containers on dedicated plan)
- use_flex_consumption (bool, default: false)
Switch to flex consumption plan. Note: dotnet runtime must be
dotnet-isolatedfor .NET workloads;customand docker are not supported on flex - site_config (object)
- Mirrors
azurerm_linux_function_appandazurerm_function_app_flex_consumptionsupported settings with module-level conveniences: - https_only (bool)
- client_certificate_enabled (bool)
- client_certificate_mode (string)
- client_certificate_exclusion_paths (string)
- virtual_network_subnet_id (string)
- Logging settings (disk quota, retention)
- Plus many standard Function App flags (see variable docs)
- Not supported on flex:
always_on,builtin_logging_enabled,ftp_publish_basic_authentication_enabled,ftps_state
- Mirrors
- flex_settings (object, default: {})
- maximum_instance_count (number, default: 1)
- instance_memory_in_mb (number, default: 1024)
- connection_strings (list(object), default: [])
- name (string)
- type (string)
- secret_name (string; must match a secret in app_secrets)
- 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 in location.
- app_insights_name (string, default: null)
- Use an existing Application Insights by name (in the target RG); otherwise one is created.
- location (string, default: "eastus2")
- service_plan_sku (string, default: "B2")
- Size for the App Service Plan (dedicated plan only). Ignored if
service_plan_idis provided or flex is used.
- Size for the App Service Plan (dedicated plan only). Ignored if
- service_plan_id (string, default: null)
- Use an existing App Service Plan (dedicated plan only).
- diagnostic_log_category_groups (list(string), default: ["allLogs"])
- diagnostic_log_categories (list(string), default: [])
- diagnostic_metric_categories (list(string), default: ["AllMetrics"])
- enable_system_assigned_identity (bool, default: false)
- Adds a system-assigned identity in addition to the user-assigned identity when needed.
- key_vault (object, default: {})
- Ignored if no app_secrets are provided.
- 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)
- storage (object, default: {})
- Use existing Storage Account and/or Container for functions artifacts:
- existing_name (string, default: null)
- existing_container_name (string, default: null)
- existing_rg_name (string, default: null)
- sticky_settings (object, default: null)
- app_setting_names (list(string))
- connection_string_names (list(string))
- private_acr_id (string, default: null)
- Optional ID of a private ACR to grant AcrPull for containerized functions (not supported with flex)
- function_app
- service_plan_id
- application_insights
- resource_group
- Flex vs dedicated
- When use_flex_consumption = true:
- docker/custom not supported
- dotnet (in-process) not supported; use dotnet-isolated
- Some site_config fields are not supported (the module warns accordingly)
- Key Vault values
- initial_value is intended as a seed only; Terraform ignores future changes to secret values by design
- Rotate/manage real values outside of Terraform (Portal, CLI, or CI pipelines)
- ACR integration
- If private_acr_id is set, a user-assigned identity is created and granted AcrPull
- Container credentials in application_stack can be omitted when using ACR + managed identity