Skip to content

7Factor/terraform-azurerm-function-app

Repository files navigation

terraform-azurerm-function-app

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

Why this module?

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

Usage

Basic example

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"
  }
}

Flex Consumption

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"
  }
}

Containerized functions (dedicated plan only)

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.

Inputs

Required

  • app_name (string, required)
    • Base name for resources (combined with template).

Recommended

  • 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_name and runtime_version are required.
    • Supports: node, dotnet, dotnet-isolated, powershell, python, java, custom (custom typically for containers on dedicated plan)

Optional

  • use_flex_consumption (bool, default: false) Switch to flex consumption plan. Note: dotnet runtime must be dotnet-isolated for .NET workloads; custom and docker are not supported on flex
  • site_config (object)
    • Mirrors azurerm_linux_function_app and azurerm_function_app_flex_consumption supported 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
  • 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_id is provided or flex is used.
  • 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)

Outputs

  • function_app
  • service_plan_id
  • application_insights
  • resource_group

Notes

  • 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

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages