This module deploys self-hosted Azure DevOps Agents and Github Runners with support for both Personal Access Token (PAT) and User Assigned Managed Identity (UAMI) authentication.
- Deploys Azure DevOps Agents with PAT or UAMI authentication
- Deploys Github Runners with PAT or GitHub App authentication
- Supports Azure Container Apps with KEDA auto scaling
- Supports Azure Container Instances
- Supports public or private networking
- Creates all required Azure resources or use existing ones
- No PAT token management required with UAMI authentication
Azure DevOps: PAT (token-based) or UAMI (identity-based, no tokens required) GitHub: PAT (token-based) or GitHub App (app-based)
Important: Before using UAMI authentication with Azure DevOps, the User Assigned Managed Identity must be configured in your Azure DevOps organization:
- Add the identity to Azure DevOps: The UAMI must be added as a service principal in your Azure DevOps organization with appropriate license (Basic or higher)
- Grant agent pool permissions: The UAMI service principal needs Administrator role on the target agent pool
- Organization access: The UAMI must be member of the Azure DevOps organization
- Option 1: Use existing pre-configured UAMI (recommended) - requires
user_assigned_managed_identity_creation_enabled = falseand UAMI details - Option 2: Let module create UAMI, then configure it manually in Azure DevOps afterward
- Option 3: Use
azure_devops_container_app_uamiexample for fully automated setup
Note: This module handles Azure infrastructure provisioning only. Azure DevOps organization configuration is managed separately (either manually or through examples using the azuredevops provider).
Deploy Azure DevOps Agents using User Assigned Managed Identity - no PAT tokens required.
module "azure_devops_agents_uami" {
source = "Azure/avm-ptn-cicd-agents-and-runners/azurerm"
version = "~> 0.2"
postfix = "my-agents"
location = "uksouth"
version_control_system_type = "azuredevops"
version_control_system_authentication_method = "uami" # No PAT required
version_control_system_organization = "https://dev.azure.com/my-organization"
version_control_system_pool_name = "my-agent-pool"
# Use existing UAMI (must be configured in Azure DevOps first)
user_assigned_managed_identity_creation_enabled = false
user_assigned_managed_identity_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/my-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-uami"
user_assigned_managed_identity_client_id = "12345678-1234-1234-1234-123456789012"
user_assigned_managed_identity_principal_id = "87654321-4321-4321-4321-210987654321"
virtual_network_address_space = "10.0.0.0/16"
}module "azure_devops_agents_uami" {
source = "Azure/avm-ptn-cicd-agents-and-runners/azurerm"
version = "~> 0.2"
postfix = "my-agents"
location = "uksouth"
version_control_system_type = "azuredevops"
version_control_system_authentication_method = "uami" # No PAT required
version_control_system_organization = "https://dev.azure.com/my-organization"
version_control_system_pool_name = "my-agent-pool"
# Module creates new UAMI (you must configure it in Azure DevOps after creation)
user_assigned_managed_identity_creation_enabled = true
user_assigned_managed_identity_name = "uami-my-agents"
virtual_network_address_space = "10.0.0.0/16"
}Deploy Azure DevOps Agents using Personal Access Token authentication.
module "azure_devops_agents_pat" {
source = "Azure/avm-ptn-cicd-agents-and-runners/azurerm"
version = "~> 0.2"
postfix = "my-agents"
location = "uksouth"
version_control_system_type = "azuredevops"
version_control_system_authentication_method = "pat"
version_control_system_personal_access_token = "**************************************"
version_control_system_organization = "https://dev.azure.com/my-organization"
version_control_system_pool_name = "my-agent-pool"
virtual_network_address_space = "10.0.0.0/16"
}Deploy GitHub Runners using Personal Access Token authentication.
module "github_runners" {
source = "Azure/avm-ptn-cicd-agents-and-runners/azurerm"
version = "~> 0.2"
postfix = "my-runners"
location = "uksouth"
version_control_system_type = "github"
version_control_system_authentication_method = "pat"
version_control_system_personal_access_token = "**************************************"
version_control_system_organization = "my-organization"
version_control_system_repository = "my-repository"
virtual_network_address_space = "10.0.0.0/16"
}The following requirements are needed by this module:
The following resources are used by this module:
- azurerm_container_app_environment.this (resource)
- azurerm_management_lock.this (resource)
- azurerm_nat_gateway.this (resource)
- azurerm_nat_gateway_public_ip_association.this (resource)
- azurerm_private_dns_zone.container_registry (resource)
- azurerm_private_dns_zone_virtual_network_link.container_registry (resource)
- azurerm_public_ip.this (resource)
- azurerm_resource_group.this (resource)
- modtm_telemetry.telemetry (resource)
- random_uuid.telemetry (resource)
- time_sleep.delay_after_container_app_environment_creation (resource)
- time_sleep.delay_after_container_image_build (resource)
- azapi_client_config.telemetry (data source)
- azurerm_client_config.current (data source)
- modtm_module_source.telemetry (data source)
The following input variables are required:
Description: Azure region where the resource should be deployed.
Type: string
Description: A postfix used to build default names if no name has been supplied for a specific resource type.
Type: string
Description: The version control system organization to deploy the agents too.
Type: string
Description: The type of the version control system to deploy the agents too. Allowed values are 'azuredevops' or 'github'
Type: string
The following input variables are optional (have default values):
Description: The types of compute to use. Allowed values are 'azure_container_app' and 'azure_container_instance'.
Type: set(string)
Default:
[
"azure_container_app"
]Description: Required CPU in cores, e.g. 0.5
Type: number
Default: 1
Description: Required memory, e.g. '250Mb'
Type: string
Default: "2Gi"
Description: Whether or not to create a Container App Environment.
Type: bool
Default: true
Description: The resource id of the Container App Environment. Only required if container_app_environment_creation_enabled is false.
Type: string
Default: null
Description: The name of the Container App Environment. Only required if container_app_environment_creation_enabled is true.
Type: string
Default: null
Description: List of additional environment variables to pass to the container.
Type:
set(object({
name = string
value = string
}))Default: []
Description: The name of the resource group where the Container Apps infrastructure is deployed.
Type: string
Default: null
Description: The name of the container for the runner Container Apps job.
Type: string
Default: null
Description: The name of the Container App runner job.
Type: string
Default: null
Description: The maximum number of executions (ADO jobs) to spawn per polling interval.
Type: number
Default: 100
Description: The minimum number of executions (ADO jobs) to spawn per polling interval.
Type: number
Default: 0
Description: The name of the container for the placeholder Container Apps job.
Type: string
Default: null
Description: The name of the Container App placeholder job.
Type: string
Default: null
Description: The number of times to retry the placeholder Container Apps job.
Type: number
Default: 0
Description: The timeout in seconds for the placeholder Container Apps job.
Type: number
Default: 300
Description: How often should the pipeline queue be checked for new events, in seconds.
Type: number
Default: 30
Description: The number of times to retry the runner Container Apps job.
Type: number
Default: 3
Description: The timeout in seconds for the runner Container Apps job.
Type: number
Default: 1800
Description: List of additional sensitive environment variables to pass to the container.
Type:
set(object({
name = string
value = string
container_app_secret_name = string
keda_auth_name = optional(string)
}))Default: []
Description: The address prefix for the Container App Environment. Either subnet_id or subnet_name and subnet_address_prefix must be specified.
Type: string
Default: null
Description: The CIDR size for the container instance subnet.
Type: number
Default: 27
Description: The ID of a pre-existing subnet to use. Required if virtual_network_creation_enabled is false.
Type: string
Default: null
Description: The name of the subnet. Must be specified if virtual_network_creation_enabled is true.
Type: string
Default: null
Description: The CPU value for the container instance
Type: number
Default: 2
Description: The CPU limit value for the container instance
Type: number
Default: 2
Description: The memory value for the container instance
Type: number
Default: 4
Description: The memory limit value for the container instance
Type: number
Default: 4
Description: The name of the container instance
Type: string
Default: null
Description: The number of container instances to create
Type: number
Default: 2
Description: List of additional environment variables to pass to the container.
Type:
set(object({
name = string
value = string
}))Default: []
Description: The name prefix of the container instance
Type: string
Default: null
Description: List of additional sensitive environment variables to pass to the container.
Type:
set(object({
name = string
value = string
}))Default: []
Description: The address prefix for the Container App Environment. Either subnet_id or subnet_name and subnet_address_prefix must be specified.
Type: string
Default: null
Description: The CIDR size for the container instance subnet.
Type: number
Default: 28
Description: The ID of a pre-existing subnet to use. Required if virtual_network_creation_enabled is false.
Type: string
Default: null
Description: The name of the subnet. Must be specified if virtual_network_creation_enabled == false.
Type: string
Default: null
Description: Whether to use availability zones for the container instance
Type: bool
Default: true
Description: Whether or not to create a container registry.
Type: bool
Default: true
Description: The ID of the private DNS zone to create for the container registry. Only required if container_registry_private_dns_zone_creation_enabled is false and you are not using policy to update the DNS zone.
Type: string
Default: null
Description: The name of the container registry. Only required if container_registry_creation_enabled is true.
Type: string
Default: null
Description: Whether or not to create a private DNS zone for the container registry.
Type: bool
Default: true
Description: The address prefix for the Container App Environment. Either subnet_id or subnet_name and subnet_address_prefix must be specified.
Type: string
Default: null
Description: The ID of a pre-existing subnet to use. Required if virtual_network_creation_enabled is false.
Type: string
Default: null
Description: The name of the subnet. Must be specified if virtual_network_creation_enabled == false.
Type: string
Default: null
Description: The CIDR size for the container registry subnet.
Type: number
Default: 29
Description: The images to build and push to the container registry. This is only relevant if container_registry_creation_enabled is true and use_default_container_image is set to false.
- task_name: The name of the task to create for building the image (e.g.
image-build-task) - dockerfile_path: The path to the Dockerfile to use for building the image (e.g.
dockerfile) - context_path: The path to the context of the Dockerfile in three sections
<repository-url>#<repository-commit>:<repository-folder-path>(e.g. https://github.com/Azure/avm-container-images-cicd-agents-and-runners#bc4087f:azure-devops-agent) - context_access_token: The access token to use for accessing the context. Supply a PAT if targetting a private repository.
- image_names: A list of the names of the images to build (e.g.
["image-name:tag"])
Type:
map(object({
task_name = string
dockerfile_path = string
context_path = string
context_access_token = optional(string, "a") # This `a` is a dummy value because the context_access_token should not be required in the provider
image_names = list(string)
}))Default: null
Description: The login server of the container registry to use if container_registry_creation_enabled is false.
Type: string
Default: null
Description: The password of the container registry to use if container_registry_creation_enabled is false.
Type: string
Default: null
Description: The username of the container registry to use if container_registry_creation_enabled is false.
Type: string
Default: null
Description: The default image name to use if no custom image is provided.
Type: string
Default: null
Description: The default image registry Dockerfile path to use if no custom image is provided.
Type: string
Default: "dockerfile"
Description: The default image repository commit to use if no custom image is provided.
Type: string
Default: "221742d"
Description: The default image repository folder path to use if no custom image is provided.
Type: map(string)
Default:
{
"azuredevops-container-app": "azure-devops-agent-aca",
"azuredevops-container-instance": "azure-devops-agent-aci",
"github-container-app": "github-runner-aca",
"github-container-instance": "github-runner-aci"
}Description: The default image repository URL to use if no custom image is provided.
Type: string
Default: "https://github.com/Azure/avm-container-images-cicd-agents-and-runners"
Description: Delays (in seconds) to apply to the module operations.
Type:
object({
delay_after_container_image_build = optional(number, 60)
delay_after_container_app_environment_creation = optional(number, 120)
})Default: {}
Description: This variable controls whether or not telemetry is enabled for the module.
For more information see https://aka.ms/avm/telemetryinfo.
If it is set to false, then no telemetry will be collected.
Type: bool
Default: true
Description: Controls the Resource Lock configuration for this resource. The following properties can be specified:
kind- (Required) The type of lock. Possible values are\"CanNotDelete\"and\"ReadOnly\".name- (Optional) The name of the lock. If not specified, a name will be generated based on thekindvalue. Changing this forces the creation of a new resource.
Type:
object({
kind = string
name = optional(string, null)
})Default: null
Description: Whether or not to create a log analytics workspace.
Type: bool
Default: true
Description: The resource Id of the Log Analytics Workspace.
Type: string
Default: null
Description: Whether or not to enable internet ingestion for the Log Analytics workspace. If null, defaults to opposite of use_private_networking (true when private networking is false).
Type: bool
Default: null
Description: Whether or not to enable internet query for the Log Analytics workspace. If null, defaults to opposite of use_private_networking (true when private networking is false).
Type: bool
Default: null
Description: The name of the log analytics workspace. Only required if log_analytics_workspace_creation_enabled == false.
Type: string
Default: null
Description: The retention period for the Log Analytics Workspace.
Type: number
Default: 30
Description: The SKU of the Log Analytics Workspace.
Type: string
Default: "PerGB2018"
Description: Whether or not to create a NAT Gateway.
Type: bool
Default: true
Description: The ID of the NAT Gateway. Only required if nat_gateway_creation_enabled is false.
Type: string
Default: null
Description: The name of the NAT Gateway.
Type: string
Default: null
Description: Whether or not to create a public IP.
Type: bool
Default: true
Description: The ID of the public IP. Only required if public_ip_creation_enabled is false.
Type: string
Default: null
Description: The name of the public IP.
Type: string
Default: null
Description: The availability zones for the public IP. Only required if public_ip_creation_enabled is true.
Type: set(string)
Default:
[
"1",
"2",
"3"
]Description: Whether or not to create a resource group.
Type: bool
Default: true
Description: The resource group where the resources will be deployed. Must be specified if resource_group_creation_enabled == false
Type: string
Default: null
Description: (Optional) Tags of the resource.
Type: map(string)
Default: null
Description: Whether or not to use the default container image provided by the module.
Type: bool
Default: true
Description: Whether or not to use private networking for the container registry.
Type: bool
Default: true
Description: Enable zone redundancy for the deployment
Type: bool
Default: true
Description: The client id of the user assigned managed identity. Only required if user_assigned_managed_identity_creation_enabled == false and using UAMI authentication. The identity must be configured in Azure DevOps separately.
Type: string
Default: null
Description: Whether or not to create a user assigned managed identity. When using UAMI authentication, the identity must also be configured in Azure DevOps separately.
Type: bool
Default: true
Description: The resource Id of the user assigned managed identity. Only required if user_assigned_managed_identity_creation_enabled == false. When using UAMI authentication, ensure the identity is configured in Azure DevOps.
Type: string
Default: null
Description: The name of the user assigned managed identity. Must be specified if user_assigned_managed_identity_creation_enabled == true.
Type: string
Default: null
Description: The principal id of the user assigned managed identity. Only required if user_assigned_managed_identity_creation_enabled == false. When using UAMI authentication, ensure the identity is configured in Azure DevOps.
Type: string
Default: null
Description: The version control system agent name prefix.
Type: string
Default: null
Description: The target value for the amound of pending jobs to scale on.
Type: number
Default: 1
Description: Authentication method. For Azure DevOps: 'pat' or 'uami' (requires Azure DevOps prerequisites - see README). For GitHub: 'pat' or 'github_app'
Type: string
Default: "pat"
Description: The enterprise name for the version control system.
Type: string
Default: null
Description: The application ID for the GitHub App authentication method.
Type: string
Default: ""
Description: The installation ID for the GitHub App authentication method.
Type: string
Default: ""
Description: The application key for the GitHub App authentication method.
Type: string
Default: null
Description: The personal access token for the version control system. Required when authentication_method is 'pat'.
Type: string
Default: null
Description: The version control system placeholder agent name.
Type: string
Default: null
Description: The name of the agent pool in the version control system.
Type: string
Default: null
Description: The version control system repository to deploy the agents too.
Type: string
Default: null
Description: The runner group to add the runner to.
Type: string
Default: null
Description: The scope of the runner. Must be ent, org, or repo. This is ignored for Azure DevOps.
Type: string
Default: "repo"
Description: The address space for the virtual network. Must be specified if virtual_network_creation_enabled is true.
Type: string
Default: null
Description: Whether or not to create a virtual network.
Type: bool
Default: true
Description: The ID of the virtual network. Only required if virtual_network_creation_enabled is false.
Type: string
Default: null
Description: The name of the virtual network. Must be specified if virtual_network_creation_enabled is true.
Type: string
Default: null
The following outputs are exported:
Description: The subnet id of the container app job.
Description: The names of the container instances.
Description: The resource ids of the container instances.
Description: The container registry login server.
Description: The container registry name.
Description: The container registry resource id.
Description: The name of the container app job.
Description: The resource id of the container app job.
Description: The name of the container app environment.
Description: The name of the placeholder contaienr app job.
Description: The resource id of the placeholder container app job.
Description: The private dns zone id of the container registry.
Description: The resource id of the container app environment.
Description: The client id of the user assigned managed identity.
Description: The resource id of the user assigned managed identity.
Description: The principal id of the user assigned managed identity.
Description: The virtual network name.
Description: The virtual network resource id.
The following Modules are called:
Source: ./modules/container-app-job
Version:
Source: ./modules/container-instance
Version:
Source: ./modules/container-registry
Version:
Source: Azure/avm-res-operationalinsights-workspace/azurerm
Version: 0.4.2
Source: Azure/avm-res-managedidentity-userassignedidentity/azurerm
Version: 0.3.3
Source: Azure/avm-res-network-virtualnetwork/azurerm
Version: 0.8.1
The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.