Deploying Veramo on Azure using Terraform and Helm (Part 1): A Step-by-Step Guide for deploying a DID and Verifiable Credentials framework

Environment Setup using Terraform.

Rameez
6 min readFeb 28, 2024

For a recent project at ISO-Gruppe we decided to use Veramo framework for managing and creating DIDs and Verifiable Credentials. “Veramo is a JavaScript framework that makes it easy for anyone to use cryptographically verifiable data in their applications. It was designed to make it easy for developers who want to use DIDs, verifiable credentials, and data-centric protocols to bring next-generation features to their users”. This guide covers the deployment of Veramo Cloud Agent to Azure. We decided to create it as the official deployment docs from Veramo only cover deployment to AWS and Heroku. This article focuses on creating an environment on Azure. If you have already created the necessary infrastructure please refer to Part 2 which covers the deployment of Veramo Agent into Azure Kubernetes Service using Helm.

Prerequisites

  1. Azure Account
  2. Terraform
  3. Helm
  4. Docker

Azure environment setup

We will use Terraform to create the required infrastructure elements on Azure. This guide assumes that you have already created an Azure account and have downloaded the required access credentials on your local machine. If not, please do so by typing az login in your terminal. Our environment will consist of the following:

  1. Azure Kubernetes Service (AKS)
  2. Azure Container Registry (ACR)
  3. Azure Database for PostgreSQL
  4. Azure Resource group

Environment creation with Terraform

We will create Terraform modules for each of these four elements. This approach has the added benefit of creating repeatable infrastructure which can be deployed for different projects and users. You can start by creating a new repository for your Infrastructure. This repository will hold the Terraform scripts to create and configure an Azure environment for Veramo deployment. Add the files and folders to this repo as shown in the picture below:

The modules folder contains the sub-modules which are used to create the desired infrastructure on Azure. Each sub-module contains three files i.e. main, variables, and output. main.tf contains the Terraform script to create a particular piece of infrastructure. variables.tf contains the variables which are used to configure this module and outputs.tf contains output variables which can be used by other modules. Veramo folder contains the terraform.tfvars file which we can use to instantiate and configure sub-modules.

Azure Container Registry

Copy and paste the following code in the main.tf file for your container registry:

resource "azurerm_container_registry" "acr" {
name = var.container_registry_config.name
resource_group_name = var.resource_group_name
location = var.location
sku = var.container_registry_config.sku
admin_enabled = true
}

The variables.tf file will contain the following variables:

variables.tf

The outputs.tf file:

outputs.tf

Azure Kubernetes Service

  1. main.tf:
resource "azurerm_kubernetes_cluster" "aks" {
name = var.aks_name
location = var.location
resource_group_name = var.resource_group_name
dns_prefix = var.dns_prefix

default_node_pool {
name = var.node_pool.name
node_count = var.node_pool.node_count
vm_size = var.node_pool.vm_size
}

identity {
type = "SystemAssigned"
}

http_application_routing_enabled = false

tags = {
Environment = var.env
}
}

2. Variables.tf

AKS variables.tf

3. Outputs.tf

AKS outputs.tf

Azure flexible PostgreSQL

  1. main.tf:
resource "azurerm_postgresql_flexible_server" "psql" {
name = var.azurerm_postgresql_server_config.name
resource_group_name = var.resource_group_name
location = var.location
version = var.azurerm_postgresql_server_config.version

administrator_login = var.azurerm_postgresql_server_config.admin_user
administrator_password = var.azurerm_postgresql_server_config.admin_pw
zone = var.azurerm_postgresql_server_config.zone

storage_mb = var.azurerm_postgresql_server_config.storage_mb

sku_name = var.azurerm_postgresql_server_config.sku_name

}

#### configure access from within azure ####
resource "azurerm_postgresql_flexible_server_firewall_rule" "azure" {

name = "allow-access-from-azure-services"
server_id = azurerm_postgresql_flexible_server.psql.id
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}

#### configure access from internet ####
resource "azurerm_postgresql_flexible_server_firewall_rule" "external" {

name = "allow-all-ips"
server_id = azurerm_postgresql_flexible_server.psql.id
start_ip_address = "x.x.x.x" # external IP address range start
end_ip_address = "x.x.x.x" # external IP address range end
}

2. Variables.tf

variables.tf

Azure Resource Group

  1. main.tf:
resource "azurerm_resource_group" "rg" {
name = var.group_name
location = var.location
tags = var.tags
}

2. Variables.tf:

resource group variables.tf

3. Outputs.tf:

azure resource group outputs.tf

Instantiate sub-modules in Veramo folder

  1. main.tf:
# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}

}
required_version = ">= 1.1.0"
}

provider "azurerm" {
features {}
}


resource "azurerm_resource_group" "resource_group" {
name = "veramo-resource-group"
location = var.location
}

module "container-registry" {
source = "../modules/azure_container_registry"

resource_group_name = azurerm_resource_group.resource_group.name
location = var.location

# Azure Container Registry configuration
container_registry_config = {
name = var.container_registry_config.name
sku = var.container_registry_config.sku
}
}

module "kubernetes-cluster" {
source = "../modules/azure_kubernetes_cluster"
aks_name = var.aks_name
env = var.env
resource_group_name = azurerm_resource_group.resource_group.name
location = var.location
dns_prefix = var.dns_prefix

# node_pool
node_pool = {
name = var.node_pool.name
node_count = var.node_pool.node_count
vm_size = var.node_pool.vm_size
}

}

resource "azurerm_role_assignment" "aks" {
principal_id = module.kubernetes-cluster.kubelet_identity_principal_id
role_definition_name = "AcrPull"
scope = module.container-registry.container_registry_id
skip_service_principal_aad_check = true
}

module "azure_managed_flexible_postgres_db" {

source = "../modules/azure_flexible_postgresql"
resource_group_name = azurerm_resource_group.resource_group.name
location = var.location
private_dns_name = var.private_dns_name
azurerm_postgresql_server_config = var.azurerm_postgresql_server_config
}

2. terraform.tfvars:

# module resource_group
resource_group_name = "resource_group_name"
location = "Germany West Central"

# module azure_container_registry
container_registry_config = {
name = "veramoRegistry"
sku = "Basic"
}

# module azure_kubernetes_cluster
aks_name = "veramo-cluster"

env = "dev"
dns_prefix = "veramo"

node_pool = {
name = "default"
node_count = 1
vm_size = "Standard_B4as_v2" #"Standard_B2as_v2"
}

# module azure_flexible_postgresql
azurerm_postgresql_server_config = {
name = "veramo-demo-db"
admin_user = "yourUserNAME" # change
admin_pw = "yourSUperSecurePassword" # change
sku_name = "B_Standard_B1ms"
version = "13"
storage_mb = 32768
zone = "1"
}

private_dns_name = "veramo-db"

3. Variables.tf:

##### resource group ##### 
variable location {
type = string
description = "Resource Group Location"
}

variable resource_group_name {
type = string
description = "Resource Group Name"
}

##### container registry #####
variable "container_registry_config" {
description = "Manages an Azure Container Registry"
type = object({
name = string
admin_enabled = optional(bool)
sku = optional(string)
public_network_access_enabled = optional(bool)
quarantine_policy_enabled = optional(bool)
zone_redundancy_enabled = optional(bool)
})
}

##### kubernetes cluster #####
variable "aks_name" {
type = string
}

variable "env" {
type = string
description = "environment name"
}


variable "dns_prefix" {
type = string
description = "dns prefix for generating fqdn for this cluster"
}

variable "node_pool" {
description = "Manages an aks node pool"
type = object({
name = string
node_count = number
vm_size = string
})
}

#### azure postgres db ####
variable "azurerm_postgresql_server_config" {
description = "Manages an Azure flexible postgres sql server"
type = object({
name = string
admin_user = string
admin_pw = string
sku_name = string
version = string
zone = optional(string)
storage_mb = number

})
}

variable "private_dns_name" {
type = string
description = "Resource Group Location"
}

Bringing it all together

Switch to veramo folder and run the following commands:

Step -1

terraform init
tf init

Step -2

terraform plan

If everything is ok, you will see an output as follows:

Step-3

terraform apply

Terraform apply command will create the necessary infrastructure on Azure for you.

The output of the terraform apply will look as follows.

Enter yes to create your infrastructure.

If everything goes well, you should see an output as follows:

infrastructure created

If you already have the necessary infrastructure in place, please refer to Part 2 which covers the deployment of Veramo Agent into Azure Kubernetes Service using Helm.

If you have any further questions, please contact us at info@iso-gruppe.com.

--

--