Appearance
Azure CI/CD pipeline
How Nomain container images and Bicep templates flow from Nomain's supply chain into your Azure subscription, and the recommended customer-side pipeline that runs Bicep from a self-hosted Azure DevOps agent with private connectivity to the stamp.
Advanced reference
This is an operator-level reference for the Azure BYOC deployment pipeline. Specific commands, stages, and sizing recommendations may change between releases. For the wider stamp architecture and prerequisites, see BYOC on Azure.
Overview
Nomain ships container images and Bicep templates. The customer owns the deployment pipeline. The recommended pattern below pulls the supply chain into the customer's perimeter (no runtime dependency on Nomain ACR) and runs Bicep from a self-hosted agent that already has private connectivity to the stamp.
The pipeline has two halves that share the same Azure DevOps and self-hosted agent footprint: image mirroring on top, and Bicep deployment below it.
Image mirroring from Nomain ACR
Nomain publishes immutable, cosign-signed images to nomainregistry.azurecr.io (5 service images plus the Helm OCI charts). The customer pulls them into their own ACR, the dedicated registry inside the stamp's resource group, so the runtime never depends on Nomain ACR availability and the customer's supply-chain controls (Defender scan, Notary signature verification, ACR retention policy) apply.
| Property | Recommended setup |
|---|---|
| Mechanism | az acr import --source nomainregistry.azurecr.io/<image>:<tag> --image <image>:<tag> against the customer ACR. Native ACR feature, no extra runner-side state. |
| Authentication | A scoped Nomain-issued pull token (read-only on nomainregistry.azurecr.io) is provisioned at customer onboarding. The token sits in your Key Vault and is referenced from the ADO pipeline as a secret variable. |
| Cadence | On every Nomain release (typically every 1-2 weeks). The pipeline can be triggered manually, on a schedule, or by a webhook from Nomain announcing the new tag. |
| Tag strategy | Mirror specific immutable semver tags only (e.g. 2026.05.0), never floating tags like latest or production. The Bicep values.yaml in your env pins the exact tag the App Services pull. |
| Signature verification | Images are cosign-signed against a Nomain public key. The mirror job can verify signatures pre-push, and ACR Trust Policies / Notary v2 can enforce them on pull (recommended for prod). |
| Scanning | Microsoft Defender for Cloud, Container Registries plan, scans the customer ACR on push, flagging CVEs before any App Service pulls the image. |
| Rollback | Previous tags stay in the customer ACR until the retention policy expires them. Rollback is a Bicep redeploy with the previous tag value, no re-pull from Nomain needed. |
Net effect
After first onboarding, the runtime stamp has zero connectivity to Nomain ACR. Image pulls during scale-out, restart, or recovery all terminate at the customer's ACR Private Endpoint.
Recommended deployment tool: Azure DevOps
Azure DevOps is the recommended deployment tool for this BYOC pattern because customers in risk-sensitive environments usually already operate it, and because its self-hosted agent model maps cleanly onto the private-VNet posture of the stamp.
- Aligns with existing Azure tenancy. Service connections to your Azure subscription use federated Workload Identity, so there are no service-principal secrets to rotate. Repos, pipelines, artifacts, and the agent pool live inside the same tenant boundary.
- Self-hosted agent in your DevOps VNet. A VM (or VMSS scale set) running the ADO agent service, with its NIC in a dedicated DevOps VNet that is peered to the stamp VNet's
deploymentSubnet. Bicep can reach private endpoints without any public route. - No public exposure. The pipeline talks to private endpoints: the App Service SCM endpoint, Key Vault data-plane, and ACR data-plane are all reached over the peered VNet using their
privatelink.*DNS records. Microsoft-hosted agents cannot reach these and are not recommended. - Approval gates. ADO Environments give you native manual-approval gates between dev, staging, and prod, combined with Bicep's
what-ifdry-run in each stage as the change-control evidence.
Reference pipeline stages
| Stage | What it does | Runs on |
|---|---|---|
| 1. Lint & build | az bicep build + bicep lint on the Bicep templates and per-env parameter files. No Azure write access needed. | Microsoft-hosted agent (no private resources touched) |
| 2. Mirror images | az acr import from Nomain ACR into customer ACR for the target release tag. Optional cosign signature verification step before importing. | Self-hosted agent (DevOps VNet) |
| 3. Bicep what-if | az deployment sub what-if against the target subscription. Output published as a pipeline artifact for the approver to review. | Self-hosted agent |
| Manual approval | ADO Environment gate, required for staging and production deploys. | (gate only) |
| 4. Deploy | az deployment sub create with the per-env Bicep parameter file. WorkOS / M2M secrets injected as pipeline secrets at this step. | Self-hosted agent |
| 5. Smoke test | HTTPS probe against the webapp, healthcheck against each API, Postgres connectivity check via private endpoint. Failure rolls back to the previous Bicep deployment. | Self-hosted agent |
| 6. Tag & release | Tag the deployed commit in the ADO repo with the release version, attach Bicep what-if and smoke-test outputs as the audit trail. | Microsoft-hosted agent |
Self-hosted agent: sizing and placement
| Item | Recommendation |
|---|---|
| Form factor | VMSS scale set with 1-2 instances for HA. VM image: latest Ubuntu LTS with Azure CLI + Bicep + Docker pre-baked. |
| Size | Standard_D2s_v5 (2 vCPU / 8 GiB) is enough. Bicep deploys are I/O- and API-bound, not CPU-bound. |
| VNet placement | Dedicated DevOps VNet, peered to the stamp VNet. Reuse the same DevOps VNet across all environments (dev / staging / prod) so the agent pool is one set of nodes, not three. |
| Identity | VMSS bound to a user-assigned managed identity with Contributor on the stamp RG (or scoped down further with custom roles). No service-principal secrets in pipeline variables. |
| Outbound | Only needs egress to dev.azure.com (the ADO control plane). All other traffic is inbound from the peered VNet. |
| Patching | VMSS rolling reimage on a weekly schedule, or use Azure Image Builder with a baked-in image refreshed monthly. |
If Azure DevOps isn't an option
GitHub Actions and GitLab CI both work with the same shape: Bicep plus a private agent in a peered VNet. The pipeline stages translate one-to-one. Microsoft-hosted runners and shared runners cannot complete the deploy because the App Service SCM endpoint is private. A self-hosted runner inside the VNet is required regardless of the CI platform you choose.
For the full stamp architecture, prerequisites, and secret handling that this pipeline deploys into, see BYOC on Azure.