Skip to content

Terraform/Tofu Modules

Merkalis publishes OpenTofu modules that compose into a complete Kastoria environment on Azure. The sample deployment below illustrates what they provision when applied together; the module pages that follow document each one.

Sample Deployment

The diagram below shows the resources created when the sample environment configuration is applied. It is a reference deployment that the Merkalis Terraform/OpenTofu modules listed below are designed to produce.

graph TB

  subgraph AZURE["Azure"]
    subgraph INFRA["Azure subscription (infra)"]
      ACR["ACR<br/>infra-rg"]
    end

    subgraph DEV["Azure subscription (dev) · RG rg"]
      UMI["User Managed Identity<br/>umi-*-secrets<br/>umi-*-app-id"]

      subgraph NET["Networking"]
        subgraph VNET["VNet vnet<br/>10.x.0.0/16"]
          SUB_COMPUTE["compute · 10.x.0.0/21<br/>Service Endpoints: Microsoft.ContainerRegistry, Microsoft.KeyVault, Microsoft.Storage<br/>delegated to Microsoft.App"]
          SUB_STORAGE["storage · 10.x.8.0/24<br/>Service Endpoints: Microsoft.Storage"]
        end
      end

      subgraph SEC["Secrets"]
        KV["Key Vault kv-*-1a99<br/>RBAC · deny-by-default"]
        UMI_SEC["umi-*-secrets"]
        KV -.->|Key Vault Secrets User| UMI_SEC
      end

      subgraph OBJ["fa:fa-id-badge Object store - sharded"]
        subgraph SN["node storage account(s)<br/>1..n"]
          SN_BLOB["BLOB store"]
          SN_TAB["table store"]
        end
        subgraph SB["block storage account(s)<br/>1..n"]
          SB_BLOB["BLOB store"]
          SB_TAB["table store"]
        end
      end

      subgraph COMPUTE["Container App Environment"]
        LA["Log Analytics logs"]
        OHIF["app-*--ohif<br/>OHIF viewer · :8080 ext"]
        KAST["fa:fa-id-badge app-*--kastoria<br/>:3000 ext"]
        SMART["fa:fa-id-badge app-*--smartlaunchapi<br/>:4000 ext"]
        PROXY["app-*--kastoria-proxy<br/>:8080 int"]
        OTEL["otel-gateway<br/>OTel collector · :4317 int"]
        JPROC["fa:fa-id-badge job-*-stdyproc<br/>study processor"]
      end
    end
  end

  NET ~~~ SEC
  UMI ~~~ NET
  PROXY <--> KAST
  PROXY <--> SMART
  PROXY <--> OHIF

  ACR -.->|AcrPull| PROXY
  ACR -.->|AcrPull| OTEL

  KAST <-.-> OBJ
  SMART <-.-> OBJ
  JPROC <-.-> OBJ

  KAST -.->|metrics/traces| OTEL
  SMART -.->|metrics/traces| OTEL
  OHIF -.->|metrics/traces| OTEL
  JPROC -.->|metrics/traces| OTEL

  USER --> PROXY
  OHIF --> LA
  KAST --> LA
  SMART --> LA
  PROXY --> LA
  JPROC --> LA

  classDef computeFill fill:#dbeafe,stroke:#1e40af,color:#000;
  classDef storageFill fill:#dcfce7,stroke:#166534,color:#000;
  classDef gatewayFill fill:#fef3c7,stroke:#92400e,color:#000;
  class SUB_COMPUTE computeFill
  class SUB_STORAGE storageFill
  class SUB_GATEWAY gatewayFill
  class LA,OHIF,KAST,SMART,PROXY,CFAPP,OTEL,JPROC computeFill
  class SN,SB storageFill
  class SN_BLOB,SN_TAB,SB_BLOB,SB_TAB storageFill

Notes

  1. The Azure Container Registry (ACR) and resource group (infra-rg) are shown in a separate subscription as that is how they are deployed at Merkalis. Having an ACR is a deployment prerequisite.
  2. The VNet is segmented into 2 subnets (compute and storage). The diagram denotes which subnet each component is a member of by using matching colors.
  3. All communications on the compute subnet are secured by mTLS.
  4. All communications to/from the storage subnets are secured by TLS 1.2

Modules

Documentation for the Merkalis Azure modules is available below. Each page covers the module's features, prerequisites, inputs, outputs, and example usage.

Module Description
Networking Provisions a Virtual Network (vNet) and subnets with consistent FinOps tagging
Secrets Provisions a purge-protected Azure Key Vault with RBAC and a reader managed identity
Object Store Provisions sharded Azure Storage Accounts for Blob object storage with mirrored Azure Tables
File Store Provisions sharded Azure Storage Accounts with SMB file shares encrypted at rest and in transit
Queue Provisions a dedicated, key-disabled Azure Storage Account with a single queue for Notification Events
Compute Provisions a shared Container App Environment with container apps and jobs
Gateway Provisions the reverse proxy entrypoint, with optional Cloudflare Tunnel and mTLS proxy
Telemetry Provisions an OpenTelemetry collector container app with optional Grafana Cloud pipelines

How the module outputs and inputs wire together — and the effective build order — is documented in Module Dependencies.

A complete, hand-composed configuration that provisions the sample deployment above — including the full main.tf and a walk-through of every wire — lives in Sample Deployment.