Well-Architected Framework
Manage VCS configuration as code
Manually configuring version control systems creates inconsistent repository settings, security gaps, and configuration drift. Managing VCS configuration as code with Terraform standardizes repository settings, enforces security policies, and automates team and permission management across your organization.
Version control systems (VCS) like GitHub, GitLab, and Bitbucket store and version your infrastructure code, application code, and configuration files. While teams use VCS to manage infrastructure as code, the VCS platforms themselves require configuration including repository settings, branch protections, team permissions, and security controls. Terraform manages both on-premises VCS installations and cloud-based VCS platforms.
Why manage VCS configuration as code
Managing VCS configuration as code addresses critical operational and security challenges:
Enforce security policies: Apply branch protection rules, approval requirements, and access controls consistently across all repositories from creation.
Prevent configuration drift: Set identical baseline configurations across repositories with variations defined in code rather than through manual changes.
Automate access management: Remove manual management of team membership and repository permissions. Define and review access for your entire organization in code.
Meet audit and compliance requirements: Create comprehensive audit trails through version control history, pull request reviews, and approval workflows instead of limited web interface logs.
Manage GitHub configuration
The following example shows Terraform managing GitHub repository configuration, including branch protection rules and team permissions. Before running this configuration, create a GitHub personal access token or GitHub App with appropriate permissions for repository and team management.
github.tf
terraform {
required_providers {
github = {
source = "integrations/github"
version = "~> 6.1"
}
}
}
provider "github" {
owner = "your-organization"
}
# Create repository with standard configuration
resource "github_repository" "infrastructure" {
name = "infrastructure-production"
description = "Production infrastructure as code"
visibility = "private"
auto_init = true
}
# Enforce branch protection on main branch
resource "github_branch_protection" "main" {
repository_id = github_repository.infrastructure.node_id
pattern = "main"
# Require pull request reviews
required_pull_request_reviews {
required_approving_review_count = 2
}
# Prevent force pushes and deletions
allows_force_pushes = false
allows_deletions = false
}
# Create team with repository access
resource "github_team" "platform" {
name = "platform-engineering"
description = "Platform engineering team"
privacy = "closed"
}
# Assign team permissions to repository
resource "github_team_repository" "platform_infra" {
team_id = github_team.platform.id
repository = github_repository.infrastructure.name
permission = "maintain"
}
This configuration creates a repository with security best practices enabled, enforces branch protection requiring two approvals before merging, and assigns team permissions. To learn more about each of the resources used in this example, refer to the GitHub provider documentation.
Manage GitLab configuration
The following example shows Terraform managing GitLab project configuration with merge request approvals and protected branches:
gitlab.tf
terraform {
required_providers {
gitlab = {
source = "gitlabhq/gitlab"
version = "~> 18.8"
}
}
}
# Create GitLab group for organization
resource "gitlab_group" "platform" {
name = "platform-engineering"
path = "platform"
description = "Platform engineering infrastructure"
visibility_level = "private"
}
# Create project with standard settings
resource "gitlab_project" "infrastructure" {
name = "infrastructure-production"
namespace_id = gitlab_group.platform.id
description = "Production infrastructure as code"
visibility_level = "private"
# Require successful pipeline before merging
only_allow_merge_if_pipeline_succeeds = true
}
# Protect main branch
resource "gitlab_branch_protection" "main" {
project = gitlab_project.infrastructure.id
branch = "main"
push_access_level = "no one"
merge_access_level = "maintainer"
}
# Require approvals for merge requests
resource "gitlab_project_approval_rule" "security" {
project = gitlab_project.infrastructure.id
name = "Security review required"
approvals_required = 2
group_ids = [gitlab_group.platform.id]
}
This configuration creates a GitLab project that requires pipeline success before merging, protects the main branch from direct pushes, and enforces approval requirements through code. To learn more about each of the resources used in this example, refer to the GitLab provider documentation.
Secure VCS credentials with Vault
Store VCS access tokens and credentials in Vault instead of environment variables or configuration files. Vault provides centralized secret management, automatic credential rotation, and comprehensive audit logging for all credential access.
The following example shows how to retrieve VCS credentials from Vault in your Terraform configuration:
vault-vcs.tf
terraform {
required_providers {
vault = {
source = "hashicorp/vault"
version = "~> 4.0"
}
github = {
source = "integrations/github"
version = "~> 6.1"
}
}
}
# Retrieve GitHub token from Vault
data "vault_kv_secret_v2" "github_token" {
mount = "secret"
name = "github/terraform"
}
# Configure GitHub provider with Vault-sourced token
provider "github" {
owner = "your-organization"
token = data.vault_kv_secret_v2.github_token.data["token"]
}
# Create repository with credentials from Vault
resource "github_repository" "infrastructure" {
name = "infrastructure-production"
description = "Production infrastructure as code"
visibility = "private"
}
The configuration retrieves the GitHub token from Vault's secret store, removing the need to store credentials in Terraform variables or environment variables. Before using this pattern, store your VCS access token in Vault using the Vault CLI or API. Vault's audit logs track all credential access, providing visibility into who accessed VCS credentials and when. When you rotate VCS tokens in Vault, all Terraform runs automatically use the updated credentials without modifying Terraform configurations.
HashiCorp resources
- Learn to define infrastructure as code to manage VCS platforms consistently
- Store code in version control for infrastructure and application code
- Learn to manage GitHub users, teams, and repository permissions with Terraform
Terraform and VCS integration:
- Get started with Terraform tutorials and read the Terraform documentation
- Learn about Terraform providers for VCS platforms
GitHub provider documentation:
- Read the GitHub provider documentation for resource types and authentication methods
- Configure repository resources for visibility, security, and feature settings
- Set up branch protection for required reviews and status checks
- Manage teams and team repository permissions for access control
GitLab provider documentation:
- Read the GitLab provider documentation for resource types and authentication methods
- Configure projects and groups for organizational structure
- Set up branch protection for push and merge restrictions
- Configure approval rules for required reviewers and approvals
Vault for credential management:
- Get started with Vault tutorials and read the Vault documentation
- Learn about Vault secrets engines for managing VCS credentials
- Read the Vault Terraform provider documentation for integration examples
- Explore dynamic secrets for automated credential rotation
Next steps
In this section of Codify infrastructure and tools, you learned how to define version control systems using infrastructure as code to enable version control and audit capabilities for VCS changes. Define version control systems is part of the Define and automate processes pillar.
After managing VCS configuration as code, apply these practices:
- Use Terraform modules to create reusable repository templates with standard security settings.
- Implement policy as code to validate VCS configurations before applying changes.