Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/fireactions/printables.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type printablePool struct {
}

func (p *printablePool) Cols() []string {
return []string{"Name", "Current", "Desired", "Organization", "Group ID", "Labels", "Image", "State"}
return []string{"Name", "Current", "Desired", "Organization", "Repository", "Group ID", "Labels", "Image", "State"}
}

func (p *printablePool) ColsMap() map[string]string {
Expand All @@ -23,6 +23,7 @@ func (p *printablePool) ColsMap() map[string]string {
"Current": "Current",
"Desired": "Desired",
"Organization": "Organization",
"Repository": "Repository",
"Group ID": "Group ID",
"Labels": "Labels",
"Image": "Image",
Expand All @@ -42,6 +43,7 @@ func (p *printablePool) KV() []map[string]interface{} {
"Current": pool.CurrentReplicas,
"Desired": pool.DesiredReplicas,
"Organization": pool.Organization,
"Repository": pool.Repository,
"Group ID": pool.GroupId,
"Labels": strings.Join(pool.Labels, ", "),
"Image": pool.Image,
Expand Down
17 changes: 17 additions & 0 deletions docs/help/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,20 @@ gh api --paginate /orgs/$ORG/actions/runners | jq '.runners[] | select(.status==
```

Please replace `<ORG>` with the name of your GitHub Account or Organization.

For repository scoped pools (including pools of personal accounts), the runners live on the repository instead, so use
the repository endpoint. With bash:

```bash
export GH_PAGER=
export REPO="<OWNER>/<REPOSITORY>"
gh api --paginate /repos/$REPO/actions/runners | jq '.runners[] | select(.status=="offline") | .id' | xargs -I {} gh api --method DELETE /repos/$REPO/actions/runners/{}
Comment thread
kholisrag marked this conversation as resolved.
```

With fish shell:

```fish
set -x GH_PAGER
set -x REPO <OWNER>/<REPOSITORY>
gh api --paginate /repos/$REPO/actions/runners | jq '.runners[] | select(.status=="offline") | .id' | xargs -I {} gh api --method DELETE /repos/$REPO/actions/runners/{}
Comment thread
kholisrag marked this conversation as resolved.
```
29 changes: 25 additions & 4 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ metrics:
address: 127.0.0.1:8081

#
# GitHub configuration.
# GitHub configuration. See the GitHub App guide for the permissions the App
# needs: ../user-guide/github-app.md
#
github:
#
Expand Down Expand Up @@ -89,15 +90,35 @@ pools:
#
# GitHub runner group ID. 1 is the default group.
#
# Required: true
# Required: true when `organization` is set. Runner groups don't exist for
# personal accounts, so this is optional (and defaults to 1) when
# `repository` is set.
group_id: 1
#
# Organization name.
# Organization name. Runners are registered with the organization and are
# available to all of its repositories.
#
# Required: true
# Exactly one of `organization` or `repository` is required.
#
organization: hostinger
#
# Repository, in <owner>/<repository> format. Runners are registered with
# this single repository. This is the only option for personal (user)
# accounts, which can't have organization runners.
#
# Exactly one of `organization` or `repository` is required.
#
# repository: octocat/hello-world
#
# GitHub App installation ID. By default Fireactions looks the installation
# up from the configured organization or repository, which requires no
# extra configuration. Set this to skip the lookup, e.g. when the App can't
# read the installation itself.
#
# Required: false, Default: 0 (look up automatically)
#
# installation_id: 12345678
#
# Labels to apply to the GitHub runner.
#
# Required: true
Expand Down
37 changes: 37 additions & 0 deletions docs/user-guide/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,40 @@ pools:
```

This will create a pool named `example` with 5 replicas for the GitHub runners. The runners will have the labels `self-hosted` and `fireactions`, and will use the specified Firecracker configuration.

## Runner scope

A pool registers its runners either with an organization or with a single repository. Exactly one of `runner.organization` or `runner.repository` must be set.

### Organization scoped

```yaml
runner:
organization: hostinger
group_id: 1
```

Runners are registered with the organization and can be used by any of its repositories, subject to the runner group's repository access settings. `group_id` is required, `1` is the default runner group.

### Repository scoped

```yaml
runner:
repository: octocat/hello-world
```

Runners are registered with a single repository. This is the only option for repositories owned by a personal (user) account, since GitHub doesn't offer organization runners or runner groups outside of organizations. `group_id` is optional and defaults to `1`.

Repository scoped pools work for organization owned repositories too, which is useful when you want a pool dedicated to one repository.

### GitHub App permissions

The two scopes use different GitHub APIs and therefore need different GitHub App permissions:

| Runner scope | Permission |
|--------------------|-----------------------------------------------------|
| Organization | Organization `Self-hosted runners`: Read and write |
| Repository | Repository `Administration`: Read and write |

See the [GitHub App](github-app.md) guide for how to create and install the App, and for the `runner.installation_id`
option.
4 changes: 2 additions & 2 deletions docs/user-guide/first-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ After installing and configuring Fireactions, verify your setup by running a tes

## Verify Runners Are Registered

Check your GitHub organization's Actions settings to confirm runners are registered:
Check your GitHub Actions settings to confirm runners are registered:

1. Navigate to your GitHub organization settings
1. Navigate to your GitHub organization settings, or, for repository scoped pools, to your repository settings
2. Go to **Actions** → **Runners**
3. Verify that runners are listed as **Idle** and ready to receive jobs

Expand Down
128 changes: 128 additions & 0 deletions docs/user-guide/github-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# GitHub App

Fireactions authenticates with GitHub as a [GitHub App](https://docs.github.com/en/apps/creating-github-apps). The App is
the only credential Fireactions needs: it creates just-in-time (JIT) runner registrations before starting a Firecracker
VM, and deletes the runner from GitHub after the VM exits.

The App is configured in the `github` section of the configuration file:

```yaml
github:
app_id: 12345
app_private_key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
```

Which permissions the App needs depends on the [runner scope](concepts.md#runner-scope) of your pools.

## Permissions

### Organization scoped pools

For pools that set `runner.organization`, grant the following **organization permission**:

| Permission | Access |
|---------------------|------------------|
| Self-hosted runners | Read and write |

This is the permission that covers `POST /orgs/{org}/actions/runners/generate-jitconfig` and
`DELETE /orgs/{org}/actions/runners/{runner_id}`. The organization `Administration` permission does **not** grant access
to these endpoints, so granting it instead won't work.

No repository permissions are needed: runners are registered with the organization itself, not with any of its
repositories.

### Repository scoped pools

For pools that set `runner.repository`, grant the following **repository permissions**:

| Permission | Access |
|----------------|-----------------------------------|
| Administration | Read and write |
| Metadata | Read-only (granted automatically) |

`Administration` covers `POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig` and
`DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}`. GitHub grants `Metadata: Read-only` automatically as soon as
any repository permission is selected.

Repository scoped pools are the only option for personal (user) accounts, which can't have organization runners. They
work for organization owned repositories too.

!!! note
A single App can serve both kinds of pools. Grant the organization `Self-hosted runners` permission and the
repository `Administration` permission if you run organization scoped and repository scoped pools side by side.

### Not required

Fireactions does not need any of the following, and you can leave them unset:

- **Webhooks and webhook events.** Fireactions keeps each pool at its configured number of replicas on its own and does
not consume `workflow_job` or any other event, so the App needs no webhook URL and no event subscriptions.
- **The `Actions` permission.** Fireactions never reads or writes workflow runs, jobs or artifacts.
- **Account (user) permissions.**

## Creating and installing the App

The App can be owned by an organization or by a personal account. Ownership only decides who administers the App; what
matters for Fireactions is the account the App is *installed* on.

1. Create the App:
- **Organization owned:** `https://github.com/organizations/<ORG>/settings/apps/new`
- **Personal account owned:** `https://github.com/settings/apps/new`
2. Set a name and a homepage URL. Uncheck **Active** under **Webhook** — Fireactions doesn't use webhooks.
3. Under **Permissions**, grant the permissions for your runner scope from the tables above.
4. Create the App, then note the **App ID** and generate a **private key**. The downloaded `.pem` file is what goes into
`github.app_private_key`.
5. Install the App:
- **On an organization** (for organization scoped pools): **Install App** → choose the organization.
- **On a personal account** (for repository scoped pools): **Install App** → choose your account, then
**Only select repositories** and pick the repositories your pools register runners with.

!!! warning
Changing an App's permissions after installation requires accepting the new permissions on the installation before
they take effect. If Fireactions starts failing with `403` errors after a permission change, check the installation
settings page for a pending request.

## Installation ID

Fireactions needs the ID of the App installation on the account owning the runners. It looks the ID up automatically
using the App's own JWT — `GET /orgs/{org}/installation` for organization scoped pools and
`GET /repos/{owner}/{repo}/installation` for repository scoped pools. Neither call needs an installation permission, so
in most setups nothing else is required.

Set `runner.installation_id` to skip the lookup:

```yaml
runner:
repository: octocat/hello-world
installation_id: 12345678
```

You can find the ID in the URL of the installation's settings page:

- Organization: **Settings** → **GitHub Apps** → **Configure**, the URL ends in
`/organizations/<ORG>/settings/installations/<INSTALLATION_ID>`
- Personal account: **Settings** → **Applications** → **Configure**, the URL ends in
`/settings/installations/<INSTALLATION_ID>`

Or via the API, authenticating with the App's JWT:

```bash
gh api /repos/<OWNER>/<REPOSITORY>/installation --jq .id
```
Comment thread
kholisrag marked this conversation as resolved.
Outdated

## API calls Fireactions makes

| Endpoint | Authenticated as | Permission |
|-------------------------------------------------------------|------------------|-------------------------------------------|
| `GET /orgs/{org}/installation` | App (JWT) | None |
| `GET /repos/{owner}/{repo}/installation` | App (JWT) | None |
| `POST /orgs/{org}/actions/runners/generate-jitconfig` | Installation | Organization `Self-hosted runners: write` |
| `DELETE /orgs/{org}/actions/runners/{runner_id}` | Installation | Organization `Self-hosted runners: write` |
| `POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig` | Installation | Repository `Administration: write` |
| `DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}` | Installation | Repository `Administration: write` |

The organization endpoints are only used by pools with `runner.organization` set, the repository endpoints only by pools
with `runner.repository` set.
10 changes: 7 additions & 3 deletions docs/user-guide/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ Before you begin, ensure you have:
- **KVM virtualization support** - Firecracker requires hardware virtualization
- **GitHub App credentials**:
- App ID
- App must be installed on your target organization
- Private key (PEM format)
- See [Creating GitHub Apps](https://docs.github.com/en/apps/creating-github-apps) for setup instructions
- App must be installed on your target organization or personal account
- App needs the organization `Self-hosted runners: Read and write` permission for organization scoped pools, or the repository `Administration: Read and write` permission for repository scoped pools
- See the [GitHub App](github-app.md) guide for setup instructions
- **Dedicated block device** for Containerd storage (e.g., `/dev/nvme1n1`, `/dev/sdb`)
- This will be used exclusively for container image storage via LVM
- Minimum 50GB recommended, though this depends on your image sizes
Expand Down Expand Up @@ -412,7 +413,10 @@ pools:
image: ghcr.io/hostinger/fireactions-images/ubuntu22.04:latest
image_pull_policy: IfNotPresent # or Always to pull on every run
group_id: 1 # Runner group ID in GitHub (1 = default)
organization: YOUR_GITHUB_ORGANIZATION # or use 'repository: owner/repo'
# Register runners with an organization...
organization: YOUR_GITHUB_ORGANIZATION
# ...or with a single repository, the only option for personal accounts:
# repository: YOUR_GITHUB_USERNAME/YOUR_REPOSITORY
Comment thread
kholisrag marked this conversation as resolved.
Outdated
labels:
- self-hosted
- fireactions
Expand Down
2 changes: 2 additions & 0 deletions docs/user-guide/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The following metrics are available, excluding the default Prometheus metrics:
| `fireactions_scale_duration_seconds` | Histogram | Time taken to complete a scale operation | `pool`, `organization`, `direction` |


The `organization` label holds the GitHub account that owns the pool's runners: the organization name for organization scoped pools, or the repository owner (which may be a personal account) for repository scoped pools.

Example Grafana dashboard for vizualisation of Fireactions metrics:

![Grafana Dashboard](../img/grafana-dashboard.png)
4 changes: 2 additions & 2 deletions docs/user-guide/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Fireactions is still in the early stages of development, we are waiting for feed
There are a few requirements to run Fireactions:

- Linux machine with KVM support. We recommend using a machine with at least 2 CPU cores and 4GB of RAM.
- GitHub organisation account (currently only organisation accounts are supported)
- GitHub App with permissions to manage self-hosted runners. See the [installation guide](installation.md) for setup details.
- GitHub organisation or personal account. Organisation accounts can register runners with the organisation or with a single repository, personal accounts with a single repository. See [runner scope](concepts.md#runner-scope).
- GitHub App with permissions to manage self-hosted runners, installed on your organization or personal account. See the [GitHub App guide](github-app.md) for the required permissions and setup details.
- [Containerd v1.7.0 or newer](https://github.com/containerd/containerd)
- [Firecracker v1.4.1 or newer](https://github.com/firecracker-microvm/firecracker)
- [CNI Plugins v1.6.0 or newer](https://github.com/containernetworking/plugins) (with `firewall` and `bridge` plugins)
Expand Down
Loading
Loading