https://github.com/vmvarela/terraform-github-actions-runner-scale-set
This Terraform module simplifies the deployment of self-hosted GitHub Actions runners on any Kubernetes cluster. It uses the official Actions Runner Controller (ARC) to create and manage auto-scaling runner sets.
https://github.com/vmvarela/terraform-github-actions-runner-scale-set
actions-runner-controller terraform-module
Last synced: 8 days ago
JSON representation
This Terraform module simplifies the deployment of self-hosted GitHub Actions runners on any Kubernetes cluster. It uses the official Actions Runner Controller (ARC) to create and manage auto-scaling runner sets.
- Host: GitHub
- URL: https://github.com/vmvarela/terraform-github-actions-runner-scale-set
- Owner: vmvarela
- License: mit
- Created: 2025-10-29T00:09:36.000Z (8 months ago)
- Default Branch: master
- Last Pushed: 2025-12-08T21:28:58.000Z (6 months ago)
- Last Synced: 2026-03-02T01:38:58.350Z (4 months ago)
- Topics: actions-runner-controller, terraform-module
- Language: HCL
- Homepage: https://registry.terraform.io/modules/vmvarela/actions-runner-scale-set/github/latest
- Size: 30.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# GitHub Actions Runner Scale Set on Kubernetes
Terraform module that deploys self-hosted GitHub Actions runners on Kubernetes using the official [Actions Runner Controller (ARC)](https://github.com/actions/actions-runner-controller).
This module automates the deployment of:
- **ARC Controller**: Manages the lifecycle of runner scale sets
- **Runner Scale Sets**: Auto-scaling GitHub Actions runners
- **Runner Groups**: Organized runner access control (optional)
- **Authentication**: Support for both GitHub Apps and Personal Access Tokens
## Features
- ✅ Multiple scale sets with independent configurations
- ✅ Auto-scaling runners (min/max configuration)
- ✅ GitHub App or PAT authentication
- ✅ Private container registry support
- ✅ Runner group management with repository and workflow restrictions
- ✅ Flexible runner image configuration
- ✅ Container mode support (Docker-in-Docker or Kubernetes)
- ✅ Automatic namespace creation
## Usage
### Basic Example
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_token = var.github_token
}
```
### Complete Example with Multiple Scale Sets
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_token = var.github_token
controller = {
name = "arc-controller"
namespace = "arc-system"
create_namespace = true
version = "0.13.0"
}
scale_sets = {
"default-runners" = {
namespace = "arc-runners-default"
create_namespace = true
min_runners = 1
max_runners = 10
runner_image = "ghcr.io/actions/actions-runner:latest"
container_mode = "dind"
visibility = "all"
create_runner_group = true
}
"production-runners" = {
namespace = "arc-runners-prod"
create_namespace = true
min_runners = 2
max_runners = 20
runner_group = "production"
visibility = "selected"
repositories = ["repo1", "repo2"]
create_runner_group = true
}
"ci-runners" = {
namespace = "arc-runners-ci"
create_namespace = true
min_runners = 3
max_runners = 15
runner_group = "ci"
visibility = "selected"
workflows = [".github/workflows/ci.yml"]
create_runner_group = true
}
}
}
```
### GitHub App Authentication
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_app_id = 123456
github_app_installation_id = 789012
github_app_private_key = file("${path.module}/github-app-key.pem")
}
```
### Private Container Registry
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_token = var.github_token
private_registry = "registry.example.com"
private_registry_username = var.registry_username
private_registry_password = var.registry_password
scale_sets = {
"custom-image-runners" = {
runner_image = "registry.example.com/custom/runner:latest"
}
}
}
```
## Requirements
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.0 |
| [github](#requirement\_github) | ~> 6.0 |
| [helm](#requirement\_helm) | ~> 3.0 |
| [kubernetes](#requirement\_kubernetes) | ~> 2.0 |
## Providers
| Name | Version |
|------|---------|
| [github](#provider\_github) | ~> 6.0 |
| [helm](#provider\_helm) | ~> 3.0 |
| [kubernetes](#provider\_kubernetes) | ~> 2.0 |
## Resources
| Name | Type |
|------|------|
| [github_actions_runner_group.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_runner_group) | resource |
| [helm_release.controller](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [helm_release.scale_set](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [kubernetes_namespace.controller](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
| [kubernetes_namespace.scale_set](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
| [kubernetes_secret.github_creds](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [kubernetes_secret.private_registry_creds](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [github_repositories.all](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/repositories) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| [github\_org](#input\_github\_org) | GitHub organization name | `string` | n/a | yes |
| [controller](#input\_controller) | Controller configuration |
object({
name = optional(string, "arc")
namespace = optional(string, "arc-systems")
create_namespace = optional(bool, true)
version = optional(string, "0.13.0")
}) | {
"name": "arc",
"namespace": "arc-systems",
"create_namespace": true,
"version": "0.13.0"
} | no |
| [scale\_sets](#input\_scale\_sets) | Scale sets configuration (map) | map(object({
runner_group = optional(string, null)
create_runner_group = optional(bool, true)
namespace = optional(string, "arc-runners")
create_namespace = optional(bool, true)
version = optional(string, "0.13.0")
min_runners = optional(number, 1)
max_runners = optional(number, 5)
runner_image = optional(string, "ghcr.io/actions/actions-runner:latest")
pull_always = optional(bool, true)
container_mode = optional(string, "dind")
visibility = optional(string, "all")
workflows = optional(list(string), null)
repositories = optional(list(string), null)
})) | {
"arc-runner-set": {
"runner_group": null,
"create_runner_group": true,
"namespace": "arc-runners",
"create_namespace": true,
"version": "0.13.0",
"min_runners": 1,
"max_runners": 5,
"runner_image": "ghcr.io/actions/actions-runner:latest",
"pull_always": true,
"container_mode": "dind",
"visibility": "all",
"workflows": null,
"repositories": null
}
} | no |
| [github\_token](#input\_github\_token) | GitHub Token (use either token or GitHub App credentials) | `string` | `null` | no |
| [github\_app\_id](#input\_github\_app\_id) | GitHub App ID (use either token or GitHub App credentials) | `number` | `null` | no |
| [github\_app\_installation\_id](#input\_github\_app\_installation\_id) | GitHub App Installation ID | `number` | `null` | no |
| [github\_app\_private\_key](#input\_github\_app\_private\_key) | GitHub App private key (PEM format) | `string` | `null` | no |
| [github\_repositories](#input\_github\_repositories) | All repositories in the organization. If not provided, they will be fetched by the module | `any` | `null` | no |
| [private\_registry](#input\_private\_registry) | Private container registry URL | `string` | `null` | no |
| [private\_registry\_username](#input\_private\_registry\_username) | Private container registry username | `string` | `null` | no |
| [private\_registry\_password](#input\_private\_registry\_password) | Private container registry password | `string` | `null` | no |
## Outputs
| Name | Description |
|------|-------------|
| [controller](#output\_controller) | The Helm release name of the controller |
| [scale\_set](#output\_scale\_set) | List of scale set names created |
## Authentication Methods
This module supports two authentication methods with GitHub:
### Personal Access Token (PAT)
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_token = var.github_token # Classic PAT with admin:org scope
}
```
**Required Scopes:**
- `admin:org` (for runner group management)
- `repo` (if managing repository runners)
### GitHub App
```hcl
module "github_runners" {
source = "path/to/module"
github_org = "my-organization"
github_app_id = var.github_app_id
github_app_installation_id = var.github_app_installation_id
github_app_private_key = file("github-app-key.pem")
}
```
**Required Permissions:**
- Repository permissions: `Actions: Read & Write`, `Administration: Read & Write`
- Organization permissions: `Self-hosted runners: Read & Write`
## Scale Set Configuration
### Container Modes
- **`dind`** (Docker-in-Docker): Runs Docker daemon inside the runner container
- **`kubernetes`**: Uses Kubernetes-native container execution
- **`null`**: No container mode (bare runner)
### Visibility Options
- **`all`**: Runners available to all repositories in the organization
- **`selected`**: Runners limited to specific repositories
- **`private`**: Runners available only to private repositories
### Runner Groups
Runner groups organize runners and control access:
```hcl
scale_sets = {
"backend-runners" = {
runner_group = "backend-team"
create_runner_group = true
visibility = "selected"
repositories = ["api", "database", "worker"]
workflows = [".github/workflows/deploy.yml"]
}
}
```
## Testing
This module includes comprehensive Terraform native tests using mock providers:
```bash
terraform test
```
Tests cover:
- Controller creation
- Multiple scale sets
- GitHub App authentication
- Private registry configuration
- Runner groups
- Variable validations
- Container modes
- Resource dependencies
## License
MIT License - see [LICENSE](LICENSE) for details.
## Contributing
Contributions are welcome! Please open an issue or submit a pull request.
## Authors
Created and maintained by [Your Name/Organization]