Skip to content

Public Terraform Registry module for setting up an AZURE hosted Sonarqube ACI instance incl. persistent PaaS Database (Azure SQL), PaaS File Share (Azure Files) and custom domain using reverse proxy (Caddy) sidecar container.

License

Notifications You must be signed in to change notification settings

Pwd9000-ML/terraform-azurerm-sonarqube-aci

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Manual-Tests-and-Release Automated-Dependency-Tests-and-Release Dependabot

Module: Sonarqube Azure Container Instance (+ Automatic SSL)

image.png

Description

Public Terraform Registry module for setting up an AZURE hosted Sonarqube Azure Container Instance (ACI) including: persistent PaaS Database (Azure SQL), persistent PaaS File Shares (Azure Files) and support for custom domain using reverse proxy (Caddy) sidecar container.

Also see this module for creating a VNET integrated instance of SonarQube using a private .local DNS zone and self-signed Certificate. VNET integrated SonarQube Azure Container Instance (+ Automatic SSL self-signed certificate).

The module will build the following Azure resources:

  • Azure Resource Group (Optional)
  • Azure Key Vault (Used to store MSSQL sa username and password)
  • Azure Storage account and file shares (Used for persistent storage for sonarqube container)
  • Azure MSSQL instance and MSSQL database (Used for persistent database for sonarqube container)
  • Azure Container Group:
    • Sonarqube container instance
    • Caddy Reverse Proxy container instance (Automatic SSL for custom domain via Let's Encrypt)

image.png

Sonarqube is exposed over TCP port 9000, and uses a production-ready reverse proxy (caddy) using the sidecar pattern. Caddy will "automagically" take care of the SSL certificate setup, configuration and automatically proxy traffic to the sonarqube instance using 'Lets Encrypt certs'. Caddy requires zero configuration and provides out of the box secure https:// access to your sonarqube instance using your own custom domain.

image.png

NOTE: There are some rate limits using Let's Encrypt

More information can also be found here: caddy documentation.
Custom domain can be configured by giving your "custom.domain.com" value in the variable, var.caddy_config as shown in the snippet below.
See Examples for more details.

#Terraform caddy container commands:
container_commands = ["caddy", "reverse-proxy", "--from", "custom.domain.com", "--to", "localhost:9000"]

After resource creation, get the DNS-Label of the container group: (dnslabel).(azureregion).azurecontainer.io:

image.png

Ensure you create a DNS 'CNAME' on your DNS provider for your 'custom.domain.com' to point to the DNS label FQDN of the ACI container group.

image.png

Once the sonarqube instance is up and running, log in and change the default password:

  • User: Admin
  • Password: Admin

image.png

Sonarqube container image reference: Sonarqube docker image tags
Caddy container image reference: Caddy docker image tags

Example 1

Simple example where the entire solution is built in a new Resource Group (Default).
This example requires very limited input. Only specify an Azure Resource Group and required variable values and supply your own custom domain (FQDN) you want to link to the Let's encrypt cert using caddy_config and the container group DNS label using aci_dns_label.

provider "azurerm" {
  features {}
}

resource "random_integer" "number" {
  min = 0001
  max = 9999
}

module "sonarcube-aci" {
  source = "Pwd9000-ML/sonarqube-aci/azurerm"

  sonarqube_rg_name = "Terraform-Sonarqube-aci-simple-demo"
  kv_config = {
    name = "sonarqubekv${random_integer.number.result}"
    sku  = "standard"
  }
  sa_config = {
    name                      = "sonarqubesa${random_integer.number.result}"
    account_kind              = "StorageV2"
    account_tier              = "Standard"
    account_replication_type  = "LRS"
    min_tls_version           = "TLS1_2"
    access_tier               = "Hot"
    is_hns_enabled            = false
  }
  mssql_config = {
    name    = "sonarqubemssql${random_integer.number.result}"
    version = "12.0"
  }
  aci_group_config = {
    container_group_name = "sonarqubeaci${random_integer.number.result}"
    ip_address_type      = "Public"
    os_type              = "Linux"
    restart_policy       = "OnFailure"
  }
  aci_dns_label = "sonarqube-aci-${random_integer.number.result}"
  caddy_config = {
    container_name                  = "caddy-reverse-proxy"
    container_image                 = "ghcr.io/sashkab/docker-caddy2/docker-caddy2:latest"
    container_cpu                   = 1
    container_memory                = 1
    container_environment_variables = null
    container_commands              = ["caddy", "reverse-proxy", "--from", "custom.domain.com", "--to", "localhost:9000"]
  }
}

NOTE: Remember to create a DNS 'CNAME' record on your DNS provider to point your "custom.domain.com" to (dnslabel).(azureregion).azurecontainer.io

Example 2

Advanced example where the entire solution is built in an existing Resource Group (And supplying all possible variable values).
This example shows all configurable inputs.

provider "azurerm" {
  features {}
}

resource "random_integer" "number" {
  min = 0001
  max = 9999
}

module "sonarcube-aci" {
  source = "Pwd9000-ML/sonarqube-aci/azurerm"

  create_rg         = false
  sonarqube_rg_name = "pwd9000-sonarqube-aci-demo" #provide existing RG name (location for resources will be based on existing RG location)
  kv_config = {
    name = "sonarqubekv${random_integer.number.result}"
    sku  = "standard"
  }
  sa_config = {
    name                      = "sonarqubesa${random_integer.number.result}"
    account_kind              = "StorageV2"
    account_tier              = "Standard"
    account_replication_type  = "LRS"
    min_tls_version           = "TLS1_2"

    access_tier               = "Hot"
    is_hns_enabled            = false
  }
  shares_config = [
    {
      share_name = "data"
      quota_gb   = 10
    },
    {
      share_name = "extensions"
      quota_gb   = 5
    },
    {
      share_name = "logs"
      quota_gb   = 5
    },
    {
      share_name = "conf"
      quota_gb   = 1
    }
  ]
  pass_length        = 24
  sql_admin_username = "Sonar-Admin"
  mssql_config = {
    name    = "sonarqubemssql${random_integer.number.result}"
    version = "12.0"
  }
  mssql_fw_rules = [
    ["Allow All Azure IPs", "0.0.0.0", "0.0.0.0"]
  ]
  mssql_db_config = {
    db_name                     = "sonarqubemssqldb${random_integer.number.result}"
    collation                   = "SQL_Latin1_General_CP1_CS_AS"
    create_mode                 = "Default"
    license_type                = null
    max_size_gb                 = 128
    min_capacity                = 1
    auto_pause_delay_in_minutes = 60
    read_scale                  = false
    sku_name                    = "GP_S_Gen5_2"
    storage_account_type        = "Zone"
    zone_redundant              = false
    point_in_time_restore_days  = 7
    backup_interval_in_hours    = 24
  }
  aci_dns_label = "sonarqube-aci-${random_integer.number.result}"
  aci_group_config = {
    container_group_name = "sonarqubeaci${random_integer.number.result}"
    ip_address_type      = "Public"
    os_type              = "Linux"
    restart_policy       = "OnFailure"
  }
  sonar_config = {
    container_name                  = "sonarqube-server"
    container_image                 = "ghcr.io/metrostar/quartz/ironbank/big-bang/sonarqube-9:9.9.4-community"
    container_cpu                   = 2
    container_memory                = 8
    container_environment_variables = null
    container_commands              = []
  }
  caddy_config = {
    container_name                  = "caddy-reverse-proxy"
    container_image                 = "ghcr.io/sashkab/docker-caddy2/docker-caddy2:latest"
    container_cpu                   = 1
    container_memory                = 1
    container_environment_variables = null
    container_commands              = ["caddy", "reverse-proxy", "--from", "custom.domain.com", "--to", "localhost:9000"]
  }
  tags = {
    Terraform   = "True"
    Description = "Sonarqube aci with caddy"
    Author      = "Marcel Lupo"
    GitHub      = "https://github.com/Pwd9000-ML/terraform-azurerm-sonarqube-aci"
  }
}

NOTE: Remember to create a DNS 'CNAME' record on your DNS provider to point your "custom.domain.com" to (dnslabel).(azureregion).azurecontainer.io

Requirements

Name Version
terraform >= 1.9.5
azurerm ~> 3.110.0

Providers

Name Version
azurerm ~> 3.110.0
random n/a

Modules

No modules.

Resources

Name Type
azurerm_container_group.sonarqube_aci resource
azurerm_key_vault.sonarqube_kv resource
azurerm_key_vault_secret.password_secret resource
azurerm_key_vault_secret.username_secret resource
azurerm_mssql_database.sonarqube_mssql_db resource
azurerm_mssql_firewall_rule.sonarqube_mssql_fw_rules resource
azurerm_mssql_server.sonarqube_mssql resource
azurerm_resource_group.sonarqube_rg resource
azurerm_role_assignment.kv_role_assigment resource
azurerm_storage_account.sonarqube_sa resource
azurerm_storage_share.sonarqube resource
azurerm_storage_share_file.sonar_properties resource
random_password.sql_admin_password resource
azurerm_client_config.current data source
azurerm_resource_group.sonarqube_rg data source

Inputs

Name Description Type Default Required
aci_dns_label DNS label to assign onto the Azure Container Group. string n/a yes
aci_group_config Container group configuration object to create sonarqube aci with caddy reverse proxy.
object({
container_group_name = string
ip_address_type = string
os_type = string
restart_policy = string
})
n/a yes
caddy_config Caddy container configuration object to create caddy reverse proxy aci.
object({
container_name = string
container_image = string
container_cpu = number
container_memory = number
container_environment_variables = map(string)
container_commands = list(string)
})
{
"container_commands": [
"caddy",
"reverse-proxy",
"--from",
"custom.domain.com",
"--to",
"localhost:9000"
],
"container_cpu": 1,
"container_environment_variables": null,
"container_image": "ghcr.io/sashkab/docker-caddy2/docker-caddy2:latest",
"container_memory": 1,
"container_name": "caddy-reverse-proxy"
}
no
create_rg Create a new resource group for this deployment. (Set to false to use existing resource group) bool true no
kv_config Key Vault configuration object to create azure key vault to store sonarqube aci sql creds.
object({
name = string
sku = string
})
n/a yes
location Location in azure where resources will be created. (Only in effect on newly created Resource Group when var.create_rg=true) string "uksouth" no
mssql_config MSSQL configuration object to create persistent SQL server instance for sonarqube aci.
object({
name = string
version = string
})
n/a yes
mssql_db_config MSSQL database configuration object to create persistent azure SQL db for sonarqube aci.
object({
db_name = string
collation = string
create_mode = string
license_type = string
max_size_gb = number
min_capacity = number
auto_pause_delay_in_minutes = number
read_scale = bool
sku_name = string
storage_account_type = string
zone_redundant = bool
point_in_time_restore_days = number
backup_interval_in_hours = number
})
{
"auto_pause_delay_in_minutes": 60,
"backup_interval_in_hours": 24,
"collation": "SQL_Latin1_General_CP1_CS_AS",
"create_mode": "Default",
"db_name": "sonarqubemssqldb9000",
"license_type": null,
"max_size_gb": 128,
"min_capacity": 1,
"point_in_time_restore_days": 7,
"read_scale": false,
"sku_name": "GP_S_Gen5_2",
"storage_account_type": "Zone",
"zone_redundant": false
}
no
mssql_fw_rules List of SQL firewall rules in format: [[rule1, startIP, endIP],[rule2, startIP, endIP]] etc. list(list(string))
[
[
"Allow All Azure IPs",
"0.0.0.0",
"0.0.0.0"
]
]
no
pass_length Password length for sql admin creds. (Stored in sonarqube key vault) number 36 no
sa_config Storage configuration object to create persistent azure file shares for sonarqube aci.
object({
name = string
account_kind = string
account_tier = string
account_replication_type = string
access_tier = string
min_tls_version = string
is_hns_enabled = bool
})
n/a yes
shares_config Sonarqube file shares
list(object({
share_name = string
quota_gb = number
}))
[
{
"quota_gb": 10,
"share_name": "data"
},
{
"quota_gb": 10,
"share_name": "extensions"
},
{
"quota_gb": 10,
"share_name": "logs"
},
{
"quota_gb": 1,
"share_name": "conf"
}
]
no
sonar_config Sonarqube container configuration object to create sonarqube aci.
object({
container_name = string
container_image = string
container_cpu = number
container_memory = number
container_environment_variables = map(string)
container_commands = list(string)
})
{
"container_commands": [],
"container_cpu": 2,
"container_environment_variables": null,
"container_image": "ghcr.io/metrostar/quartz/ironbank/big-bang/sonarqube-9:9.9.4-community",
"container_memory": 8,
"container_name": "sonarqube-server"
}
no
sonarqube_rg_name Name of the existing resource group. (var.create_rg=false) / Name of the resource group to create. (var.create_rg=true). string "Terraform-Sonarqube-aci" no
sql_admin_username Username for sql admin creds. (Stored in sonarqube key vault) string "Sonar-Admin" no
tags A map of key value pairs that is used to tag resources created. map(string)
{
"Author": "Marcel Lupo",
"Description": "Sonarqube aci with caddy",
"GitHub": "https://github.com/Pwd9000-ML/terraform-azurerm-sonarqube-aci",
"Terraform": "True"
}
no

Outputs

Name Description
sonarqube_aci_container_group_id The container group ID.
sonarqube_aci_kv_id The resource ID for the sonarqube key vault.
sonarqube_aci_mssql_db_id The resource ID for the sonarqube MSSQL database.
sonarqube_aci_mssql_db_name The name of the sonarqube MSSQL database.
sonarqube_aci_mssql_id The resource ID for the sonarqube MSSQL Server instance.
sonarqube_aci_rg_id Output Resource Group ID. (Only if new resource group was created as part of this deployment).
sonarqube_aci_sa_id The resource ID for the sonarqube storage account hosting file shares.
sonarqube_aci_share_ids List of resource IDs of each of the sonarqube file shares.

About

Public Terraform Registry module for setting up an AZURE hosted Sonarqube ACI instance incl. persistent PaaS Database (Azure SQL), PaaS File Share (Azure Files) and custom domain using reverse proxy (Caddy) sidecar container.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages