Skip to content

Project Summary

This page summarizes the work done across the Hinze Technologies repositories.

SampleBlazor.Web

Repository: konradhinze/sampleblazor

A sample Blazor WebAssembly application that serves as the first containerized workload deployed on the Hinze Technologies Azure infrastructure.

What It Is

SampleBlazor.Web is a client-side Blazor WebAssembly application built on .NET 10. It includes the default Blazor template pages (Home, Counter, Weather) and is served as a static site via nginx inside a Docker container.

What Was Done

  • Created the Blazor WebAssembly project using the standard .NET Blazor template with interactive WebAssembly render mode
  • Dockerized the application with a multi-stage Dockerfile:
    • Build stage: .NET SDK 10.0 restores, builds, and publishes the app
    • Runtime stage: nginx Alpine serves the static wwwroot output on port 80
  • Set up the Azure DevOps pipeline (azure-pipelines.yml) to:
    1. Install .NET SDK 10.0
    2. Publish the Blazor app in Release configuration
    3. Build and tag the Docker image as acrht.azurecr.io/sampleblazorweb:{BuildId}
    4. Push the image to Azure Container Registry (acrht)
    5. Deploy the container app using the container-pipeline.yml template from azure-templates
  • Deployed as a Container App (ca-sampleblazorweb-ht-dev) in the dev environment, accessible via the Application Gateway at sampleblazorweb.dev.hinze-technologies.com

Tech Stack

Component Technology
Framework .NET 10 Blazor WebAssembly
Web Server nginx Alpine
Container Registry Azure Container Registry (acrht)
Hosting Azure Container Apps
CI/CD Azure DevOps Pipelines

Infrastructure

Repository: konradhinze/infrastructure

Contains the Azure DevOps pipeline definitions that deploy the shared and environment-specific Azure infrastructure for Hinze Technologies.

What Was Done

  • Created global-pipeline.yml — Deploys global shared services (ACR, Managed Identity, Log Analytics, App Insights, Global Key Vault) to rg-ht-global using the global-pipeline.yml template from azure-templates
  • Created global-dev.yaml — Deploys dev environment infrastructure (VNet, Container Apps Environment, Application Gateway WAF v2, Private Endpoints, DNS Zones, Environment Key Vault) to rg-ht-dev using the environment-pipeline.yml template from azure-templates

Both pipelines:

  • Reference the konradhinze/azure-templates repository as a template source
  • Use the HinzeTechnologiesPlayground Azure service connection
  • Are configured with prefix ht and region northeurope
  • Trigger on pushes to the main branch

Pipeline Configuration

Pipeline File Template Used Target Resource Group What It Deploys
global-pipeline.yml global-pipeline.yml@azure-templates rg-ht-global ACR, Managed Identity, Log Analytics, App Insights, Global KV
global-dev.yaml environment-pipeline.yml@azure-templates rg-ht-dev VNet, NSGs, CAE, App Gateway, Private Endpoints, DNS, Env KV

Key Variables

Variable Value Description
prefix ht Resource naming prefix
location northeurope Azure region
azureServiceConnection HinzeTechnologiesPlayground Azure DevOps service connection
domainName dev.hinze-technologies.com Custom domain for host-based routing (dev only)

Azure Templates

Repository: konradhinze/azure-templates

A library of reusable Bicep modules and Azure DevOps pipeline templates that provide the building blocks for the entire infrastructure.

What Was Done

Bicep Modules (_modules/)

  • global.bicep — Shared services deployed once per project:

    • Azure Container Registry (Basic SKU, public access enabled)
    • User-Assigned Managed Identity (used by all container apps for ACR pull and Key Vault access)
    • Log Analytics Workspace (PerGB2018 pricing, 30-day retention)
    • Application Insights (Web type, linked to Log Analytics)
    • Global Key Vault (Standard, RBAC-enabled, soft delete)
    • RBAC role assignment: Managed Identity gets Key Vault Secrets User on Global KV
  • global.environment.bicep — Environment-specific infrastructure deployed per environment:

    • Virtual Network (10.0.0.0/16) with three subnets:
      • snet-containerapps (10.0.0.0/23) — delegated to Container Apps
      • snet-privateendpoints (10.0.4.0/24) — for Private Endpoints
      • snet-appgw (10.0.8.0/24) — for Application Gateway
    • Three Network Security Groups with environment-appropriate rules
    • Container Apps Environment (internal, VNet-integrated, Log Analytics-connected)
    • Private DNS Zone for the Container Apps default domain
    • Application Gateway WAF v2 with:
      • Public IP (Standard, Static)
      • Host-based routing for container apps ({appName}.{domainName})
      • HTTPS backend settings with health probes
      • WAF policy (OWASP 3.2, Prevention mode)
      • Dynamic backend pools, listeners, and routing rules based on discovered apps
    • Environment Key Vault (Standard, RBAC, private access only)
    • Private Endpoints for Key Vault and Log Analytics
    • Private DNS Zones with VNet links for privatelink.vaultcore.azure.net and privatelink.ods.opinsights.azure.com
    • RBAC: Managed Identity gets Key Vault Secrets User on Environment KV
  • containers.bicep — Reusable container app module:

    • Deploys a single Container App with user-assigned managed identity
    • External ingress on port 80 with HTTPS transport
    • ACR registry authentication via managed identity
    • Application Insights integration via environment variable
    • Auto-scaling: 1–3 replicas based on HTTP concurrency (50 requests)
    • Outputs: resource ID, FQDN, and name (saved to Key Vault for discovery)

Pipeline Templates (pipelines/)

  • global-pipeline.yml — Deploys global.bicep and saves outputs to Global Key Vault
  • environment-pipeline.yml — Reads global outputs from Key Vault, discovers existing container apps, deploys global.environment.bicep with app routing, saves environment outputs to Environment Key Vault
  • container-pipeline.yml — Reads global and environment secrets from Key Vault, deploys containers.bicep, saves container app outputs (ID, FQDN, name) to Environment Key Vault for App Gateway discovery

Helper Templates (pipelines/templates/)

  • read-keyvault.yml — Reads secrets from an Azure Key Vault and sets them as pipeline variables
  • save-outputs-to-keyvault.yml — Saves Bicep deployment outputs as Key Vault secrets
  • deploy-bicep.yml — Deploys a Bicep template to a resource group

Design Patterns

Key Vault as State Store

Pipeline outputs are persisted in Azure Key Vault, enabling cross-pipeline data sharing. Global outputs (ACR login server, managed identity ID, etc.) are stored in the Global Key Vault (kvg-ht), while environment-specific outputs are stored in Environment Key Vaults (kv-ht-{env}).

Dynamic App Gateway Routing

The environment pipeline discovers deployed container apps by scanning Key Vault secrets (pattern: containerApp-*-name / containerApp-*-fqdn). It then passes the apps array to global.environment.bicep, which dynamically generates App Gateway backend pools, HTTP listeners, and routing rules.

Layered Deployment

Infrastructure is deployed in three layers with clear dependency ordering: Global → Environment → Applications. Each layer consumes outputs from the previous layer via Key Vault secrets.