Integrate Azure DevOps Pipelines with Private GitHub Repos

In cloud-native engineering, securely connecting Azure DevOps pipelines to private GitHub repositories is essential — especially when working with Terraform modules that define your infrastructure. This guide walks through how to establish that connection using PowerShell Core, ensuring a secure and maintainable setup.

🛠️ Prerequisites

Before you begin, make sure you have:

  • An Azure DevOps organisation and project.
  • A GitHub account with access to the private repository.
  • SSH key pair (public and private).
  • The public key added to GitHub.
  • The private key stored as a secure file in Azure DevOps.
  • A pipeline agent with PowerShell Core available.

🔑 Why Use SSH Over PAT?

While GitHub Personal Access Tokens (PATs) are easy to set up, SSH keys offer better security and automation. SSH keys can be rotated, scoped, and stored securely in Azure DevOps without exposing them in logs or scripts.

📄 PowerShell Core Script to Install SSH Key

Below is the PowerShell script to be run on the Azure DevOps Agent, which will setup the Private SSH Key on the agent.

param (
    [Parameter(Mandatory = $true)]
    [string]$sshPrivateKey,

    [string]$knownHostsEntry = "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA..."
)

$sshFolder = "$HOME/.ssh"

# Step 1: Create the .ssh directory if it doesn't exist
if (-not (Test-Path -Path $sshFolder)) {
    New-Item -ItemType Directory -Path $sshFolder -Force | Out-Null
}

# Step 2: Write the private key to id_rsa
$privateKeyPath = Join-Path $sshFolder "id_rsa"
$sshPrivateKey | Out-File -FilePath $privateKeyPath -Encoding ascii -Force

# Step 3: Set file permissions (Linux-style)
chmod 600 $privateKeyPath

# Step 4: Add GitHub to known_hosts
$knownHostsPath = Join-Path $sshFolder "known_hosts"
Add-Content -Path $knownHostsPath -Value $knownHostsEntry

Write-Host "SSH key installed successfully."




🔍 Breakdown of the Script

> param (...)

Defines input parameters for the script:

  • $sshPrivateKey: The private key content passed securely from Azure DevOps.
  • $knownHostsEntry: GitHub’s SSH fingerprint to prevent MITM attacks.

> $sshFolder = "$HOME/.ssh"

Sets the path to the SSH configuration directory.

> Out-File

Writes the private key to id_rsa using ASCII encoding.

> chmod 600

Sets strict permissions so only the owner can read/write the key.

> Add-Content

Appends GitHub’s fingerprint to known_hosts to avoid interactive prompts during SSH connections.

📦 Calling the Terraform Module

Once the SSH key is installed, you can reference the private module directly in your Terraform configuration like this:

module "networking" {
  source = "git@github.com:your-org/terraform-modules.git//networking?ref=v1.0.0"
}




This tells Terraform to:

  • Use SSH to access the GitHub repo.
  • Load the networking module from the specified path.
  • Use the tagged version v1.0.0.

Make sure your pipeline includes terraform init and terraform plan steps after the SSH setup.

🛡️ Security Best Practices

  • Use Secure Files: Store sensitive keys in Azure DevOps secure files or secret variables.
  • Rotate Keys: Periodically regenerate SSH keys and update them in GitHub and Azure DevOps.
  • Restrict Access: Limit who can view or modify pipeline secrets.
  • Audit Logs: Monitor pipeline runs for unauthorized access or changes.

⚠️ Common Issues & Troubleshooting Tips

  • Permission denied (publickey): Ensure the public key is correctly added to GitHub and the private key is installed with proper permissions (chmod 600).
  • Host key verification failed: Add GitHub’s SSH fingerprint to known_hosts.
  • Terraform module not found: Double-check the source path and ref tag in your module block.

🧩 Conclusion

Using SSH for authenticating Azure DevOps pipelines with GitHub is a secure and salable approach. Unlike PATs, SSH keys are not tied to a user’s identity and can be scoped to specific repositories or environments. They’re easier to rotate, harder to misuse, and more resilient to accidental exposure.

By implementing SSH authentication with PowerShell Core, you gain full control over how credentials are handled, reduce reliance on built-in tasks, and align with best practices for DevSecOps and infrastructure automation.

Published by Chris Pateman - PR Coder

A Digital Technical Lead, constantly learning and sharing the knowledge journey.

Leave a message please

This site uses Akismet to reduce spam. Learn how your comment data is processed.