Deploying GitHub Enterprise Server on Azure using Bicep

11 mins read

Learn how to deploy GitHub Enterprise Server on Azure using Infrastructure-As-Code.

đŸ’ȘDeploying GitHub Enterprise Server on Azure using Bicep

In this article, we will leverage Bicep, the new language for declaratively deploying Azure resources, and author a Bicep template to deploy GitHub Enterprise Server.

We will perform the following steps:

Create SSH KeypairCreate our Bicep templateDeploy Bicep template

1. Create SSH Key Pair

The first step is to create an SSH key pair; you can check the following article on how to create an SSH key pair for Linux VMs in Azure — https://docs.microsoft.com/en-us/azure/virtual-machines/linux/mac-create-ssh-keys

In this case, we will create an SSH key pair using the Azure Bash console. In the Azure Portal, request a new console as shown in the below image:

Azure Portal — Bash

Then we will generate an SSH Key using the command below:

ssh-keygen
-m PEM
-t rsa
-b 4096
-C “github-enterprise”
-f ~/.ssh/ge-priv-key
-N yourpasshphrase

This will generate the Key under the SSH directory in your file share:

SSH Keys

If you’re not familiar with the format of an SSH public key, you can display your public key with the following cat command, replace ‘~/.ssh/id_rsa.pub’ with the path and filename of your own public key file if needed:

cat ~/.ssh/ge-priv-key.pub

The above command will show the SSH public key in the console. We will need it during deployment time so have it at hand.

Cool! Now we have the SSH key pair.

2. Azure Bicep template — parameters

We will define start by defining the parameters for the virtual machine.

The code below shows the parameters to be utilized for this deployment:

@description(‘Unique prefix for your Storage Account and VM name. Must be all lower case letters or numbers. No spaces or special characters.’)
param accountPrefix string@description(‘Username for the VM. This value is ignored.’)
param adminUsername string@description(‘VM Size. Select an ES v3 Series VM with at least 32 GB of RAM. Default value: Standard_E4s_v3’)
param vmSize string = ‘Standard_E4s_v3’@description(‘Select a Premium Storage disk capacity for your source code, in GB. Default value: 512.’)
param storageDiskSizeGB int = 512@allowed([
‘sshPublicKey’
‘password’
])
@description(‘Type of authentication to use on the Virtual Machine. SSH key is recommended.’)
param authenticationType string = ‘sshPublicKey’@description(‘SSH Key or password for the Virtual Machine. SSH key is recommended.’)
@secure()
param adminPasswordOrKey string@description(‘Location for all resources.’)
param location string = resourceGroup().location

Note that we use a “@secure()” decorator to pass on the SSH key securely. I recommend you look at this article on how to leverage the @secure() decorator to pass on secrets in parameters securely.

3. Azure Bicep template — variables

Next, we will define the following variables:

var imagePublisher = ‘GitHub’
var imageOffer = ‘GitHub-Enterprise’
var OSDiskName = ‘osdiskforlinuxsimple’
var nicName_var = ‘${replace(replace(accountPrefix, ‘.’, ”), ‘_’, ‘-‘)}-nic’
var addressPrefix = ‘10.0.0.0/16’
var subnetName = ‘Subnet’
var subnetPrefix = ‘10.0.0.0/24’
var storageAccountType = ‘Premium_LRS’
var storageAccountName_var = ‘${replace(replace(replace(accountPrefix, ‘.’, ”), ‘_’, ”), ‘-‘, ”)}data’
var publicIPAddressName_var = ‘${replace(replace(accountPrefix, ‘.’, ”), ‘_’, ‘-‘)}-pub-ip’
var publicIPAddressType = ‘Dynamic’
var dnsNameForPublicIP = ‘${accountPrefix}-ghe’
var vmName_var = ‘${replace(replace(accountPrefix, ‘.’, ”), ‘_’, ‘-‘)}-ghe-vm’
var virtualNetworkName_var = ‘${replace(replace(accountPrefix, ‘.’, ”), ‘_’, ‘-‘)}-vnet’
var networkSecurityGroupName_var = ‘${replace(replace(accountPrefix, ‘.’, ”), ‘_’, ‘-‘)}-nsg’
var subnetRef = resourceId(‘Microsoft.Network/virtualNetworks/subnets’, virtualNetworkName_var, subnetName)
var dataDiskName = ‘ghe-data’
var linuxConfiguration = {
disablePasswordAuthentication: true
ssh: {
publicKeys: [
{
path: ‘/home/${adminUsername}/.ssh/authorized_keys’
keyData: adminPasswordOrKey
}
]
}
}

Then we will define the resources.

4. Azure Bicep template — resources

We will now define the resources as follows:

resource storageAccountName ‘Microsoft.Storage/storageAccounts@2021-01-01’ = {
name: storageAccountName_var
location: location
sku: {
name: storageAccountType
}
kind: ‘StorageV2’
}resource publicIPAddressName ‘Microsoft.Network/publicIPAddresses@2020-05-01’ = {
name: publicIPAddressName_var
location: location
properties: {
publicIPAllocationMethod: publicIPAddressType
dnsSettings: {
domainNameLabel: dnsNameForPublicIP
}
}
}resource virtualNetworkName ‘Microsoft.Network/virtualNetworks@2020-05-01’ = {
name: virtualNetworkName_var
location: location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetPrefix
networkSecurityGroup: {
id: networkSecurityGroupName.id
}
}
}
]
}
}resource nicName ‘Microsoft.Network/networkInterfaces@2020-05-01’ = {
name: nicName_var
location: location
properties: {
ipConfigurations: [
{
name: ‘ipconfig1’
properties: {
privateIPAllocationMethod: ‘Dynamic’
publicIPAddress: {
id: publicIPAddressName.id
}
subnet: {
id: subnetRef
}
}
}
]
}
dependsOn: [
virtualNetworkName
]
}resource vmName ‘Microsoft.Compute/virtualMachines@2019-12-01’ = {
name: vmName_var
location: location
properties: {
hardwareProfile: {
vmSize: vmSize
}
osProfile: {
computerName: vmName_var
adminUsername: adminUsername
adminPassword: adminPasswordOrKey
linuxConfiguration: ((authenticationType == ‘password’) ? json(‘null’) : linuxConfiguration)
}
storageProfile: {
imageReference: {
publisher: imagePublisher
offer: imageOffer
sku: imageOffer
version: ‘latest’
}
osDisk: {
name: ‘${OSDiskName}_OSDisk’
caching: ‘ReadWrite’
createOption: ‘FromImage’
}
dataDisks: [
{
name: ‘${dataDiskName}_DataDisk1’
diskSizeGB: storageDiskSizeGB
createOption: ‘Empty’
lun: 0
}
]
}
networkProfile: {
networkInterfaces: [
{
id: nicName.id
}
]
}
}
dependsOn: [
storageAccountName
]
}resource networkSecurityGroupName ‘Microsoft.Network/networkSecurityGroups@2020-05-01’ = {
name: networkSecurityGroupName_var
location: location
properties: {
securityRules: [
{
name: ‘https_8443’
properties: {
description: ‘https’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘8443’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 100
direction: ‘Inbound’
}
}
{
name: ‘http_8080’
properties: {
description: ‘http plain text’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘8080’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 101
direction: ‘Inbound’
}
}
{
name: ‘ssh_port_122’
properties: {
description: ‘Allow admin SSH’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘122’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 102
direction: ‘Inbound’
}
}
{
name: ‘vpn_1194’
properties: {
description: ‘Allow VPN’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘1194’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 103
direction: ‘Inbound’
}
}
{
name: ‘snmp_161’
properties: {
description: ‘Allow SNMP’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘161’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 104
direction: ‘Inbound’
}
}
{
name: ‘https_443’
properties: {
description: ‘Allow HTTPS’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘443’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 105
direction: ‘Inbound’
}
}
{
name: ‘http_80’
properties: {
description: ‘Allow HTTP’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ’80’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 106
direction: ‘Inbound’
}
}
{
name: ‘ssh_22’
properties: {
description: ‘Allow Git SSH’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ’22’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 107
direction: ‘Inbound’
}
}
{
name: ‘git_9418’
properties: {
description: ‘Allow Git’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ‘9418’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 108
direction: ‘Inbound’
}
}
{
name: ‘smtp_25’
properties: {
description: ‘Allow SMTP’
protocol: ‘*’
sourcePortRange: ‘*’
destinationPortRange: ’25’
sourceAddressPrefix: ‘Internet’
destinationAddressPrefix: ‘*’
access: ‘Allow’
priority: 109
direction: ‘Inbound’
}
}
]
}
}

Lastly, we will pass on a parameters file.

5. Parameters file.

The parameters file will contain just a few parameters for the name of the resources, the disk size, and the SSH Key. Create this new file and save it as azuredeploy.parameters.json

{
“$schema”: “https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#“,
“contentVersion”: “1.0.0.0”,
“parameters”: {
“accountPrefix”: {
“value”: “azinsider”
},
“vmSize”: {
“value”: “Standard_E4s_v3”
},
“storageDiskSizeGB”: {
“value”: 512
},
“adminUsername”: {
“value”: “azureuser”
},
“adminPasswordOrKey”: {
“value”: “ssh-rsa AAAAB3NzaC1yc2…== github-enterprise”
}
}
}

Here’s the complete Bicep template:

https://medium.com/media/8a30a0551d7e29a03fc540df777ee99d/href

6. Azure Bicep deployment

As a best practice, I recommend you preview the deployment by using the flag -C. We will use the command below to enable the preview of the deployment:

New-AzResourceGroupDeployment -Name $deploymentName -ResourceGroupName azinsider-ge -TemplateFile .main.bicep -TemplateParameterFile .azuredeploy.parameters.json -c

Note that we are adding the flag -c at the end of the command; this will enable a What-IF validation. This way, you can preview the deployment operation before doing the actual deployment.

The image below shows the preview of the deployment:

Azure Bicep — Deployment Preview — GitHub Enterprise Server

Once all is properly configured, we will proceed with the deployment. The figure below shows the output from the deployment:

Azure Bicep — Deployment Output— GitHub Enterprise Server

You can also go to the Azure Portal and check all the resources created from this deployment, as shown below:

Azure Bicep Deployment — GitHub Enterprise Server

I hope this article helps you on your Bicep journey and how you can leverage Bicep to deploy GitHub Enterprise Server on Azure.

👉 Join the AzInsider email list here.

-Dave R.

đŸ’ȘDeploying GitHub Enterprise Server on Azure using Bicep was originally published in CodeX on Medium, where people are continuing the conversation by highlighting and responding to this story.

Leave a Reply

Your email address will not be published.

Follow Us