Jenkins Controller on Azure (VM)
Self-hosted Jenkins on a hardened Azure Linux VM — self-contained vnet/subnet/NSG, SSH-key auth only, managed-disk encryption, Jenkins installed via cloud-init.
Verification
Live-testedReally deployed, verified, idempotent and destroyed in a cloud sandbox.
Conformance
- Static validation (fmt · validate · tflint)
- Security scan (Checkov)
- Plan tests (mocked: validation rules · outputs)
Provenance
- SHA-256 checksum
- Signature (pending)
Functional
- Live-tested — applied, verified, destroyed
Last verified 2026-06-29 · how we verify
Documentation
azure-jenkins
Status: static-validated, live-test pending. Ships under live-test quarantine until promoted by the Azure live lane. Schema is validated against the azurerm v4 provider docs. Jenkins installs asynchronously via cloud-init after the VM boots — the apply completes before Jenkins is reachable.
A fully self-contained Jenkins controller on a single Azure Linux VM. One
tofu apply creates everything — resource group, virtual network, subnet, NSG,
NIC, an optional public IP and the VM — and bootstraps Jenkins via cloud-init.
tofu destroy removes all of it (including the resource group). Works with
Terraform and OpenTofu (>= 1.6), azurerm provider >= 4.0, < 5.0.
What it provisions
azurerm_resource_group(created and destroyed by this module)azurerm_virtual_network+azurerm_subnetazurerm_network_security_group— SSH (22) and the Jenkins UI (jenkins_port) allowed only fromallowed_source_cidr, plus an explicit DenyAllInboundazurerm_network_interface(+ NSG association)- optional
azurerm_public_ip(Standard, static;create_public_ip) azurerm_linux_virtual_machine(SSH-key-only, system-assigned identity, cloud-init Jenkins bootstrap)
Secure defaults
- SSH-key auth only —
disable_password_authentication = true; a validadmin_ssh_public_keyis required. - No open ingress by default —
allowed_source_cidris required (no default) and gates both SSH and the Jenkins UI; a catch-all rule denies everything else. - System-assigned managed identity for least-privilege role grants.
- OS disk encrypted at rest with platform-managed keys (always on in Azure).
- Optional Trusted Launch (Secure Boot + vTPM) for capable VM sizes
(
secure_boot_enabled/vtpm_enabled, off by default so the cheapest B1s size always applies).
Usage
module "jenkins" {
source = "./azure-jenkins"
name = "ci-prod"
location = "eastus"
allowed_source_cidr = "203.0.113.10/32" # your office / VPN CIDR
admin_ssh_public_key = file("~/.ssh/id_ed25519.pub")
vm_size = "Standard_B2s"
tags = { Environment = "prod" }
}
After apply, SSH in and read the initial admin password:
ssh azureadmin@<public_ip>
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
# then browse http://<public_ip>:8080
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
name | string | jenkins | Base name; prefixes all resources + VM hostname |
location | string | — | Azure region (required) |
resource_group_name | string | null | RG to create; null => rg-<name> |
vnet_address_space | list(string) | ["10.20.0.0/16"] | VNet address space |
subnet_address_prefixes | list(string) | ["10.20.1.0/24"] | Subnet prefixes |
allowed_source_cidr | string | — | Required. Source CIDR for SSH + Jenkins UI |
create_public_ip | bool | true | Attach a Standard static public IP |
jenkins_port | number | 8080 | Jenkins UI port (also opened in the NSG) |
vm_size | string | Standard_B1s | VM size |
admin_username | string | azureadmin | Local admin (SSH-key only) |
admin_ssh_public_key | string | — | Required. OpenSSH public key |
os_disk_type | string | StandardSSD_LRS | OS managed-disk SKU |
os_disk_size_gb | number | 32 | OS disk size (GB) |
source_image | object | Ubuntu 22.04 LTS Gen2 | Marketplace image |
secure_boot_enabled | bool | false | Trusted Launch: UEFI Secure Boot |
vtpm_enabled | bool | false | Trusted Launch: virtual TPM |
custom_data | string | null | Override the built-in cloud-init (raw) |
tags | map(string) | {} | Tags applied to all resources |
Outputs
vm_id, public_ip, private_ip, jenkins_url, nsg_id,
resource_group_name, identity_principal_id.
Requirements & notes
- Terraform or OpenTofu
>= 1.6;hashicorp/azurerm>= 4.0, < 5.0. - Authenticate via
az login(or a service principal); setARM_SUBSCRIPTION_ID. Seedocs/CONNECTING-PROVIDERS.md#azure. - Tighten
allowed_source_cidrto a/32admin address;0.0.0.0/0is only acceptable for short-lived throwaway tests. - Trusted Launch is off by default for broad VM-size compatibility (including the
cheapest
Standard_B1s); enablesecure_boot_enabled+vtpm_enabledon a Trusted-Launch-capable size for production. - Jenkins is installed asynchronously by cloud-init after first boot; give it a minute or two before the UI responds.
Verification
Static-validated (tofu fmt, tofu validate, tflint, checkov). Live
apply/verify/destroy testing pending an Azure sandbox subscription — see catalog
status.
License
Commercial — LicenseRef-IaCBazaar-Commercial