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)
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.
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:
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.
Once the sonarqube instance is up and running, log in and change the default password:
- User: Admin
- Password: Admin
Sonarqube container image reference: Sonarqube docker image tags
Caddy container image reference: Caddy docker image tags
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
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
Name | Version |
---|---|
terraform | >= 1.9.5 |
azurerm | ~> 3.110.0 |
Name | Version |
---|---|
azurerm | ~> 3.110.0 |
random | n/a |
No modules.
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 |
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({ |
n/a | yes |
caddy_config | Caddy container configuration object to create caddy reverse proxy aci. | object({ |
{ |
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({ |
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({ |
n/a | yes |
mssql_db_config | MSSQL database configuration object to create persistent azure SQL db for sonarqube aci. | object({ |
{ |
no |
mssql_fw_rules | List of SQL firewall rules in format: [[rule1, startIP, endIP],[rule2, startIP, endIP]] etc. | list(list(string)) |
[ |
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({ |
n/a | yes |
shares_config | Sonarqube file shares | list(object({ |
[ |
no |
sonar_config | Sonarqube container configuration object to create sonarqube aci. | object({ |
{ |
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) |
{ |
no |
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. |