Skip to content

DFE-Digital/terraform-azurerm-container-apps-hosting

Repository files navigation

Azure Container Apps Hosting terraform module

Terraform CI Tflint GitHub release

This module creates and manages Azure Container Apps, deployed within an Azure Virtual Network.

Usage

Terraform

module "azure_container_apps_hosting" {
  source = "github.com/DFE-Digital/terraform-azurerm-container-apps-hosting?ref=v1.6.3"

  environment    = "dev"
  project_name   = "myproject"
  azure_location = "uksouth"

  ## Set launch_in_vnet to false to prevent deploying a new Virtual Network
  # launch_in_vnet = false

  ## Specify the name of an existing Virtual Network if you want to use that instead of creating a new one
  # existing_virtual_network = "my-vnet-example-name"

  ## Specify the name of an existing Resource Group to deploy resources into
  # existing_resource_group = "my-existing-resource-group"

  # Set the default IP Range that will be assigned to the Virtual Network used by the Container Apps
  virtual_network_address_space = "172.32.10.0/24"

  # Create an Azure Container Registry and connect it to the Container App Environment
  enable_container_registry = true
  # registry_ipv4_allow_list = [ "8.8.8.8/32" ]
  ## Specify the connection details for an existing Container Registry if 'enable_container_registry' is false
  # registry_server                     = ""
  # registry_username                   = ""
  # registry_password                   = ""
  ## Change the SKU of ACR from "Standard"
  # registry_sku = "Premium"
  ## Change the retention period (only applicable to Premium SKU)
  # enable_registry_retention_policy = true
  # registry_retention_days          = 90
  ## Disable admin username and access keys if authenticating using a service principal
  # registry_admin_enabled = false
  ## If you dont need a public registry, set this to false to prevent internet access
  # registry_public_access_enabled = false
  ## If 'registry_admin_enabled' is disabled, you can create a User Assigned Managed Identity to authenticate with ACR
  # registry_use_managed_identity = true
  ## The UAMI needs the 'AcrPull' role assignment which can be done manually or applied with terraform
  # registry_managed_identity_assign_role = false

  ## Specify a custom name for the Container App
  # container_app_name_override = "my-awesome-app"

  # Specify the Container Image and Tag that will get pulled from the Container Registry
  image_name = "my-app"
  image_tag  = "latest"

  ## Deploy an Azure SQL Server and create an initial database
  # enable_mssql_database          = true
  # mssql_sku_name                 = "Basic"
  # mssql_max_size_gb              = 2
  # mssql_database_name            = "my-database"
  # mssql_firewall_ipv4_allow_list = [ "8.8.8.8", "1.1.1.1" ]
  # mssql_server_public_access_enabled = true
  # mssql_version = "12.0"
  ## If you want to use a local SQL administrator account you can set a password with
  # mssql_server_admin_password    = "change-me-!!!"
  ## Or, if you want to assign an Azure AD Administrator you must specify
  # mssql_azuread_admin_username = "my-email-address@DOMAIN"
  # mssql_azuread_admin_object_id = "aaaa-bbbb-cccc-dddd"
  ## Restrict SQL authentication to Azure AD
  # mssql_azuread_auth_only = true

  ## Deploy an Azure Database for PostgreSQL flexible server and create an initial database
  # enable_postgresql_database        = true
  # postgresql_server_version         = "11"
  # postgresql_administrator_password = "change-me-!!!"
  # postgresql_administrator_login    = "my-admin-user"
  # postgresql_availability_zone      = "1"
  # postgresql_max_storage_mb         = 32768
  # postgresql_sku_name               = "B_Standard_B1ms"
  # postgresql_collation              = "en_US.utf8"
  # postgresql_charset                = "utf8"
  # postgresql_enabled_extensions     = "citext,pgcrypto"
  # postgresql_network_connectivity_method = "private" # or "public" to enable Public network access
  # postgresql_firewall_ipv4_allow = {
  #   "my-rule-1" = {
  #     start_ip_address = "0.0.0.0",
  #     end_ip_address = "0.0.0.0"
  #   }
  #   # etc
  # }

  ## Deploy an Azure Cache for Redis instance
  # enable_redis_cache                   = true
  # redis_cache_version                  = 6
  # redis_cache_family                   = "C"
  # redis_cache_sku                      = "Basic"
  # redis_cache_capacity                 = 1
  # redis_cache_patch_schedule_day       = "Sunday"
  # redis_cache_patch_schedule_hour      = 23
  # redis_cache_firewall_ipv4_allow_list = [ "8.8.8.8", "1.1.1.1" ]

  ## Deploy an Azure Storage Account and connect it to the Container App
  ## This will expose a 'ConnectionStrings__BlobStorage' environment var to the Container App
  # enable_container_app_blob_storage                = false
  # container_app_blob_storage_public_access_enabled = false
  # container_app_blob_storage_ipv4_allow_list       = [ "8.8.8.8", "1.1.1.1" ]

  ## Increase the hardware resources given to each Container
  # container_cpu    = 1 # core count
  # container_memory = 2 # gigabyte

  # Change the Port number that the Container is listening on
  # container_port = 80

  # Change the number of replicas (commonly called 'instances') for the Container.
  # Setting 'container_max_replicas' to 1 will prevent scaling
  container_min_replicas = 2
  container_max_replicas = 10

  # Maximum number of concurrent HTTP requests before a new replica is created
  container_scale_http_concurrency = 100

  ## Enable out-of-hours scale down to reduce resource usage
  # container_scale_out_at_defined_time = false
  # container_scale_out_rule_start      = "0 9 * * *" # Must be a valid cron time
  # container_scale_out_rule_end        = "0 17 * * *" # Must be a valid cron time

  # Enable a Liveness probe that checks to ensure the Container is responding. If this fails, the Container is restarted
  enable_container_health_probe   = true
  container_health_probe_interval = 60 # seconds
  container_health_probe_protocol = "https" # or "tcp"
  container_health_probe_path     = "/" # relative url to your status page (e.g. /healthcheck, /health, /status)

  # What command should be used to start your Container
  container_command = [ "/bin/bash", "-c", "echo hello && sleep 86400" ]

  ## Set environment variables that are passed to the Container at runtime. (See note below)
  ## It is strongly recommended not to include any sensitive or secret values here
  # container_environment_variables = {
  #   "Environment" = "Development"
  # }

  ## Note: It is recommended to use `container_secret_environment_variables` rather than `container_environment_variables`.
  ##       This ensures that environment variables are set as `secrets` within the container app revision.
  ##       If they are set directly as `env`, they can be exposed when running `az containerapp` commands, especially
  ##       if those commands are ran as part of CI/CD.
  # container_secret_environment_variables = {
  #   "RedirectUri" = "https://www.example.com/signin"
  # }

  ## If your app requires a worker container, you can enable it by setting 'enable_worker_container' to true
  # enable_worker_container       = false
  # worker_container_command      = [ "/bin/bash", "-c", "echo hello && sleep 86400" ]
  # worker_container_min_replicas = 1
  # worker_container_max_replicas = 1

  ## Custom container apps
  # custom_container_apps = {
  #   "my-container-app" = {
  #     # managedEnvironmentId = "/existing-managed-environment-id" # Use this if
  #     #                        you need to launch the container in a different
  #     #                        container app environment
  #     configuration = {
  #       activeRevisionsMode = "single",
  #       secrets = [
  #         {
  #           "name"  = "my-secret",
  #           "value" = "S3creTz"
  #         }
  #       ],
  #       ingress = {
  #         external = false
  #       },
  #       registries = [
  #         {
  #           "server"            = "my-registry.com",
  #           "username"          = "me",
  #           "passwordSecretRef" = "my-secret"
  #         }
  #       ],
  #       dapr = {
  #         enabled = false
  #       }
  #     },
  #     template = {
  #       revisionSuffix = "my-container-app",
  #       containers = [
  #         {
  #           name  = "app",
  #           image = "my-registry.com/my-app:latest",
  #           resources = {
  #             cpu = 0.25,
  #             memory = "0.5Gi"
  #           },
  #           command = [
  #             "say",
  #             "'hello world'",
  #             "-v",
  #             "10"
  #           ]
  #         }
  #       ],
  #       scale = {
  #         minReplicas = 0,
  #         maxReplicas = 1
  #       },
  #       volumes = [
  #         {
  #           "name": "myempty",
  #           "storageType": "EmptyDir"
  #         },
  #         {
  #           "name": "azure-files-volume",
  #           "storageType": "AzureFile",
  #           "storageName": "myazurefiles"
  #         }
  #       ]
  #     }
  #   }
  # }

  # Create a DNS Zone, associate a primary domain and map different DNS Records as you require.
  enable_dns_zone      = true
  dns_zone_domain_name = "example.com"

  ## The SOA record contains important information about a domain and who is responsible for it
  # dns_zone_soa_record  = {
  #   email         = "hello.example.com"
  #   host_name     = "ns1-03.azure-dns.com."
  #   expire_time   = "2419200"
  #   minimum_ttl   = "300"
  #   refresh_time  = "3600"
  #   retry_time    = "300"
  #   serial_number = "1"
  #   ttl           = "3600"
  # }

  ## An A record maps a domain to the physical IP address of the computer hosting that domain
  # dns_a_records = {
  #   "example" = {
  #     ttl = 300,
  #     records = [
  #       "1.2.3.4",
  #       "5.6.7.8",
  #     ]
  #   }
  # }

  ## An ALIAS record is a virtual record type DNSimple created to provide CNAME-like behavior on apex domains
  # dns_alias_records = {
  #   "alias-example" = {
  #     ttl = 300,
  #     target_resource_id = "azure_resource_id",
  #   }
  # }

  ## An AAAA record type is a foundational DNS record when IPv6 addresses are used
  # dns_aaaa_records = {
  #   "aaaa-example" = {
  #     ttl = 300,
  #     records = [
  #       "2001:db8::1:0:0:1",
  #       "2606:2800:220:1:248:1893:25c8:1946",
  #     ]
  #   }
  # }

  # A CAA record is used to specify which certificate authorities (CAs) are allowed to issue certificates for a domain
  # dns_caa_records = {
  #   "caa-example" = {
  #     ttl = 300,
  #     records = [
  #       {
  #         flags = 0,
  #         tag   = "issue",
  #         value = "example.com"
  #       },
  #       {
  #         flags = 0
  #         tag   = "issuewild"
  #         value = ";"
  #       },
  #       {
  #         flags = 0
  #         tag   = "iodef"
  #         value = "mailto:caa@example.com"
  #       }
  #     ]
  #   }
  # }

  ## A CNAME record provides an alias for another domain
  # dns_cname_records = {
  #   "cname-example" = {
  #     ttl    = 300,
  #     record = "example.com",
  #   }
  # }

  ## A MX record directs email to a mail server
  # dns_mx_records = {
  #   "mx-example" = {
  #     ttl = 300,
  #     records = [
  #       {
  #         preference = 10,
  #         exchange   = "mail.example.com"
  #       }
  #     ]
  #   }
  # }

  ## An NS record contains the name of the authoritative name server within the DNS zone
  # dns_ns_records = {
  #   "ns-example" = {
  #     ttl = 300,
  #     records = [
  #       "ns-1.net",
  #       "ns-1.com",
  #       "ns-1.org",
  #       "ns-1.info"
  #     ]
  #   }
  # }

  ## A PTR record is used for reverse DNS lookups, and it matches domain names with IP addresses
  # dns_ptr_records = {
  #   "ptr-example" = {
  #     ttl = 300,
  #     records = [
  #       "example.com",
  #     ]
  #   }
  # }

  ## A SRV record specifies a host and port for specific services such as voice over IP (VoIP), instant messaging etc
  # dns_srv_records = {
  #   "srv-example" = {
  #     ttl = 300,
  #     records = [
  #       {
  #         priority = 1,
  #         weight   = 5,
  #         port     = 8080
  #         target   = target.example.com
  #       }
  #     ]
  #   }
  # }

  ## A TXT record stores text notes on a DNS server
  # dns_txt_records = {
  #   "txt-example" = {
  #     ttl = 300,
  #     records = [
  #       "google-site-authenticator",
  #       "more site information here"
  #     ]
  #   }
  # }

  ## Add additional service endpoints to the infrastructure subnet
  # container_apps_infra_subnet_service_endpoints = ["Microsoft.KeyVault"]

  # Deploy an Azure Front Door CDN. This will be configured as the entrypoint for all traffic accessing your Containers
  enable_cdn_frontdoor           = true
  # cdn_frontdoor_sku            = "Standard_AzureFrontDoor"
  cdn_frontdoor_response_timeout = 300 # seconds

  # Any domains defined here will be associated to the Front Door as acceptable hosts
  cdn_frontdoor_custom_domains = [
    "example.com",
    "www.example.com"
  ]

  # If you want to set up specific domain redirects, you can specify them with 'cdn_frontdoor_host_redirects'
  cdn_frontdoor_host_redirects = [
    {
      "from" = "example.com",
      "to"   = "www.example.com",
    }
  ]

  ## Override the default Origin hostname if you do not want to use the FQDN of the Container App
  # cdn_frontdoor_origin_fqdn_override = "my-backend-host.acme.org"

  ## Override the default origin ports of 80 (HTTP) and 443 (HTTPS) if required
  # cdn_frontdoor_origin_http_port = 8080
  # cdn_frontdoor_origin_https_port = 4443

  # Add additional HTTP Response Headers to include on every response
  cdn_frontdoor_host_add_response_headers = [
    {
      "name"  = "Strict-Transport-Security",
      "value" = "max-age=31536000",
    }
  ]

  # Remove any surplus HTTP Response Headers that you might not want to include
  cdn_frontdoor_remove_response_headers = [
    "Server",
  ]

  # Deploy an Azure Front Door WAF Rate Limiting Policy
  cdn_frontdoor_enable_rate_limiting              = true

  ## Available options are "Prevention" for blocking any matching traffic, or "Detection" just to report on it
  # cdn_frontdoor_waf_mode                        = "Prevention"

  ## Number of minutes to block the requester's IP Address
  cdn_frontdoor_rate_limiting_duration_in_minutes = 5

  ## How many requests can a single IP make in a minute before the WAF policy gets applied
  # cdn_frontdoor_rate_limiting_threshold         = 300

  ## Provide a list of IP Addresses or Ranges that should be exempt from the WAF Policy
  # cdn_frontdoor_rate_limiting_bypass_ip_list    = [ "8.8.8.8/32" ]

  # Prevent traffic from accessing the Container Apps directly
  restrict_container_apps_to_cdn_inbound_only     = true

  ## Should the CDN keep monitoring the backend pool to ensure traffic can be routed?
  enable_cdn_frontdoor_health_probe       = true
  cdn_frontdoor_health_probe_interval     = 300 # seconds
  cdn_frontdoor_health_probe_path         = "/" # relative url to your status page (e.g. /healthcheck, /health, /status)
  cdn_frontdoor_health_probe_request_type = "GET" # HTTP Method (e.g. GET, POST, HEAD etc)

  ## Switch on/off diagnostic settings for the Azure Front Door CDN
  # cdn_frontdoor_enable_waf_logs        = false
  cdn_frontdoor_enable_access_logs       = true # default: false
  cdn_frontdoor_enable_health_probe_logs = true # default: false

  ## Logs are by default exported to a Log Analytics Workspace so enabling these two values are only necessary if you
  ## want to ingest the logs using a 3rd party service (e.g. logit.io)
  # enable_event_hub = true
  # enable_logstash_consumer = true
  ## Specify which Log Analytics tables you want to send to Event Hub
  # eventhub_export_log_analytics_table_names = [
  #   "AppExceptions"
  # ]

  # Monitoring is disabled by default. If enabled, the following metrics will be monitored:
  # Container App: CPU usage, Memory usage, Latency, Revision count, HTTP regional availability
  # Redis (if enabled): Server Load Average
  enable_monitoring                 = true
  monitor_email_receivers           = [ "list@email.com" ]
  monitor_endpoint_healthcheck      = "/"
  ## If you have an existing Logic App Workflow for routing Alerts then you can specify it here instead of creating
  ## a new one
  # existing_logic_app_workflow = {
  #   name                = "my-logic-app"
  #   resource_group_name = "my-other-rg"
  #   trigger_url         = "https://my-callback-url.tld"
  # }
  monitor_enable_slack_webhook      = true
  monitor_slack_webhook_receiver    = "https://hooks.slack.com/services/xxx/xxx/xxx"
  monitor_slack_channel             = "channel-name-or-id"
  alarm_cpu_threshold_percentage    = 80
  alarm_memory_threshold_percentage = 80
  alarm_latency_threshold_ms        = 1000
  alarm_log_ingestion_gb_per_day    = 1

  # Note: that only 1 network watcher can be created within an Azure Subscription
  #     It would probably be advisable to create a Network Watcher outside of this module, as it
  #     may need to be used by other things

  ## Deploy an Azure Network Watcher
  # enable_network_watcher                     = true
  existing_network_watcher_name                = "MyNetworkWatcher"
  existing_network_watcher_resource_group_name = "NetworkWatcherRG"
  # network_watcher_flow_log_retention         = 90 # Days
  # enable_network_watcher_traffic_analytics   = true
  # network_watcher_traffic_analytics_interval = 60

  ## Use a user assigned or system assigned identity on the Container App
  #   container_app_identities = {
  #   type         = "UserAssigned", # Accepted values: "UserAssigned", "SystemAssigned", "SystemAssigned, UserAssigned"
  #   identity_ids = [azurerm_user_assigned_identity.user_assigned_identity.id]
  # }


  # Tags are applied to every resource deployed by this module
  # Include them as Key:Value pairs
  tags = {
    "Environment"   = "Dev",
    "My Custom Tag" = "My Value"
  }
}

Requirements

Name Version
terraform >= 1.4.5
azapi >= 1.13.0
azurerm >= 3.76.0
null >= 3.2.1

Providers

Name Version
azapi 1.13.1
azurerm 3.101.0

Resources

Name Type
azapi_update_resource.mssql_threat_protection resource
azapi_update_resource.mssql_vulnerability_assessment resource
azurerm_application_insights.main resource
azurerm_application_insights_standard_web_test.main resource
azurerm_application_insights_standard_web_test.tls resource
azurerm_cdn_frontdoor_custom_domain.custom_container_apps resource
azurerm_cdn_frontdoor_custom_domain.custom_domain resource
azurerm_cdn_frontdoor_custom_domain_association.custom_domain_association resource
azurerm_cdn_frontdoor_endpoint.custom_container_apps resource
azurerm_cdn_frontdoor_endpoint.endpoint resource
azurerm_cdn_frontdoor_firewall_policy.waf resource
azurerm_cdn_frontdoor_origin.custom_container_apps resource
azurerm_cdn_frontdoor_origin.origin resource
azurerm_cdn_frontdoor_origin_group.custom_container_apps resource
azurerm_cdn_frontdoor_origin_group.group resource
azurerm_cdn_frontdoor_profile.cdn resource
azurerm_cdn_frontdoor_route.custom_container_apps resource
azurerm_cdn_frontdoor_route.route resource
azurerm_cdn_frontdoor_rule.add_response_headers resource
azurerm_cdn_frontdoor_rule.redirect resource
azurerm_cdn_frontdoor_rule.remove_response_header resource
azurerm_cdn_frontdoor_rule_set.add_response_headers resource
azurerm_cdn_frontdoor_rule_set.redirects resource
azurerm_cdn_frontdoor_rule_set.remove_response_headers resource
azurerm_cdn_frontdoor_security_policy.waf resource
azurerm_container_app.container_apps resource
azurerm_container_app.custom_container_apps resource
azurerm_container_app_environment.container_app_env resource
azurerm_container_app_environment_storage.container_app_env resource
azurerm_container_registry.acr resource
azurerm_dns_a_record.custom_container_frontdoor_custom_domain resource
azurerm_dns_a_record.dns_a_records resource
azurerm_dns_a_record.dns_alias_records resource
azurerm_dns_a_record.frontdoor_custom_domain resource
azurerm_dns_aaaa_record.dns_aaaa_records resource
azurerm_dns_caa_record.dns_caa_records resource
azurerm_dns_cname_record.dns_cname_records resource
azurerm_dns_mx_record.dns_mx_records resource
azurerm_dns_ns_record.dns_ns_records resource
azurerm_dns_ptr_record.dns_ptr_records resource
azurerm_dns_srv_record.dns_srv_records resource
azurerm_dns_txt_record.custom_container_frontdoor_custom_domain resource
azurerm_dns_txt_record.dns_txt_records resource
azurerm_dns_txt_record.frontdoor_custom_domain resource
azurerm_dns_zone.default resource
azurerm_eventhub.container_app resource
azurerm_eventhub_authorization_rule.listen_only resource
azurerm_eventhub_consumer_group.logstash resource
azurerm_eventhub_namespace.container_app resource
azurerm_log_analytics_data_export_rule.container_app resource
azurerm_log_analytics_query_pack.container_app resource
azurerm_log_analytics_workspace.app_insights resource
azurerm_log_analytics_workspace.container_app resource
azurerm_log_analytics_workspace.default_network_watcher_nsg_flow_logs resource
azurerm_logic_app_action_custom.var_affected_resource resource
azurerm_logic_app_action_custom.var_alarm_context resource
azurerm_logic_app_action_http.slack resource
azurerm_logic_app_trigger_http_request.webhook resource
azurerm_logic_app_workflow.webhook resource
azurerm_management_lock.default resource
azurerm_monitor_action_group.main resource
azurerm_monitor_diagnostic_setting.blobs resource
azurerm_monitor_diagnostic_setting.cdn resource
azurerm_monitor_diagnostic_setting.container_app_env resource
azurerm_monitor_diagnostic_setting.default_redis_cache resource
azurerm_monitor_diagnostic_setting.event_hub resource
azurerm_monitor_diagnostic_setting.files resource
azurerm_monitor_diagnostic_setting.mssql_security_storage resource
azurerm_monitor_diagnostic_setting.webhook resource
azurerm_monitor_metric_alert.count resource
azurerm_monitor_metric_alert.cpu resource
azurerm_monitor_metric_alert.http resource
azurerm_monitor_metric_alert.latency resource
azurerm_monitor_metric_alert.memory resource
azurerm_monitor_metric_alert.redis resource
azurerm_monitor_metric_alert.sql_cpu resource
azurerm_monitor_metric_alert.sql_dtu resource
azurerm_monitor_metric_alert.tls resource
azurerm_monitor_scheduled_query_rules_alert_v2.exceptions resource
azurerm_monitor_scheduled_query_rules_alert_v2.log-analytics-ingestion resource
azurerm_mssql_database.default resource
azurerm_mssql_database_extended_auditing_policy.default resource
azurerm_mssql_firewall_rule.default_mssql resource
azurerm_mssql_server.default resource
azurerm_mssql_server_extended_auditing_policy.default resource
azurerm_network_security_group.container_apps_infra resource
azurerm_network_security_rule.container_apps_infra_allow_frontdoor_inbound_only resource
azurerm_network_security_rule.container_apps_infra_allow_ips_inbound resource
azurerm_network_watcher.default resource
azurerm_network_watcher_flow_log.default_network_watcher_nsg resource
azurerm_postgresql_flexible_server.default resource
azurerm_postgresql_flexible_server_configuration.extensions resource
azurerm_postgresql_flexible_server_database.default resource
azurerm_postgresql_flexible_server_firewall_rule.firewall_rule resource
azurerm_private_dns_a_record.mssql_private_endpoint resource
azurerm_private_dns_a_record.postgresql_private_link resource
azurerm_private_dns_a_record.redis_cache_private_endpoint resource
azurerm_private_dns_a_record.registry_private_link resource
azurerm_private_dns_a_record.storage_private_link_blob resource
azurerm_private_dns_a_record.storage_private_link_file resource
azurerm_private_dns_zone.mssql_private_link resource
azurerm_private_dns_zone.postgresql_private_link resource
azurerm_private_dns_zone.redis_cache_private_link resource
azurerm_private_dns_zone.registry_private_link resource
azurerm_private_dns_zone.storage_private_link_blob resource
azurerm_private_dns_zone.storage_private_link_file resource
azurerm_private_dns_zone_virtual_network_link.mssql_private_link resource
azurerm_private_dns_zone_virtual_network_link.postgresql_private_link resource
azurerm_private_dns_zone_virtual_network_link.redis_cache_private_link resource
azurerm_private_dns_zone_virtual_network_link.registry_private_link resource
azurerm_private_dns_zone_virtual_network_link.storage_private_link_blob resource
azurerm_private_dns_zone_virtual_network_link.storage_private_link_file resource
azurerm_private_endpoint.default resource
azurerm_redis_cache.default resource
azurerm_redis_firewall_rule.container_app_default_static_ip resource
azurerm_redis_firewall_rule.default resource
azurerm_resource_group.default resource
azurerm_role_assignment.containerapp_acrpull resource
azurerm_role_assignment.mssql_storageblobdatacontributor resource
azurerm_route_table.default resource
azurerm_storage_account.container_app resource
azurerm_storage_account.default_network_watcher_nsg_flow_logs resource
azurerm_storage_account.mssql_security_storage resource
azurerm_storage_account_network_rules.container_app resource
azurerm_storage_account_network_rules.default_network_watcher_nsg_flow_logs resource
azurerm_storage_account_network_rules.mssql_security_storage resource
azurerm_storage_container.container_app resource
azurerm_storage_container.mssql_security_storage resource
azurerm_storage_share.container_app resource
azurerm_subnet.container_apps_infra_subnet resource
azurerm_subnet.container_instances_subnet resource
azurerm_subnet.mssql_private_endpoint_subnet resource
azurerm_subnet.postgresql_subnet resource
azurerm_subnet.redis_cache_subnet resource
azurerm_subnet.registry_private_endpoint_subnet resource
azurerm_subnet.storage_private_endpoint_subnet resource
azurerm_subnet_network_security_group_association.container_apps_infra resource
azurerm_subnet_route_table_association.container_apps_infra_subnet resource
azurerm_subnet_route_table_association.containerinstances_subnet resource
azurerm_subnet_route_table_association.mssql_private_endpoint_subnet resource
azurerm_subnet_route_table_association.postgresql_subnet resource
azurerm_subnet_route_table_association.redis_cache_subnet resource
azurerm_subnet_route_table_association.registry_private_endpoint_subnet resource
azurerm_subnet_route_table_association.storage_private_endpoint_subnet resource
azurerm_user_assigned_identity.containerapp resource
azurerm_user_assigned_identity.mssql resource
azurerm_virtual_network.default resource
azapi_resource_action.existing_logic_app_workflow_callback_url data source
azurerm_logic_app_workflow.existing_logic_app_workflow data source
azurerm_resource_group.existing_resource_group data source
azurerm_storage_account_blob_container_sas.container_app data source
azurerm_subscription.current data source
azurerm_virtual_network.existing_virtual_network data source

Inputs

Name Description Type Default Required
alarm_cpu_threshold_percentage Specify a number (%) which should be set as a threshold for a CPU usage monitoring alarm number 80 no
alarm_latency_threshold_ms Specify a number in milliseconds which should be set as a threshold for a request latency monitoring alarm number 1000 no
alarm_log_ingestion_gb_per_day Define an alarm threshold for Log Analytics ingestion rate in GB (per day) (Defaults to no limit) number 0 no
alarm_memory_threshold_percentage Specify a number (%) which should be set as a threshold for a memory usage monitoring alarm number 80 no
alarm_tls_expiry_days_remaining Number of days remaining of TLS validity before an alarm should be raised number 30 no
app_insights_retention_days Number of days to retain App Insights data for (Default: 2 years) number 730 no
azure_location Azure location in which to launch resources. string n/a yes
cdn_frontdoor_custom_domains Azure CDN Front Door custom domains list(string) [] no
cdn_frontdoor_custom_domains_create_dns_records Should the TXT records and ALIAS/CNAME records be automatically created if the custom domains exist within the DNS Zone? bool true no
cdn_frontdoor_enable_access_logs Toggle the Diagnostic Setting to log Access requests bool false no
cdn_frontdoor_enable_health_probe_logs Toggle the Diagnostic Setting to log Health Probe requests bool false no
cdn_frontdoor_enable_rate_limiting Enable CDN Front Door Rate Limiting. This will create a WAF policy, and CDN security policy. For pricing reasons, there will only be one WAF policy created. bool false no
cdn_frontdoor_enable_waf_logs Toggle the Diagnostic Setting to log Web Application Firewall requests bool true no
cdn_frontdoor_forwarding_protocol Azure CDN Front Door forwarding protocol string "HttpsOnly" no
cdn_frontdoor_health_probe_interval Specifies the number of seconds between health probes. number 120 no
cdn_frontdoor_health_probe_path Specifies the path relative to the origin that is used to determine the health of the origin. string "/" no
cdn_frontdoor_health_probe_protocol Use Http or Https string "Https" no
cdn_frontdoor_health_probe_request_type Specifies the type of health probe request that is made. string "GET" no
cdn_frontdoor_host_add_response_headers List of response headers to add at the CDN Front Door [{ "Name" = "Strict-Transport-Security", "value" = "max-age=31536000" }] list(map(string)) [] no
cdn_frontdoor_host_redirects CDN FrontDoor host redirects [{ "from" = "example.com", "to" = "www.example.com" }] list(map(string)) [] no
cdn_frontdoor_origin_fqdn_override Manually specify the hostname that the CDN Front Door should target. Defaults to the Container App FQDN string "" no
cdn_frontdoor_origin_host_header_override Manually specify the host header that the CDN sends to the target. Defaults to the recieved host header. Set to null to set it to the host_name (cdn_frontdoor_origin_fqdn_override) string "" no
cdn_frontdoor_origin_http_port The value of the HTTP port used for the CDN Origin. Must be between 1 and 65535. Defaults to 80 number 80 no
cdn_frontdoor_origin_https_port The value of the HTTPS port used for the CDN Origin. Must be between 1 and 65535. Defaults to 443 number 443 no
cdn_frontdoor_rate_limiting_bypass_ip_list List if IP CIDRs to bypass CDN Front Door rate limiting list(string) [] no
cdn_frontdoor_rate_limiting_duration_in_minutes CDN Front Door rate limiting duration in minutes number 1 no
cdn_frontdoor_rate_limiting_threshold Maximum number of concurrent requests before Rate Limiting policy is applied number 300 no
cdn_frontdoor_remove_response_headers List of response headers to remove at the CDN Front Door list(string) [] no
cdn_frontdoor_response_timeout Azure CDN Front Door response timeout in seconds number 120 no
cdn_frontdoor_sku Azure CDN Front Door SKU string "Standard_AzureFrontDoor" no
cdn_frontdoor_waf_mode CDN Front Door waf mode string "Prevention" no
container_app_blob_storage_public_access_enabled Enable anonymous public read access to blobs in Azure Storage? bool false no
container_app_environment_internal_load_balancer_enabled Should the Container Environment operate in Internal Load Balancing Mode? bool false no
container_app_file_share_mount_path A path inside your container where the File Share will be mounted to string "/srv/app/storage" no
container_app_identities Identities to assign to container app
object({
type : string
identity_ids : list(string)
})
null no
container_app_name_override A custom name for the Container App string "" no
container_app_storage_account_shared_access_key_enabled Should the storage account for the container app permit requests to be authorized with the account access key via Shared Key? bool true no
container_apps_allow_ips_inbound Restricts access to the Container Apps by creating a network security group rule that only allow inbound traffic from the provided list of IPs list(string) [] no
container_apps_infra_subnet_service_endpoints Endpoints to assign to infra subnet list(string) [] no
container_command Container command list(any) [] no
container_cpu Number of container CPU cores number 1 no
container_environment_variables Container environment variables map(string) {} no
container_health_probe_interval How often in seconds to poll the Container to determine liveness number 30 no
container_health_probe_path Specifies the path that is used to determine the liveness of the Container string "/" no
container_health_probe_protocol Use HTTPS or a TCP connection for the Container liveness probe string "http" no
container_max_replicas Container max replicas number 2 no
container_memory Container memory in GB number 2 no
container_min_replicas Container min replicas number 1 no
container_port Container port number 80 no
container_scale_http_concurrency When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount. number 10 no
container_scale_out_at_defined_time Should the Container App scale out to the max-replicas during a specified time window? bool false no
container_scale_out_rule_end Specify a time using Linux cron format that represents the end of the scale-out window. Defaults to 18:00 string "0 18 * * *" no
container_scale_out_rule_start Specify a time using Linux cron format that represents the start of the scale-out window. Defaults to 08:00 string "0 8 * * *" no
container_secret_environment_variables Container environment variables, which are defined as secrets within the container app configuration. This is to help reduce the risk of accidentally exposing secrets. map(string) {} no
custom_container_apps Custom container apps, by default deployed within the container app environment managed by this module.
map(object({
container_app_environment_id = optional(string, "")
resource_group_name = optional(string, "")
revision_mode = optional(string, "Single")
container_port = optional(number, 0)
ingress = optional(object({
external_enabled = optional(bool, true)
target_port = optional(number, null)
traffic_weight = object({
percentage = optional(number, 100)
})
cdn_frontdoor_custom_domain = optional(string, "")
cdn_frontdoor_origin_fqdn_override = optional(string, "")
cdn_frontdoor_origin_host_header_override = optional(string, "")
enable_cdn_frontdoor_health_probe = optional(bool, false)
cdn_frontdoor_health_probe_protocol = optional(string, "")
cdn_frontdoor_health_probe_interval = optional(number, 120)
cdn_frontdoor_health_probe_request_type = optional(string, "")
cdn_frontdoor_health_probe_path = optional(string, "")
cdn_frontdoor_forwarding_protocol_override = optional(string, "")
}), null)
identity = optional(list(object({
type = string
identity_ids = list(string)
})), [])
secrets = optional(list(object({
name = string
value = string
})), [])
registry = optional(object({
server = optional(string, "")
username = optional(string, "")
password_secret_name = optional(string, "")
identity = optional(string, "")
}), null),
image = string
cpu = number
memory = number
command = list(string)
liveness_probes = optional(list(object({
interval_seconds = number
transport = string
port = number
path = optional(string, null)
})), [])
env = optional(list(object({
name = string
value = optional(string, null)
secretRef = optional(string, null)
})), [])
min_replicas = number
max_replicas = number
}))
{} no
dns_a_records DNS A records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
{} no
dns_aaaa_records DNS AAAA records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
{} no
dns_alias_records DNS ALIAS records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
target_resource_id : string
})
)
{} no
dns_caa_records DNS CAA records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(
object({
flags : number,
tag : string,
value : string
})
)
})
)
{} no
dns_cname_records DNS CNAME records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
record : string
})
)
{} no
dns_mx_records DNS MX records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(
object({
preference : number,
exchange : string
})
)
})
)
{} no
dns_ns_records DNS NS records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
{} no
dns_ptr_records DNS PTR records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
{} no
dns_srv_records DNS SRV records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(
object({
priority : number,
weight : number,
port : number,
target : string
})
)
})
)
{} no
dns_txt_records DNS TXT records to add to the DNS Zone
map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
{} no
dns_zone_domain_name DNS zone domain name. If created, records will automatically be created to point to the CDN. string "" no
dns_zone_soa_record DNS zone SOA record block (https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/dns_zone#soa_record) map(string) {} no
enable_app_insights_integration Deploy an App Insights instance and connect your Container Apps to it bool true no
enable_cdn_frontdoor Enable Azure CDN Front Door. This will use the Container Apps endpoint as the origin. bool false no
enable_cdn_frontdoor_health_probe Enable CDN Front Door health probe bool true no
enable_container_app_blob_storage Create an Azure Storage Account and Storage Container to be used for this app bool false no
enable_container_app_file_share Create an Azure Storage Account and File Share to be mounted to the Container Apps bool false no
enable_container_health_probe Enable liveness probes for the Container bool true no
enable_container_registry Set to true to create a container registry bool n/a yes
enable_dns_zone Conditionally create a DNS zone bool false no
enable_event_hub Send Azure Container App logs to an Event Hub sink bool false no
enable_logstash_consumer Create an Event Hub consumer group for Logstash bool false no
enable_monitoring Create an App Insights instance and notification group for the Container App bool false no
enable_mssql_database Set to true to create an Azure SQL server/database, with a private endpoint within the virtual network bool false no
enable_mssql_vulnerability_assessment Vulnerability assessment can discover, track, and help you remediate potential database vulnerabilities bool true no
enable_network_watcher Enable network watcher. Note: only 1 network watcher per subscription can be created. bool false no
enable_network_watcher_traffic_analytics Enable network watcher traffic analytics (Requires enable_network_watcher to be true) bool true no
enable_postgresql_database Set to true to create an Azure Postgres server/database, with a private endpoint within the virtual network bool false no
enable_redis_cache Set to true to create an Azure Redis Cache, with a private endpoint within the virtual network bool false no
enable_registry_retention_policy Boolean value that indicates whether the policy is enabled bool false no
enable_resource_group_lock Enabling this will add a Resource Lock to the Resource Group preventing any resources from being deleted. bool false no
enable_worker_container Conditionally launch a worker container. This container uses the same image and environment variables as the default container app, but allows a different container command to be run. The worker container does not expose any ports. bool false no
environment Environment name. Will be used along with project_name as a prefix for all resources. string n/a yes
eventhub_export_log_analytics_table_names List of Log Analytics table names that you want to export to Event Hub. See https://learn.microsoft.com/en-gb/azure/azure-monitor/logs/logs-data-export?tabs=portal#supported-tables for a list of supported tables list(string) [] no
existing_logic_app_workflow Name, Resource Group and HTTP Trigger URL of an existing Logic App Workflow. Leave empty to create a new Resource
object({
name : string
resource_group_name : string
})
{
"name": "",
"resource_group_name": ""
}
no
existing_network_watcher_name Use an existing network watcher to add flow logs. string "" no
existing_network_watcher_resource_group_name Existing network watcher resource group. string "" no
existing_resource_group Conditionally launch resources into an existing resource group. Specifying this will NOT create a resource group. string "" no
existing_virtual_network Conditionally use an existing virtual network. The virtual_network_address_space must match an existing address space in the VNet. This also requires the resource group name. string "" no
image_name Image name string n/a yes
image_tag Image tag string "latest" no
launch_in_vnet Conditionally launch into a VNet bool true no
monitor_email_receivers A list of email addresses that should be notified by monitoring alerts list(string) [] no
monitor_enable_slack_webhook Enable slack webhooks to send monitoring notifications to a channel. Has no effect if you have defined existing_logic_app_workflow bool false no
monitor_endpoint_healthcheck Specify a route that should be monitored for a 200 OK status string "/" no
monitor_slack_channel Slack channel name/id to send messages to. Has no effect if you have defined existing_logic_app_workflow string "" no
monitor_slack_webhook_receiver A Slack App webhook URL. Has no effect if you have defined existing_logic_app_workflow string "" no
monitor_tls_expiry Enable or disable daily TLS expiry check bool false no
mssql_azuread_admin_object_id Object ID of a User within Azure AD that you want to assign as the SQL Server Administrator string "" no
mssql_azuread_admin_username Username of a User within Azure AD that you want to assign as the SQL Server Administrator string "" no
mssql_azuread_auth_only Set to true to only permit SQL logins from Azure AD users bool false no
mssql_database_name The name of the MSSQL database to create. Must be set if enable_mssql_database is true string "" no
mssql_firewall_ipv4_allow_list A list of IPv4 Addresses that require remote access to the MSSQL Server
map(object({
start_ip_range : string,
end_ip_range : optional(string, "")
}))
{} no
mssql_managed_identity_assign_role Assign the 'Storage Blob Data Contributor' Role to the SQL Server User-Assigned Managed Identity. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'Storage Blob Data Contributor' Role to the identity bool true no
mssql_max_size_gb The max size of the database in gigabytes number 2 no
mssql_security_storage_firewall_ipv4_allow_list Additional IP addresses to add to the Storage Account that holds the Vulnerability Assessments list(string) [] no
mssql_server_admin_password The local administrator password for the MSSQL server string "" no
mssql_server_public_access_enabled Enable public internet access to your MSSQL instance. Be sure to specify 'mssql_firewall_ipv4_allow_list' to restrict inbound connections bool false no
mssql_sku_name Specifies the name of the SKU used by the database string "Basic" no
mssql_storage_account_shared_access_key_enabled Should the storage account for mssql security permit requests to be authorized with the account access key via Shared Key? bool true no
mssql_version Specify the version of Microsoft SQL Server you want to run string "12.0" no
network_watcher_flow_log_retention Number of days to retain flow logs. Set to 0 to keep all logs. number 90 no
network_watcher_traffic_analytics_interval Interval in minutes for Traffic Analytics. number 60 no
postgresql_administrator_login Specify a login that will be assigned to the administrator when creating the Postgres server string "" no
postgresql_administrator_password Specify a password that will be assigned to the administrator when creating the Postgres server string "" no
postgresql_availability_zone Specify the availibility zone in which the Postgres server should be located string "1" no
postgresql_charset Specify the charset to be used for the Postgres database string "utf8" no
postgresql_collation Specify the collation to be used for the Postgres database string "en_US.utf8" no
postgresql_enabled_extensions Specify a comma seperated list of Postgres extensions to enable. See https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#postgres-14-extensions string "" no
postgresql_firewall_ipv4_allow Map of IP address ranges to add into the postgres firewall. Note: only applicable if postgresql_network_connectivity_method is set to public.
map(object({
start_ip_address = string
end_ip_address = string
}))
{} no
postgresql_max_storage_mb Specify the max amount of storage allowed for the Postgres server number 32768 no
postgresql_network_connectivity_method Specify postgresql networking method, public or private. See https://learn.microsoft.com/en-gb/azure/postgresql/flexible-server/concepts-networking string "private" no
postgresql_server_version Specify the version of postgres server to run (either 11,12,13 or 14) string "" no
postgresql_sku_name Specify the SKU to be used for the Postgres server string "B_Standard_B1ms" no
project_name Project name. Will be used along with environment as a prefix for all resources. string n/a yes
redis_cache_capacity Redis Cache Capacity number 0 no
redis_cache_family Redis Cache family string "C" no
redis_cache_firewall_ipv4_allow_list A list of IPv4 address that require remote access to the Redis server list(string) [] no
redis_cache_patch_schedule_day Redis Cache patch schedule day string "Sunday" no
redis_cache_patch_schedule_hour Redis Cache patch schedule hour number 18 no
redis_cache_sku Redis Cache SKU string "Basic" no
redis_cache_version Redis Cache version number 6 no
redis_config Overrides for Redis Cache Configuration options
object({
maxmemory_reserved : optional(number),
maxmemory_delta : optional(number),
maxfragmentationmemory_reserved : optional(number),
maxmemory_policy : optional(string),
})
{} no
registry_admin_enabled Do you want to enable access key based authentication for your Container Registry? bool true no
registry_ipv4_allow_list List of IPv4 CIDR blocks that require access to the Container Registry list(string) [] no
registry_managed_identity_assign_role Assign the 'AcrPull' Role to the Container App User-Assigned Managed Identity. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity bool true no
registry_password Container registry password (required if enable_container_registry is false) string "" no
registry_public_access_enabled Should your Container Registry be publicly accessible? bool true no
registry_retention_days The number of days to retain an untagged manifest after which it gets purged number 7 no
registry_server Container registry server (required if enable_container_registry is false) string "" no
registry_sku The SKU name of the container registry. Possible values are 'Basic', 'Standard' and 'Premium'. string "Standard" no
registry_use_managed_identity Create a User-Assigned Managed Identity for the Container App. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity bool false no
registry_username Container registry username (required if enable_container_registry is false) string "" no
restrict_container_apps_to_cdn_inbound_only Restricts access to the Container Apps by creating a network security group rule that only allows 'AzureFrontDoor.Backend' inbound, and attaches it to the subnet of the container app environment. bool true no
storage_account_file_share_quota_gb The maximum size of the share, in gigabytes. number 2 no
storage_account_ipv4_allow_list A list of public IPv4 address to grant access to the Storage Account list(string) [] no
storage_account_public_access_enabled Should the Azure Storage Account have Public visibility? bool false no
tags Tags to be applied to all resources map(string) {} no
virtual_network_address_space Virtual Network address space CIDR string "172.16.0.0/12" no
worker_container_command Container command for the Worker container. enable_worker_container must be set to true for this to have any effect. list(string) [] no
worker_container_max_replicas Worker ontainer max replicas number 2 no
worker_container_min_replicas Worker container min replicas number 1 no

Outputs

Name Description
azurerm_container_registry Container Registry
azurerm_dns_zone_name_servers Name servers of the DNS Zone
azurerm_eventhub_container_app Container App Event Hub
azurerm_log_analytics_workspace_container_app Container App Log Analytics Workspace
azurerm_resource_group_default Default Azure Resource Group
cdn_frontdoor_dns_records Azure Front Door DNS Records that must be created manually
container_app_managed_identity User-Assigned Managed Identity assigned to the Container App
container_fqdn FQDN for the Container App
networking IDs for various VNet resources if created