Skip to content

microsoft-sgp/deploy-github-enterprise-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Deploying GitHub Enterprise Server to Azure with Terraform

This repository provisions a GitHub Enterprise Server (GHES) instance on Microsoft Azure using Terraform. The Terraform state is stored remotely in an Azure Storage Account (blob backend).

The deployment is split into two Terraform workspaces:

Folder Purpose
azure-storage-blob-backend/ Bootstraps the Storage Account used to hold the remote Terraform state. Run this once, first.
ghes/ Provisions the GHES VM, networking, disks, and security rules. Uses the backend created above.

Architecture

The ghes/ workspace creates:

  • A resource group, virtual network, and subnet (10.0.0.0/16 / 10.0.1.0/24)
  • A Standard SKU static public IP
  • A network interface with an attached network security group (NSG)
  • NSG rules for web/git traffic (22, 25, 80, 443, 8080, 8443, 9418) and admin SSH (122)
  • A Linux VM running the GitHub Enterprise Server marketplace image (Gen2)
  • A 200 GB premium OS disk and a separate 200 GB premium data disk

Prerequisites

Requirement Version / Notes
Terraform >= 1.9.0
Azure CLI Latest
azurerm provider ~> 4.0 (installed automatically by terraform init)
Azure subscription Contributor rights to create resource groups, storage, networking, and VMs
SSH key pair Public key supplied via the ssh_public_key variable

GHES image / sizing: Defaults to image SKU github-enterprise-gen2, version 3.21.1, on a Standard_D8s_v4 VM (8 vCPU / 32 GiB) to meet GHES 3.x minimum requirements.


1. Azure authentication

Authenticate the Azure CLI and select the target subscription:

az login --tenant <TENANT_ID>
az account set --subscription <SUBSCRIPTION_ID>

Export the subscription ID so the azurerm 4.x provider can pick it up (required):

# bash / zsh
export ARM_SUBSCRIPTION_ID="$(az account show --query id -o tsv)"
# PowerShell
$env:ARM_SUBSCRIPTION_ID = (az account show --query id -o tsv)

See the Azure CLI authentication guide for service-principal and OIDC alternatives.


2. Create the Terraform state backend

This step creates the Storage Account that the GHES workspace uses for its remote state. It runs with local state.

cd azure-storage-blob-backend
terraform init
terraform plan      # review the 3 resources to be created
terraform apply

After apply, note the outputs (resource_group_name, storage_account_name, container_name). They must match the backend "azurerm" block in ghes/main.tf:

backend "azurerm" {
  resource_group_name  = "terraformbackend-resources"
  storage_account_name = "terraformbackendstoracct"
  container_name       = "terraformbackend-content"
  key                  = "terraform.tfstate"
  use_azuread_auth     = true
}

If you change the prefix variable, update the backend block in ghes/main.tf accordingly.


3. Deploy GitHub Enterprise Server (local)

cd ../ghes
terraform init     # connects to the remote backend created in step 2
terraform validate
terraform plan
terraform apply

When the apply completes, Terraform prints the public_ip output:

Outputs:

public_ip = "20.x.x.x"

Configurable variables

Override any of these via -var, a *.tfvars file, or environment variables (TF_VAR_<name>):

Variable Default Description
prefix ghes Name prefix for all resources
location japaneast Azure region
ghes_version 3.21.1 GHES marketplace image version
image_sku github-enterprise-gen2 github-enterprise-gen2 (Gen2) or GitHub-Enterprise (Gen1)
vm_size Standard_D8s_v4 VM size (>= 8 vCPU / 32 GiB for GHES 3.x)
admin_username ghadmin VM admin user
os_disk_size_gb 200 Root OS disk size
data_disk_size_gb 200 GHES data disk size
allowed_ssh_cidr * CIDR allowed to reach admin SSH (port 122) — restrict in production
ssh_public_key sample key SSH public key for VM access

Example:

terraform apply -var="location=eastus" -var="ghes_version=3.21.1" -var="allowed_ssh_cidr=203.0.113.0/24"

Complete GHES setup

  1. Open https://<public_ip> in a browser.
  2. Upload your GitHub Enterprise license file and set the management console password.
  3. Configure the instance (hostname, TLS, authentication) and let it restart.
  4. Verify GitHub Actions, then register self-hosted runners against the new hostname.

4. Deploy with GitHub Actions (optional)

To deploy via CI/CD, fork this repository and create an Azure service principal:

az ad sp create-for-rbac --name "ghes-terraform" --role Contributor \
  --scopes /subscriptions/<SUBSCRIPTION_ID>

Add the following repository Actions secrets (Settings -> Secrets and variables -> Actions):

Secret name Description
ARM_CLIENT_ID Service principal client ID
ARM_CLIENT_SECRET Service principal client secret
ARM_SUBSCRIPTION_ID Subscription ID
ARM_TENANT_ID Tenant ID

Workflows:

Both workflows use hashicorp/setup-terraform@v3 and actions/checkout@v4.

Tip: For improved security, replace the client-secret credentials with OIDC federated credentials.


5. Maintenance

# Detect drift
terraform plan -detailed-exitcode

# Show the current public IP
terraform output public_ip

# Tear down (destroys the GHES instance — back up first)
terraform destroy

GHES upgrade notes

  • GHES supports skipping at most ~2 feature releases per upgrade hop. To move an existing appliance to 3.21.x, upgrade sequentially (e.g. 2.20 -> 2.22 -> 3.0 -> ... -> 3.21) using the appliance upgrade/hotpatch packages — you cannot jump the running appliance directly.
  • Re-provisioning with a new ghes_version on this Terraform config replaces the VM; back up first with ghe-backup/ghe-restore.
  • Always take a backup and snapshot the data disk before any upgrade.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages