mirror of
https://gitea.com/gitea/docs.git
synced 2026-11-04 09:15:33 +00:00
Simplify the runner docs and fix their outdated facts (#600)
The runner pages had drifted from the runner. They claimed Podman is unsupported, a registration retry limit of 10, a `container.env` proxy override that has no effect, and they used the deprecated `generate-config` command, while the actual instructions were buried under implementation details. The develop and 5.x pages are rewritten from the current runner sources (`main` is `v5.2.0`). They are shorter and aimed at operators, with a new page covering what jobs get. The reference generator now documents the `config` command, and the quickstart pages in every language use the `gitea-runner` binary name. Reviewed-on: https://gitea.com/gitea/docs/pulls/600 Reviewed-by: Lunny Xiao <[email protected]> Co-authored-by: silverwind <[email protected]>
This commit is contained in:
@@ -38,7 +38,7 @@ Use "gitea-runner [command] --help" for more information about a command.
|
||||
|
||||
## register
|
||||
|
||||
Registers the runner against a Gitea instance and writes the registration file. Interactive unless `--no-interactive` is given; the token can also come from `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable. See [Registering a runner](../registration.md).
|
||||
Registers the runner with a Gitea instance and writes the registration file. The token comes from `--token`, `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable, and the command asks for the other settings unless `--no-interactive` is given. See [Registration](../registration.md).
|
||||
|
||||
```text
|
||||
Register a runner to the server
|
||||
@@ -132,7 +132,7 @@ Global Flags:
|
||||
|
||||
## cache-server
|
||||
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys; every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys. Every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
|
||||
```text
|
||||
Start a cache server for the cache action
|
||||
|
||||
@@ -7,10 +7,8 @@ description: The commented example configuration of the runner, generated from t
|
||||
|
||||
{/* Generated by update_runner_docs.sh from the gitea/runner sources, do not edit. */}
|
||||
|
||||
This is the output of `gitea-runner generate-config`. It is safe to use unmodified,
|
||||
and it is the authoritative list of every option the runner understands. See
|
||||
[Configuration](../configuration.md) for what the options mean and how the file is
|
||||
loaded.
|
||||
Every option the runner understands, with its default, as printed by `gitea-runner generate-config`.
|
||||
See [Configuration](../configuration.md) for how to write and load a config file.
|
||||
|
||||
```yaml
|
||||
# Example configuration file, it's safe to copy this as the default config file without any modification.
|
||||
|
||||
@@ -38,7 +38,7 @@ Use "gitea-runner [command] --help" for more information about a command.
|
||||
|
||||
## register
|
||||
|
||||
Registers the runner against a Gitea instance and writes the registration file. Interactive unless `--no-interactive` is given; the token can also come from `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable. See [Registering a runner](../registration.md).
|
||||
Registers the runner with a Gitea instance and writes the registration file. The token comes from `--token`, `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable, and the command asks for the other settings unless `--no-interactive` is given. See [Registration](../registration.md).
|
||||
|
||||
```text
|
||||
Register a runner to the server
|
||||
@@ -135,7 +135,7 @@ Global Flags:
|
||||
|
||||
## cache-server
|
||||
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys; every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys. Every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
|
||||
```text
|
||||
Start a cache server for the cache action
|
||||
@@ -153,18 +153,121 @@ Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
## generate-config
|
||||
## config
|
||||
|
||||
Prints the commented example configuration on stdout, which is the starting point for a config file: `gitea-runner generate-config > config.yaml`.
|
||||
Writes, reads and edits config files. `config init` writes a minimal `config.yaml`, `config set`, `add` and `remove` change it in place, and `config generate` prints every option. See [Configuration](../configuration.md).
|
||||
|
||||
```text
|
||||
Generate, read and edit config files
|
||||
|
||||
Usage:
|
||||
gitea-runner config [flags]
|
||||
gitea-runner config [command]
|
||||
|
||||
Available Commands:
|
||||
add Append values to a list config key
|
||||
generate Print the example config, which documents every option
|
||||
get Print the value of a config key
|
||||
init Write a minimal config file
|
||||
remove Remove values from a list config key
|
||||
set Set the value of a config key
|
||||
|
||||
Flags:
|
||||
-h, --help help for config
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
Use "gitea-runner config [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
### config add
|
||||
|
||||
```text
|
||||
Append values to a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config add <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for add
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config generate
|
||||
|
||||
```text
|
||||
Print the example config, which documents every option
|
||||
|
||||
Usage:
|
||||
gitea-runner generate-config [flags]
|
||||
gitea-runner config generate [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for generate-config
|
||||
-h, --help help for generate
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config get
|
||||
|
||||
```text
|
||||
Print the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config get <key> [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for get
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config init
|
||||
|
||||
```text
|
||||
Write a minimal config file, leaving every option at its default.
|
||||
Without --config it writes config.yaml in the working directory.
|
||||
|
||||
Usage:
|
||||
gitea-runner config init [flags]
|
||||
|
||||
Flags:
|
||||
-f, --force overwrite an existing config file
|
||||
-h, --help help for init
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config remove
|
||||
|
||||
```text
|
||||
Remove values from a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config remove <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for remove
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config set
|
||||
|
||||
```text
|
||||
Set the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config set <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for set
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
@@ -7,10 +7,8 @@ description: The commented example configuration of the runner, generated from t
|
||||
|
||||
{/* Generated by update_runner_docs.sh from the gitea/runner sources, do not edit. */}
|
||||
|
||||
This is the output of `gitea-runner generate-config`. It is safe to use unmodified,
|
||||
and it is the authoritative list of every option the runner understands. See
|
||||
[Configuration](../configuration.md) for what the options mean and how the file is
|
||||
loaded.
|
||||
Every option the runner understands, with its default, as printed by `gitea-runner config generate`.
|
||||
See [Configuration](../configuration.md) for how to write and load a config file.
|
||||
|
||||
```yaml
|
||||
# Every option with its default value, all commented out. Read this file, do not copy it.
|
||||
|
||||
@@ -38,7 +38,7 @@ Use "gitea-runner [command] --help" for more information about a command.
|
||||
|
||||
## register
|
||||
|
||||
Registers the runner against a Gitea instance and writes the registration file. Interactive unless `--no-interactive` is given; the token can also come from `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable. See [Registering a runner](../registration.md).
|
||||
Registers the runner with a Gitea instance and writes the registration file. The token comes from `--token`, `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable, and the command asks for the other settings unless `--no-interactive` is given. See [Registration](../registration.md).
|
||||
|
||||
```text
|
||||
Register a runner to the server
|
||||
@@ -135,7 +135,7 @@ Global Flags:
|
||||
|
||||
## cache-server
|
||||
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys; every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys. Every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
|
||||
```text
|
||||
Start a cache server for the cache action
|
||||
@@ -153,18 +153,137 @@ Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
## generate-config
|
||||
## config
|
||||
|
||||
Prints the commented example configuration on stdout, which is the starting point for a config file: `gitea-runner generate-config > config.yaml`.
|
||||
Writes, reads and edits config files. `config init` writes a minimal `config.yaml`, `config set`, `add` and `remove` change it in place, and `config generate` prints every option. See [Configuration](../configuration.md).
|
||||
|
||||
```text
|
||||
Generate, read and edit config files
|
||||
|
||||
Usage:
|
||||
gitea-runner config [flags]
|
||||
gitea-runner config [command]
|
||||
|
||||
Available Commands:
|
||||
add Append values to a list config key
|
||||
generate Print the example config, which documents every option
|
||||
get Print the value of a config key
|
||||
init Write a minimal config file
|
||||
remove Remove values from a list config key
|
||||
runner-file Print the registration file path used by the runner
|
||||
set Set the value of a config key
|
||||
|
||||
Flags:
|
||||
-h, --help help for config
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
Use "gitea-runner config [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
### config add
|
||||
|
||||
```text
|
||||
Append values to a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config add <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for add
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config generate
|
||||
|
||||
```text
|
||||
Print the example config, which documents every option
|
||||
|
||||
Usage:
|
||||
gitea-runner generate-config [flags]
|
||||
gitea-runner config generate [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for generate-config
|
||||
-h, --help help for generate
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config get
|
||||
|
||||
```text
|
||||
Print the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config get <key> [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for get
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config init
|
||||
|
||||
```text
|
||||
Write a minimal config file, leaving every option at its default.
|
||||
Without --config it writes config.yaml in the working directory.
|
||||
|
||||
Usage:
|
||||
gitea-runner config init [flags]
|
||||
|
||||
Flags:
|
||||
-f, --force overwrite an existing config file
|
||||
-h, --help help for init
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config remove
|
||||
|
||||
```text
|
||||
Remove values from a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config remove <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for remove
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config runner-file
|
||||
|
||||
```text
|
||||
Print the registration file path used by the runner
|
||||
|
||||
Usage:
|
||||
gitea-runner config runner-file [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for runner-file
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config set
|
||||
|
||||
```text
|
||||
Set the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config set <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for set
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
@@ -7,10 +7,8 @@ description: The commented example configuration of the runner, generated from t
|
||||
|
||||
{/* Generated by update_runner_docs.sh from the gitea/runner sources, do not edit. */}
|
||||
|
||||
This is the output of `gitea-runner generate-config`. It is safe to use unmodified,
|
||||
and it is the authoritative list of every option the runner understands. See
|
||||
[Configuration](../configuration.md) for what the options mean and how the file is
|
||||
loaded.
|
||||
Every option the runner understands, with its default, as printed by `gitea-runner config generate`.
|
||||
See [Configuration](../configuration.md) for how to write and load a config file.
|
||||
|
||||
```yaml
|
||||
# Every option with its default value, all commented out. Read this file, do not copy it.
|
||||
|
||||
@@ -1,107 +1,78 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Caching
|
||||
|
||||
Every runner starts its own cache server, so `actions/cache` works without any configuration. Cache entries are local to that runner: two runners do not share a cache unless you make them.
|
||||
|
||||
## Cache service v2
|
||||
|
||||
`actions/[email protected]` and later can use the *cache service v2* API. The runner serves it from the same store as v1, on by default, and it also works behind a shared cache server. Turn it off with:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
v2: false
|
||||
```
|
||||
|
||||
Those actions refuse any host they do not take for GitHub. Rather than misreport the server URL, the runner edits that check out of the action's own JavaScript bundle and keeps the untouched copy beside it; a bundle it does not recognise is left alone and keeps to v1. The same edit lets the stock `actions/upload-artifact` and `actions/download-artifact` work from `v4.4.0` on, without the `gitea-upload-artifact` fork.
|
||||
|
||||
Because `ACTIONS_RESULTS_URL` names one origin that has to serve the whole results API, the cache server also forwards the artifact half of it to the Gitea instance the job belongs to. Jobs are therefore pointed at the cache server, which is what makes clients such as `docker buildx` find the cache service instead of receiving a 404 from Gitea.
|
||||
|
||||
## Where cache blobs are stored
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
enabled: true
|
||||
dir: /var/lib/gitea-runner/cache # default: $HOME/.cache/actcache
|
||||
```
|
||||
|
||||
The directory grows with use; entries are evicted as they expire, so give it a filesystem with room to spare and monitor it like any other build cache.
|
||||
|
||||
## Dockerized runners
|
||||
|
||||
When the runner itself runs in a container and creates a network per job, the address it detects for its own cache server is often unreachable from the job containers. `actions/cache` then fails with:
|
||||
|
||||
```text
|
||||
Failed to restore: getCacheEntry failed: connect ETIMEDOUT IP:PORT
|
||||
```
|
||||
|
||||
Pin the address and the port the job containers should use, and make that endpoint reachable:
|
||||
|
||||
1. take an address of the host that job containers can reach, and a free port on it;
|
||||
2. configure them:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
enabled: true
|
||||
dir: ""
|
||||
host: "192.168.8.17"
|
||||
port: 8088
|
||||
```
|
||||
|
||||
3. publish the port when starting the runner container:
|
||||
|
||||
```bash
|
||||
docker run -d --name gitea-runner -p 8088:8088 ... docker.io/gitea/runner:5
|
||||
```
|
||||
|
||||
Putting the runner and the job containers on one shared `container.network` instead works too, and then the auto-detected address is reachable.
|
||||
By default, each runner runs a cache server for `actions/cache`, so caching works without setup.
|
||||
The runner stores entries in `cache.dir`, which defaults to `$HOME/.cache/actcache`. It does not share entries with other runners.
|
||||
|
||||
## Sharing a cache between runners
|
||||
|
||||
Run one dedicated cache server that every runner points at.
|
||||
Run one `gitea-runner cache-server` and configure each runner to use it. Use the same secret on the cache server and every runner. Generate the secret with `openssl rand -hex 32`.
|
||||
|
||||
1. Config for the cache server host:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
dir: /data/actcache
|
||||
port: 8088
|
||||
external_secret: "replace-with-a-strong-random-secret"
|
||||
# external_secret_file: /run/secrets/cache-secret # or keep it out of this file
|
||||
```
|
||||
|
||||
2. Start it:
|
||||
|
||||
```bash
|
||||
gitea-runner -c cache-server-config.yaml cache-server
|
||||
```
|
||||
|
||||
3. On every runner:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
external_server: "http://cache-host:8088/"
|
||||
external_secret: "replace-with-a-strong-random-secret" # must match the server
|
||||
```
|
||||
|
||||
The secret authenticates runners against the shared server and must be identical on all of them; generate one with `openssl rand -hex 32`. Setting both `external_secret` and `external_secret_file` is an error.
|
||||
|
||||
`cache-server` accepts `--dir`, `--host` and `--port`, which override the corresponding `cache.*` keys. Every other setting, `external_secret` included, has to come from the config file.
|
||||
|
||||
### Alternatives
|
||||
|
||||
- **Shared filesystem** — mount the same NFS/CIFS share on every runner and point `cache.dir` at it. Simpler, but repositories are less isolated from each other than behind a cache server.
|
||||
- **Object storage** — mount S3 or MinIO as a FUSE filesystem, e.g. with [s3fs](https://github.com/s3fs-fuse/s3fs-fuse) or [goofys](https://github.com/kahing/goofys), and set `cache.dir` to the mount point.
|
||||
|
||||
## Action repository cache
|
||||
|
||||
Actions pulled by `uses:` are cached too, and by default refreshed on every job so a moved tag is picked up. To pin them to what has already been fetched:
|
||||
On the cache server:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
offline_mode: true
|
||||
dir: /data/actcache
|
||||
port: 8088
|
||||
external_secret_file: /run/secrets/cache-secret
|
||||
```
|
||||
|
||||
A re-tagged `v6` or an updated branch then stays at the cached commit until its entry expires or is removed. Combined with `runner.action_shallow_clone` (on by default, fetching only the requested ref at depth 1), this keeps job startup fast on runners with limited bandwidth.
|
||||
```bash
|
||||
gitea-runner -c cache-server.yaml cache-server
|
||||
```
|
||||
|
||||
On each runner:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
external_server: "http://cache-host:8088/"
|
||||
external_secret_file: /run/secrets/cache-secret
|
||||
```
|
||||
|
||||
Jobs send cache requests to their runner, which forwards them to the shared cache server. Only the runners need to reach the shared cache server. Set `external_secret` to supply the secret inline instead of from a file.
|
||||
|
||||
Runners can also share a `cache.dir` directory on a filesystem that supports file locks. This makes cache requests slower.
|
||||
|
||||
## S3-compatible storage
|
||||
|
||||
Use an S3-compatible bucket such as AWS S3, MinIO or RustFS to share the cache without a separate cache server:
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
s3:
|
||||
endpoint: "http://minio:9000"
|
||||
bucket: "runner-cache"
|
||||
access_key_file: "/run/secrets/cache-s3-access-key"
|
||||
secret_key_file: "/run/secrets/cache-s3-secret-key"
|
||||
```
|
||||
|
||||
Runners with the same settings share the cache. An entry saved on one runner becomes available to the others within 30 seconds. The eviction settings below do not apply to the bucket. Add lifecycle rules to expire old entries and abort incomplete multipart uploads.
|
||||
|
||||
## Eviction
|
||||
|
||||
| Option | Default | Removes |
|
||||
| --- | --- | --- |
|
||||
| `cache.retention` | `168h` | Entries not read or written within this time |
|
||||
| `cache.repo_size_limit` | `10GB` | Least recently used entries when a repository's cache exceeds this size |
|
||||
| `cache.size_limit` | off | Least recently used entries when the whole cache exceeds this size |
|
||||
|
||||
The cache also keeps 1024 MiB free on its volume, or `health_check.min_free_disk_space_mb` when [health checks](monitoring.md#health-checks) are enabled. With a shared cache server, set these options on the server.
|
||||
|
||||
## Artifacts
|
||||
|
||||
The runner adapts `actions/cache`, `actions/upload-artifact` and `actions/download-artifact` while a job runs so these actions work with Gitea. With these changes, the cache uses the cache service v2 protocol.
|
||||
|
||||
Artifact uploads go through the runner's cache server, so jobs must be able to reach it. Set `cache.v2: false` to send artifact uploads directly to Gitea. Set `runner.patch_actions: false` to run every action exactly as published. This uses the cache service v1 protocol and causes the published artifact actions to fail.
|
||||
|
||||
## Jobs cannot reach the cache
|
||||
|
||||
If `actions/cache` fails with `connect ETIMEDOUT`, jobs cannot reach the runner's cache server.
|
||||
|
||||
A runner container connects itself to each job network when it uses the same Docker daemon as its jobs. For jobs on another Docker daemon, for example through a remote `DOCKER_HOST`, set `cache.host` and `cache.port` to an address and port the jobs can reach. Jobs using `container.network: bridge` cannot reach a runner container outside that network. Leave `container.network` empty or use a network that includes the runner container.
|
||||
|
||||
## Action cache
|
||||
|
||||
For each job, the runner checks action tags and branches for updates, so it picks up moved tags such as `v6`. With `cache.offline_mode: true`, the runner reuses its downloaded copy. This speeds up jobs on slow networks, but moved tags and updated branches stay at the cached commit.
|
||||
|
||||
@@ -4,135 +4,58 @@ sidebar_position: 3
|
||||
|
||||
# Configuration
|
||||
|
||||
The runner is configured with a single YAML file. It is optional: without one, the built-in defaults apply, which are the same as an empty YAML document and safe to run with.
|
||||
The runner works without a configuration file. Create one to change a default:
|
||||
|
||||
```bash
|
||||
gitea-runner generate-config > config.yaml
|
||||
gitea-runner -c config.yaml register
|
||||
gitea-runner config init
|
||||
gitea-runner config set runner.capacity 4
|
||||
gitea-runner -c config.yaml daemon
|
||||
```
|
||||
|
||||
`-c` / `--config` is a global flag and is accepted by every command that loads configuration (`register`, `daemon`, `cache-server`). The generated file is fully commented and is reproduced in [Example configuration](reference/config-example.md).
|
||||
`config init` writes a minimal `config.yaml` in the working directory. Pass the file with `-c` when running `register`, `daemon` or `cache-server`. These commands do not find configuration files automatically. The runner reads its configuration only at startup. Restart it after each change.
|
||||
|
||||
:::warning No environment variable overrides
|
||||
The runner process is configured only through the YAML file. Earlier releases let a few variables (`GITEA_DEBUG`, `GITEA_TRACE`, `GITEA_RUNNER_CAPACITY`, `GITEA_RUNNER_FILE`, `GITEA_RUNNER_ENVIRON`, `GITEA_RUNNER_ENV_FILE`) override parts of the config; those overrides have been removed.
|
||||
## Editing
|
||||
|
||||
The variables understood by the Docker images belong to their [entrypoint](installation/docker.md#entrypoint-environment-variables), not to the runner, and `GITEA_RUNNER_LABELS` / `GITEA_RUNNER_REGISTRATION_TOKEN` are read by the corresponding CLI flags only.
|
||||
:::
|
||||
The `config` command edits the configuration file in place and preserves its comments:
|
||||
|
||||
Values with a duration type accept Go duration strings such as `30s`, `10m`, `3h`.
|
||||
```bash
|
||||
gitea-runner config set runner.timeout 90m
|
||||
gitea-runner config set runner.envs.MY_VAR value
|
||||
gitea-runner config add container.valid_volumes '/data/**'
|
||||
gitea-runner config remove container.valid_volumes '/data/**'
|
||||
gitea-runner config get runner.capacity
|
||||
```
|
||||
|
||||
## `log`
|
||||
A key is the path to a YAML value, with dots between levels. The command rejects unknown keys and values of the wrong type before changing the file. Without `-c`, these commands look for `config.yaml` or `config.yml` in the working directory, then in the directory containing the binary.
|
||||
|
||||
Controls the runner's own log, not how step output is streamed to the UI.
|
||||
`gitea-runner config generate` prints every option with its default and a description. This matches the [example configuration](reference/config-example.md).
|
||||
|
||||
Use `${NAME}` in a value to read an environment variable from the runner's environment. The configuration fails to load if `NAME` is unset. Use `$${NAME}` for a literal `${NAME}`:
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
capacity: ${RUNNER_CAPACITY}
|
||||
```
|
||||
|
||||
## Common options
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `log.level` | `info` | `trace`, `debug`, `info`, `warn`, `error`, `fatal` or `panic`. `trace` and `debug` add the caller's `file:line`. |
|
||||
| `runner.capacity` | `1` | Maximum number of jobs that can run at once. |
|
||||
| `runner.timeout` | `3h` | Maximum job duration. Gitea's own job timeout may stop a job earlier. |
|
||||
| `runner.shutdown_timeout` | `0s` | Time to let running jobs finish before canceling them during shutdown. |
|
||||
| `runner.envs` | | Environment variables for every job. |
|
||||
| `runner.env_file` | | File containing additional environment variables for every job. |
|
||||
| `runner.labels` | | See [Labels](labels.md). |
|
||||
| `runner.insecure` | `false` | Skip verification of Gitea's TLS certificate. |
|
||||
| `runner.client_cert_file`, `runner.client_key_file` | | Client certificate and key for a Gitea instance that requires mutual TLS. |
|
||||
| `runner.extra_headers` | | HTTP headers for requests to Gitea, for example for a reverse proxy. |
|
||||
| `runner.github_mirror` | | URL to use instead of `https://github.com` when downloading actions from GitHub. |
|
||||
| `container.network` | | Docker network for job containers. If empty, the runner creates a network for each job. |
|
||||
| `container.options` | | Additional `docker run` options for every job container. |
|
||||
| `container.privileged` | `false` | Run job containers in privileged mode. See [Jobs](jobs.md#volumes-and-privileges). |
|
||||
| `container.valid_volumes` | | Volumes and host paths that workflows may mount. |
|
||||
| `container.force_pull` | `false` | Pull job images even when they are already present. |
|
||||
| `log.level` | `info` | Verbosity of the runner's log. |
|
||||
|
||||
## `runner`
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `file` | `.runner` | path of the registration file. Each runner process needs its own. |
|
||||
| `capacity` | `1` | jobs executed concurrently. With an empty `container.network`, every concurrent docker job takes a subnet from the daemon's address pool, so a high capacity can exhaust it (see `default-address-pools` in the daemon config). |
|
||||
| `envs` | – | extra environment variables given to every job. |
|
||||
| `env_file` | `.env` | same, read from a file; ignored when empty or missing. |
|
||||
| `timeout` | `3h` | maximum job duration. Gitea has its own timeout (3h by default) and may stop the job earlier. |
|
||||
| `shutdown_timeout` | `0s` | how long a shutdown waits for running jobs before cancelling them. |
|
||||
| `insecure` | `false` | skip TLS verification of the Gitea instance. |
|
||||
| `fetch_timeout` | `5s` | timeout of a single job fetch. |
|
||||
| `fetch_interval` | `2s` | base polling interval. |
|
||||
| `fetch_interval_max` | `5s` | upper bound of the exponential backoff applied while idle. `0`, or the same value as `fetch_interval`, disables the backoff. |
|
||||
| `labels` | see [Labels](labels.md) | labels used at registration, and by `daemon` when the flag is absent. |
|
||||
| `github_mirror` | – | replaces `https://github.com` when actions are pulled and the instance's `DEFAULT_ACTIONS_URL` points at GitHub. |
|
||||
| `action_shallow_clone` | `true` | fetch only the requested ref of an action repository at depth 1 instead of its full history. |
|
||||
| `set_act_env` | `true` | inject `ACT=true` into jobs. Set to `false` so workflows gated on `if: ${{ !env.ACT }}` behave as they do on GitHub. |
|
||||
| `allocate_pty` | `false` | allocate a pseudo-TTY per step. Enable only when a job needs an interactive terminal; tools like `docker build` then write redrawing progress frames into the log. |
|
||||
| `workdir_cleanup_age` | `24h` | age at which stale task workspaces and orphaned host-mode scratch directories are removed while idle. |
|
||||
| `idle_cleanup_interval` | `10m` | cadence of the idle cleanup pass. Setting either this or `workdir_cleanup_age` to `0` disables all idle cleanup. |
|
||||
| `post_task_script` | – | host script run after each task's cleanup, see [Post-task script](hooks/post-task-script.md). |
|
||||
| `post_task_script_timeout` | `5m` | hard limit for that script. |
|
||||
| `hooks.job_started` / `hooks.job_completed` | – | scripts run inside the job environment, see [Job hooks](hooks/job-hooks.md). |
|
||||
|
||||
Log and state reporting can be tuned when the UI updates too slowly or the instance sees too many requests:
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `log_report_interval` | `5s` | base interval of the periodic log flush. |
|
||||
| `log_report_max_latency` | `3s` | maximum time a single log row waits. Only has an effect below `log_report_interval`. |
|
||||
| `log_report_batch_size` | `100` | flush immediately once this many rows are buffered, so bursty output arrives promptly. |
|
||||
| `state_report_interval` | `5s` | interval of task state reports. State is also sent on every step transition. |
|
||||
| `report_close_timeout` | `10s` | per-attempt deadline for the final log and state flush of a finished job. |
|
||||
|
||||
### Idle cleanup
|
||||
|
||||
While no job is running, the runner cleans up after earlier ones:
|
||||
|
||||
- stale task workspaces older than `workdir_cleanup_age` are removed when `container.bind_workdir` is enabled. Only purely numeric subdirectories of `container.workdir_parent` are treated as workspaces, and the path is assumed not to be shared with another runner;
|
||||
- orphaned host-mode scratch directories are removed on the same schedule;
|
||||
- per-job docker networks left behind by jobs the runner did not live to tear down are removed. They are recognised by the `com.gitea.runner.uuid` label carrying this runner's uuid, so leftovers of other runners on the same daemon are left alone. Without this, each leaked network keeps holding a subnet of the daemon's address pool.
|
||||
|
||||
## `cache`
|
||||
|
||||
See [Caching](cache.md) for the full picture, including shared cache servers.
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `enabled` | `true` | run the built-in cache server used by `actions/cache` and friends. |
|
||||
| `dir` | `$HOME/.cache/actcache` | where cache blobs are stored. Ignored with `external_server`. |
|
||||
| `host` | – | address job containers use to reach this runner's cache server. Empty means auto-detect; `0.0.0.0` is not valid. |
|
||||
| `port` | `0` | port of the built-in server, `0` picks a free one. |
|
||||
| `external_server` | – | URL of a shared `cache-server` to use instead of a local one. |
|
||||
| `external_secret` | – | shared secret, required with `external_server`; must be identical everywhere. Generate with `openssl rand -hex 32`. |
|
||||
| `external_secret_file` | – | read that secret from a file instead. Setting both is an error. |
|
||||
| `offline_mode` | `false` | reuse a cached action instead of fetching it on every job. A moved tag or updated branch then stays at the cached commit until the entry expires or is removed. |
|
||||
| `v2` | `true` | serve the cache service v2 API used by `actions/[email protected]` and later. |
|
||||
|
||||
## `container`
|
||||
|
||||
Applies to jobs that run in containers.
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `network` | – | network the job container joins: `host`, `bridge`, or a custom network name. Empty means the runner creates one per job. `network_mode` is still accepted for old configs. |
|
||||
| `network_create_options.enable_ipv4` / `enable_ipv6` | Docker defaults | only apply to auto-created networks. IPv6 additionally requires `dockerd --ipv6`. |
|
||||
| `privileged` | `false` | run job containers privileged; required for Docker-in-Docker inside jobs. |
|
||||
| `options` | – | extra `docker run` options, e.g. `--add-host=my.gitea.url:host-gateway`. A volume declared here replaces the one the runner mounts on the same container path, which is how the tool cache can be kept on the host (`--volume /host/toolcache:/opt/hostedtoolcache`); its source must also be allowed by `valid_volumes`. |
|
||||
| `workdir_parent` | `/workspace` | parent directory of a job's working directory inside the container. A leading `/` is trimmed and re-added. |
|
||||
| `valid_volumes` | `[]` | volumes and bind mounts a job may mount, as [glob](https://github.com/gobwas/glob) patterns. `[]` forbids all, `['**']` allows all. |
|
||||
| `docker_host` | – | override the docker host. Empty auto-detects it, `-` auto-detects it but does not mount the socket into job containers. |
|
||||
| `force_pull` | `false` | pull images even when present. Images pinned by digest are never re-pulled, and a failed pull with a local copy available only warns. |
|
||||
| `force_rebuild` | `false` | rebuild local action images even when present. |
|
||||
| `require_docker` | `false` | always require a reachable daemon, even for host-only labels. |
|
||||
| `docker_timeout` | `0s` | how long to wait for the daemon to become reachable. |
|
||||
| `bind_workdir` | `false` | bind-mount the workspace from the host instead of using a docker volume, so jobs can bind-mount it by its own path into containers they start (`.:/app` in `docker compose`). Not needed when workflows use `GITEA_DOCKER_WORKSPACE`. The parent directory must then be mounted into the runner container. |
|
||||
|
||||
:::note Privileged mode and workflow container options
|
||||
A workflow's own `jobs.<job_id>.container.options` are untrusted input. While `container.privileged` is disabled, the options that would break out of the container are stripped with a warning in the job log: `--pid`, `--ipc`, `--uts`, `--cgroupns`, `--userns`, `--cap-add`, `--security-opt`, `--device`, `--device-cgroup-rule`, `--gpus`, `--volumes-from`, `--runtime`, `--cgroup-parent` and `--sysctl`. They are honoured once privileged mode is enabled, because the operator has then opted into host access.
|
||||
:::
|
||||
|
||||
## `host`
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `host.workdir_parent` | `$HOME/.cache/act/` | parent directory of a job's working directory for host-mode jobs. |
|
||||
|
||||
## `health_check` and `metrics`
|
||||
|
||||
Both are covered in [Monitoring](monitoring.md).
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `health_check.enabled` | `false` | pause fetching new tasks while the machine looks unhealthy. |
|
||||
| `health_check.min_free_disk_space_mb` | `1024` | minimum free space on the filesystem holding the workspaces. |
|
||||
| `health_check.script` | – | extra executable; a non-zero exit, a timeout or a start failure marks the runner unavailable. |
|
||||
| `health_check.interval` | `30s` | how long a result is cached. |
|
||||
| `health_check.timeout` | `10s` | maximum script runtime. |
|
||||
| `metrics.enabled` | `false` | serve `/metrics`, `/healthz` and `/readyz`. |
|
||||
| `metrics.addr` | `127.0.0.1:9101` | listen address. There is no authentication, so only expose it behind a firewall. |
|
||||
| `metrics.readiness_grace` | `30s` | how long consecutive polling failures may last before `/readyz` returns 503. |
|
||||
|
||||
## Reloading
|
||||
|
||||
The runner reads its configuration at startup only. Restart the process after a change — with `shutdown_timeout` set, running jobs are given that much time to finish first.
|
||||
See [Caching](cache.md), [hooks](hooks/job-hooks.md) and [monitoring](monitoring.md) for their configuration options.
|
||||
|
||||
@@ -4,7 +4,7 @@ sidebar_position: 1
|
||||
|
||||
# Job hooks
|
||||
|
||||
Job hooks are operator-provided scripts that run **inside the job environment**, before the job's first step and after its last one. They are the equivalent of GitHub's [job hooks](https://docs.github.com/en/actions/how-tos/manage-runners/self-hosted-runners/run-scripts):
|
||||
Job hooks are scripts you provide. They run in the job environment before its first step and after its last step. Use them for setup that applies to every job, such as registry logins, mirror configuration or masking secrets used by all jobs.
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
@@ -13,62 +13,34 @@ runner:
|
||||
job_completed: /hooks/completed.sh
|
||||
```
|
||||
|
||||
| Setting | Runs |
|
||||
| --- | --- |
|
||||
| `runner.hooks.job_started` | before the job's first step, before any action is downloaded |
|
||||
| `runner.hooks.job_completed` | after the job's last post step, while the job environment is still up |
|
||||
`job_started` runs before any action is downloaded. `job_completed` runs after the last post step, including when the job fails or is cancelled. If these settings are unset, the runner reads GitHub's `ACTIONS_RUNNER_HOOK_JOB_STARTED` and `ACTIONS_RUNNER_HOOK_JOB_COMPLETED` from `runner.envs` or `runner.env_file`. The runner ignores workflow values for these hook variables.
|
||||
|
||||
`ACTIONS_RUNNER_HOOK_JOB_STARTED` and `ACTIONS_RUNNER_HOOK_JOB_COMPLETED` are read from the runner's environment (`runner.envs`, `runner.env_file`) when the settings are unset, so a configuration carried over from `actions/runner` keeps working. The settings take precedence. A workflow cannot point the runner at a different hook: those variables are only read from the runner's own environment, never from the job's.
|
||||
|
||||
Both hooks are **synchronous** and block the job while they run, and a non-zero exit from either one fails the job. There is no `continue-on-error` and no per-hook timeout — the job's `runner.timeout` is the only bound. Run anything long in the background from within the hook.
|
||||
|
||||
Use them for per-job setup that no workflow should have to carry: registry logins, mirror configuration, or masking runner-wide secrets with `::add-mask::`.
|
||||
A hook that exits with a non-zero status fails the job. Hooks block the job while they run and count against its timeout. Keep them fast.
|
||||
|
||||
## Where they run
|
||||
|
||||
The hooks run where the job's steps run: inside the job container, or on the host in host mode. The paths are resolved *there*, so the script has to exist in the job image or on the host — a path that only exists on the runner host is not visible to a containerized job. For host-wide cleanup after the job environment is gone, use the [post-task script](post-task-script.md) instead.
|
||||
Hooks run inside the job container, or on the host for host jobs. GitHub always runs hooks on the host. The script must exist in the job image or on the host where it runs. Job containers cannot access a path that exists only in the runner container. To make a host directory available to jobs, mount it with `container.options` and allow it in `container.valid_volumes`.
|
||||
|
||||
:::note
|
||||
This is a deliberate difference from `actions/runner`, which runs its job hooks on the host, outside any container the job declares. Running them where the steps run is what lets a hook prepare the environment the steps actually see.
|
||||
:::
|
||||
|
||||
The script is run according to its extension:
|
||||
|
||||
| Extension | Command |
|
||||
| Extension | Runs as |
|
||||
| --- | --- |
|
||||
| `.sh` | `bash -e <path>` |
|
||||
| `.ps1` | `pwsh -command . '<path>'` |
|
||||
| anything else | the file itself, which needs its own shebang and executable bit |
|
||||
| `.ps1` | `pwsh -command ". '<path>'"` |
|
||||
| Anything else | The file itself |
|
||||
|
||||
As on GitHub, the shell flags applied to `run:` steps are **not** applied to a hook — set `pipefail` or anything else you want inside the script.
|
||||
The shell options of `run:` steps do not apply to hooks. Set `pipefail` and other shell options inside the script.
|
||||
|
||||
A hook path that does not exist inside the job environment fails the job with `No such file or directory`, naming the path.
|
||||
## Environment and output
|
||||
|
||||
### Docker-in-Docker and Docker-out-of-Docker
|
||||
A hook receives the job's environment, including `runner.envs`, the workflow's `env:` and the `GITHUB_*` variables. The runner includes hook output in the job log and masks secrets as it does for step output.
|
||||
|
||||
The hook is executed and its files are exchanged over the Docker API, addressed by container ID, so no path is translated between the runner and the daemon. Both setups work unchanged, but they differ in where the hook file has to be:
|
||||
|
||||
- **DinD** — the daemon has its own filesystem. Bake the hook into the job image; a path from the runner's filesystem is not visible to it.
|
||||
- **DooD** — the job container is created by the host's daemon, so a bind mount in `container.options` is resolved against the **host**, not against the runner container. Either bake the hook into the job image, or mount a host directory and add it to `container.valid_volumes`.
|
||||
|
||||
## Environment
|
||||
|
||||
A hook sees the job's environment: the workflow, job and `container:` `env:`, the runner's `envs`, and the `GITHUB_*` context variables, with the same masking applied to its output as to a step's. The step-specific ones (`GITHUB_ACTION`, `GITHUB_OUTPUT`, `GITHUB_STATE`) are not set — a hook is not a step, so `::save-state::` and `::set-output::` have nowhere to go.
|
||||
|
||||
Its stdout is part of the job log, inside a collapsible group, and is scanned for workflow commands: `::add-mask::` registers a value to be masked for the rest of the job, `::set-env::` and `::add-path::` apply to the steps that follow.
|
||||
|
||||
`$GITHUB_ENV` and `$GITHUB_PATH` point at files that are read back after the hook exits, so the file-command form works too:
|
||||
Use `$GITHUB_ENV` and `$GITHUB_PATH` to pass environment variables and paths to later steps. Mask values with `::add-mask::`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
echo "REGISTRY_TOKEN=$(fetch-token)" >> "$GITHUB_ENV"
|
||||
token="$(fetch-token)"
|
||||
echo "::add-mask::$token"
|
||||
echo "REGISTRY_TOKEN=$token" >> "$GITHUB_ENV"
|
||||
echo "/opt/tooling/bin" >> "$GITHUB_PATH"
|
||||
```
|
||||
|
||||
Both files are the hook's own, separate from the per-step ones, so nothing a hook writes is truncated by the first step.
|
||||
|
||||
## Recommendations
|
||||
|
||||
- Keep hooks **fast** and return the right exit code: they are on the critical path of every job, and nothing bounds them.
|
||||
- Use **idempotent** operations, and expect `job_completed` to run after success, failure, and cancellation alike.
|
||||
- Mask anything secret the hook prints or exports with `::add-mask::`.
|
||||
For cleanup on the host after the job environment is gone, use the [post-task script](post-task-script.md).
|
||||
|
||||
@@ -4,98 +4,43 @@ sidebar_position: 2
|
||||
|
||||
# Post-task script
|
||||
|
||||
The post-task script is an optional host hook that runs **once after every task**, after the runner has finished its normal per-task cleanup. Typical uses are pruning Docker images, vacuuming ephemeral disks, or resetting VM state between jobs.
|
||||
The post-task script runs on the runner's host after each job, once the runner has removed the job's containers. Use it for housekeeping such as pruning Docker images or freeing disk space.
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
# Path to an executable on the host. Empty or omitted disables the hook.
|
||||
post_task_script: /usr/local/bin/gitea-post-task.sh
|
||||
# Hard limit on script runtime. Default when post_task_script is set: 5m.
|
||||
post_task_script_timeout: 2m
|
||||
```
|
||||
|
||||
| Option | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `runner.post_task_script` | disabled | host path to the script or binary. Relative paths are resolved from the runner's working directory. |
|
||||
| `runner.post_task_script_timeout` | `5m` when a script is set | maximum runtime before the runner kills the script and moves on. |
|
||||
|
||||
## When it runs
|
||||
|
||||
For each task, the order is:
|
||||
|
||||
1. the workflow runs (steps, actions, containers);
|
||||
2. in-job cleanup (action `post:` steps, container stop and removal);
|
||||
3. job outputs are reported to Gitea;
|
||||
4. the bind-workdir workspace is removed, when `container.bind_workdir` is enabled;
|
||||
5. **the post-task script**;
|
||||
6. the final task acknowledgement to Gitea.
|
||||
|
||||
The script is **additive**: it does not replace any built-in cleanup. With `container.bind_workdir` enabled, the workspace directory has usually already been deleted before the script starts, but `GITEA_WORKSPACE` still names the path the job used.
|
||||
|
||||
## The runner stays offline until the script finishes
|
||||
|
||||
This is the most important operational detail. When the script starts, the runner **stops sending task heartbeats**, so from Gitea's perspective it is not available for new work until the script exits and the final task flush has been sent.
|
||||
|
||||
While the script runs:
|
||||
|
||||
- Gitea does not assign another task to this runner for the current job slot;
|
||||
- the capacity slot stays occupied locally — with `capacity: 1`, no other task starts;
|
||||
- a shutdown counts this phase as part of the in-flight task, so a slow script delays graceful shutdown.
|
||||
|
||||
If the script never exits, the runner stays in this state until `runner.post_task_script_timeout` elapses (default **5 minutes**), then kills it and proceeds. Set that timeout to what your housekeeping is allowed to take, and keep the script short and bounded.
|
||||
|
||||
## Environment variables
|
||||
|
||||
The script receives `runner.envs` / `runner.env_file` values plus:
|
||||
|
||||
| Variable | Description |
|
||||
| --- | --- |
|
||||
| `GITEA_TASK_ID` | numeric task ID |
|
||||
| `GITEA_RUN_ID` | workflow run ID, when the server provides it |
|
||||
| `GITEA_REPOSITORY` | repository slug (`owner/name`) |
|
||||
| `GITEA_WORKSPACE` | workspace path the job used, which may already be deleted |
|
||||
| `GITEA_JOB_RESULT` | `success`, `failure`, `cancelled`, `skipped` or `unknown` |
|
||||
|
||||
The environment is **not** a copy of the job container's. Even `PATH` is only present if `runner.envs` or `runner.env_file` defines it.
|
||||
|
||||
## Output and errors
|
||||
|
||||
- stdout and stderr go to the **runner process log**, prefixed with `post-task script stdout:` / `post-task script stderr:` — not to the job log;
|
||||
- a non-zero exit is logged as a warning and does not change the job result already reported to Gitea;
|
||||
- timeouts and start failures are warnings too; the runner still acknowledges the task.
|
||||
|
||||
## Interaction with other timeouts
|
||||
|
||||
| Timeout | Effect on the post-task script |
|
||||
| --- | --- |
|
||||
| `runner.post_task_script_timeout` | kills the script if it runs too long. The **only** timeout that bounds it. |
|
||||
| `runner.timeout` | caps the task **up to** the script. The script detaches from the task deadline, so a job that nearly hit the runner timeout does not cut it short. |
|
||||
| `runner.shutdown_timeout` | bounds how long a shutdown waits for the **task**. The script detaches from cancellation and may extend shutdown until its own timeout elapses. |
|
||||
|
||||
## Examples
|
||||
|
||||
Prune dangling Docker resources on Linux:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
docker image prune -f
|
||||
docker builder prune -f --filter 'until=24h'
|
||||
```
|
||||
|
||||
On Windows, use a `.exe`, `.bat` or `.cmd` path; `.ps1` is not supported as the configured path, so wrap PowerShell in a batch file:
|
||||
The job's slot stays busy until the script exits. With `capacity: 1`, the runner accepts no new jobs while the script runs. The runner kills the script if it runs longer than `post_task_script_timeout`, which defaults to `5m`. The runner also waits for the script during shutdown.
|
||||
|
||||
The runner writes the script's output to its own log, not to the job log. If the script exits with a non-zero status, the runner logs a warning without changing the job's result.
|
||||
|
||||
## Environment
|
||||
|
||||
The script receives variables from `runner.envs` and `runner.env_file`, but not from the runner's own environment. Set `PATH` in one of these settings if the script needs it. The runner also sets these variables:
|
||||
|
||||
| Variable | Value |
|
||||
| --- | --- |
|
||||
| `GITEA_TASK_ID` | The task ID |
|
||||
| `GITEA_RUN_ID` | The workflow run ID |
|
||||
| `GITEA_REPOSITORY` | The repository as `owner/name` |
|
||||
| `GITEA_WORKSPACE` | The job's workspace path, which may already be deleted |
|
||||
| `GITEA_JOB_RESULT` | `success`, `failure`, `cancelled`, `skipped` or `unknown` |
|
||||
|
||||
## Windows
|
||||
|
||||
The configured path must be an `.exe`, `.bat` or `.cmd` file. Wrap a PowerShell script in a batch file:
|
||||
|
||||
```bat
|
||||
@echo off
|
||||
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%~dp0post-task.ps1"
|
||||
```
|
||||
|
||||
`.sh` files on Windows need a Unix shell on `PATH`, unless `post_task_script` points at the interpreter itself.
|
||||
|
||||
## Notes
|
||||
|
||||
- `gitea-runner exec` does not load the runner YAML and never runs this hook.
|
||||
- Use idempotent operations: the script runs after success, failure and cancellation alike.
|
||||
- Watch the runner log when testing failure modes — a hung script, a non-zero exit, a missing executable.
|
||||
- Bind-workdir idle cleanup (`runner.workdir_cleanup_age`) is separate from this hook and only runs while the runner is idle.
|
||||
- For work that has to happen inside the job environment, use [job hooks](job-hooks.md) instead.
|
||||
For work inside the job environment, use [job hooks](job-hooks.md).
|
||||
|
||||
@@ -5,47 +5,43 @@ slug: /
|
||||
|
||||
# Gitea Runner
|
||||
|
||||
The [Gitea Runner](https://gitea.com/gitea/runner) executes the jobs of [Gitea Actions](/usage/actions/overview).
|
||||
It polls a Gitea instance for queued jobs, runs their steps in a container or directly on the machine it is installed on, and streams the logs and the result back.
|
||||
[Gitea Runner](https://gitea.com/gitea/runner) runs [Gitea Actions](/usage/actions/overview) jobs.
|
||||
It asks a Gitea instance for jobs, runs them, and sends their logs and results back.
|
||||
|
||||
:::info
|
||||
These pages describe the runner `5.x` series. Pick another release, or the development version, in the **Runner Version** dropdown.
|
||||
These pages describe the runner `5.x` series. Select another release, or the development version, in the **Runner Version** dropdown.
|
||||
:::
|
||||
|
||||
## Requirements
|
||||
|
||||
A runner needs a Gitea instance with Actions enabled, a [registration token](registration.md), and, for containerized jobs, a Docker daemon. Actions are enabled by default since Gitea 1.21; on older instances they have to be turned on:
|
||||
- Gitea 1.21 or later with [Actions enabled](/administration/config-cheat-sheet#actions-actions), the default setting.
|
||||
- Git 2.34.1 or later on the runner's `PATH`.
|
||||
- Docker, or Podman with `podman.socket` enabled, for jobs in containers, Docker actions, and `docker://` steps.
|
||||
|
||||
```ini
|
||||
[actions]
|
||||
ENABLED=true
|
||||
```
|
||||
Jobs need these tools wherever steps run, in the job image or on the host:
|
||||
|
||||
The runner downloads actions and reusable workflows with Git, so it needs Git 2.34.1 or newer on its `PATH`; jobs that use `builtin:checkout` need Git in their image as well. The official runner images include it.
|
||||
- `bash` or `sh` for `run` steps, or `pwsh` or `powershell` on Windows.
|
||||
- `node` for JavaScript actions and `hashFiles()`.
|
||||
- `git` 2.34.1 or later for [`builtin:checkout`](jobs.md#built-in-checkout), plus `git-lfs` for its `lfs` input and `ssh` for its `ssh-key` input.
|
||||
|
||||
Other OCI engines that implement the Docker API may work, but are untested. Podman is not a supported configuration.
|
||||
## Where jobs run
|
||||
|
||||
## Execution modes
|
||||
The runner's [labels](labels.md) determine where each job runs. One runner can use a mix of these environments:
|
||||
|
||||
A runner can run jobs in three different ways. The mode is not a global setting: it follows from the [labels](labels.md) the runner is registered with, so a single runner can offer both container and host labels.
|
||||
| Label | Where the job runs |
|
||||
| --- | --- |
|
||||
| `docker://<image>` | In a container |
|
||||
| `kubernetes://<image>` | In a pod in a Kubernetes cluster |
|
||||
| `host` | Directly on the runner's machine |
|
||||
|
||||
| Mode | How jobs run | Docker daemon | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Docker (recommended) | in a container created from the label's image | external, e.g. the host's `/var/run/docker.sock` | jobs are isolated from each other, but share the daemon |
|
||||
| Docker-in-Docker | in a container created by a daemon that lives next to the runner | bundled in the `dind` / `dind-rootless` images | strongest isolation, more setup, needs `--privileged` |
|
||||
| Host | directly on the machine, with the tools installed there | only needed for `docker://` actions and service containers | no isolation between jobs |
|
||||
Host jobs run as the runner's user without isolation. Use them only for trusted repositories.
|
||||
|
||||
## Getting started
|
||||
|
||||
1. [Install the runner](installation/binary.md) as a binary, [in Docker](installation/docker.md), or [on Kubernetes](installation/kubernetes.md).
|
||||
2. [Register it](registration.md) against your instance with a registration token.
|
||||
3. [Configure it](configuration.md), and pick the [labels](labels.md) that decide which jobs it accepts.
|
||||
4. Optionally set up a [shared cache](cache.md), [job hooks](hooks/job-hooks.md), a [post-task script](hooks/post-task-script.md), or [metrics and health checks](monitoring.md).
|
||||
1. Install the runner [from a binary](installation/binary.md), [with Docker](installation/docker.md), or [on Kubernetes](installation/kubernetes.md).
|
||||
2. [Register it](registration.md) with your Gitea instance.
|
||||
3. Start it with `gitea-runner daemon`.
|
||||
|
||||
Every command and flag is listed in the [command line reference](reference/cli.md).
|
||||
The runner works without a configuration file. [Configuration](configuration.md) explains when you need one.
|
||||
|
||||
## Versioning and compatibility
|
||||
|
||||
The runner is released independently of Gitea and its version numbers are unrelated to the instance's. Gitea 1.21 or later is expected — older instances cannot accept the runner's label declaration — and individual features need a newer instance still, which is called out where they apply.
|
||||
|
||||
When moving between major runner versions, read [Upgrading](upgrade.md) first: `2.0.0`, `3.0.0`, `4.0.0` and `5.0.0` all contain breaking changes.
|
||||
The runner is released independently of Gitea. Read [Upgrading](upgrade.md) before moving to a new major version.
|
||||
|
||||
@@ -4,62 +4,46 @@ sidebar_position: 1
|
||||
|
||||
# Install from a binary
|
||||
|
||||
The runner is a single static binary called `gitea-runner`. It has no dependencies apart from a Docker daemon for containerized jobs.
|
||||
The runner is a single binary, `gitea-runner`, built for Linux, macOS, Windows, and FreeBSD.
|
||||
|
||||
## Download
|
||||
|
||||
- released builds: [dl.gitea.com/gitea-runner](https://dl.gitea.com/gitea-runner/) or the [release page](https://gitea.com/gitea/runner/releases)
|
||||
- development builds of the `main` branch: [dl.gitea.com/gitea-runner/nightly](https://dl.gitea.com/gitea-runner/nightly/)
|
||||
|
||||
Each file is published next to a `.sha256` checksum and an `.xz` compressed variant:
|
||||
Download releases from [dl.gitea.com/gitea-runner](https://dl.gitea.com/gitea-runner/). Each binary has a matching `.sha256` checksum file:
|
||||
|
||||
```bash
|
||||
VERSION=5.1.1 # any 5.x release, see the release page
|
||||
VERSION=5.2.0
|
||||
curl -sSLO "https://dl.gitea.com/gitea-runner/$VERSION/gitea-runner-$VERSION-linux-amd64"
|
||||
curl -sSLO "https://dl.gitea.com/gitea-runner/$VERSION/gitea-runner-$VERSION-linux-amd64.sha256"
|
||||
sha256sum -c "gitea-runner-$VERSION-linux-amd64.sha256"
|
||||
install -m 0755 "gitea-runner-$VERSION-linux-amd64" /usr/local/bin/gitea-runner
|
||||
sudo install -m 0755 "gitea-runner-$VERSION-linux-amd64" /usr/local/bin/gitea-runner
|
||||
```
|
||||
|
||||
Check that the binary matches your platform:
|
||||
|
||||
```bash
|
||||
gitea-runner --version
|
||||
```
|
||||
|
||||
## Build from source
|
||||
|
||||
Building requires the Go version declared in the repository's `go.mod`:
|
||||
|
||||
```bash
|
||||
git clone https://gitea.com/gitea/runner.git
|
||||
cd runner
|
||||
make build
|
||||
```
|
||||
To build the runner yourself, run `make build` in a clone of [gitea/runner](https://gitea.com/gitea/runner).
|
||||
|
||||
## First run
|
||||
|
||||
```bash
|
||||
gitea-runner generate-config > config.yaml # optional, defaults are safe
|
||||
gitea-runner -c config.yaml register # see "Registering a runner"
|
||||
gitea-runner -c config.yaml daemon
|
||||
gitea-runner register --instance https://gitea.example.com --token <token>
|
||||
gitea-runner daemon
|
||||
```
|
||||
|
||||
The `daemon` command runs in the foreground. It reads the registration file (`runner.file`, `.runner` by default) relative to its working directory, so keep the working directory stable across restarts.
|
||||
`register` prompts for the remaining settings and writes the `.runner` registration file to the working directory. Run `daemon` from the same directory so it can read the file. See [Registration](../registration.md).
|
||||
|
||||
## Run as a systemd service
|
||||
## systemd
|
||||
|
||||
Create an unprivileged user, install the binary, and register the runner as that user so the `.runner` file ends up in the service's working directory:
|
||||
Create a user and a configuration file. Then register the runner as that user from its home directory:
|
||||
|
||||
```bash
|
||||
sudo useradd --system --home-dir /var/lib/gitea-runner --create-home gitea-runner
|
||||
sudo install -d /etc/gitea-runner
|
||||
sudo -u gitea-runner gitea-runner generate-config | sudo tee /etc/gitea-runner/config.yaml >/dev/null
|
||||
sudo mkdir -p /etc/gitea-runner
|
||||
sudo gitea-runner config init -c /etc/gitea-runner/config.yaml
|
||||
sudo chown gitea-runner /etc/gitea-runner/config.yaml
|
||||
cd /var/lib/gitea-runner
|
||||
sudo -u gitea-runner gitea-runner register -c /etc/gitea-runner/config.yaml
|
||||
sudo -u gitea-runner gitea-runner register -c /etc/gitea-runner/config.yaml \
|
||||
--instance https://gitea.example.com --token <token>
|
||||
```
|
||||
|
||||
Then install the unit as `/etc/systemd/system/gitea-runner.service`:
|
||||
Install the unit as `/etc/systemd/system/gitea-runner.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
@@ -79,8 +63,6 @@ User=gitea-runner
|
||||
Group=gitea-runner
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
# Allow running jobs to finish before the runner is stopped. Keep this in sync
|
||||
# with runner.shutdown_timeout in the config.
|
||||
TimeoutStopSec=3h
|
||||
|
||||
[Install]
|
||||
@@ -92,13 +74,17 @@ sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now gitea-runner
|
||||
```
|
||||
|
||||
If jobs use the host's Docker daemon, the `gitea-runner` user also needs access to the daemon socket. Adding it to the `docker` group grants that access and is [equivalent to root on the host](https://docs.docker.com/engine/security/#docker-daemon-attack-surface).
|
||||
Stopping the service cancels running jobs unless `runner.shutdown_timeout` gives them time to finish. Keep `runner.shutdown_timeout` below `TimeoutStopSec`:
|
||||
|
||||
Environment variables for the process — most importantly [proxy variables](../proxy.md) — belong in `Environment=` lines or a drop-in file, not in the runner config.
|
||||
```bash
|
||||
sudo -u gitea-runner gitea-runner config set -c /etc/gitea-runner/config.yaml runner.shutdown_timeout 2h50m
|
||||
```
|
||||
|
||||
## Run as a launchd daemon (macOS)
|
||||
For jobs in containers, give the `gitea-runner` user access to the Docker daemon's socket, for example through the `docker` group. That access is [equivalent to root](https://docs.docker.com/engine/security/#docker-daemon-attack-surface) on the host. Set the runner's environment variables, such as [proxy settings](../proxy.md), with `Environment=` lines in the unit.
|
||||
|
||||
macOS uses `launchd` instead of systemd. Daemons run as `root` by default; an unprivileged `_gitea-runner` user can be created with `dscl`. Install the following as `/Library/LaunchDaemons/com.gitea.runner.plist` and adjust the paths to your installation:
|
||||
## launchd (macOS)
|
||||
|
||||
Adjust the paths and user for your setup, then save this file as `/Library/LaunchDaemons/com.gitea.runner.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -114,16 +100,10 @@ macOS uses `launchd` instead of systemd. Daemons run as `root` by default; an un
|
||||
<string>--config</string>
|
||||
<string>/etc/gitea-runner/config.yaml</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>UserName</key>
|
||||
<string>_gitea-runner</string>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/var/lib/gitea-runner</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/var/lib/gitea-runner/runner.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/var/lib/gitea-runner/runner.err</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
@@ -131,23 +111,22 @@ macOS uses `launchd` instead of systemd. Daemons run as `root` by default; an un
|
||||
<key>HOME</key>
|
||||
<string>/var/lib/gitea-runner</string>
|
||||
</dict>
|
||||
<key>UserName</key>
|
||||
<string>_gitea-runner</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/var/lib/gitea-runner/runner.log</string>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo launchctl load /Library/LaunchDaemons/com.gitea.runner.plist
|
||||
sudo launchctl bootstrap system /Library/LaunchDaemons/com.gitea.runner.plist
|
||||
```
|
||||
|
||||
On macOS and Windows hosts, jobs usually run with [host labels](../labels.md) and the tools installed on the machine.
|
||||
|
||||
## Windows
|
||||
|
||||
Install the `windows-amd64` binary and register it as a service with any service wrapper (for example `sc.exe` plus a wrapper such as [WinSW](https://github.com/winsw/winsw), or a scheduled task at boot). The runner itself has no service-installer subcommand.
|
||||
Run `gitea-runner daemon` with a service wrapper such as [WinSW](https://github.com/winsw/winsw). The runner has no service installer of its own.
|
||||
|
||||
Keep in mind for Windows hosts:
|
||||
|
||||
- `runner.post_task_script` accepts `.exe`, `.bat` and `.cmd` paths; `.ps1` is not supported as the configured path.
|
||||
- host-mode jobs are terminated as a process tree, so tools that daemonize are not left behind.
|
||||
On macOS and Windows, jobs usually run directly on the runner's machine with [host labels](../labels.md).
|
||||
|
||||
@@ -4,120 +4,74 @@ sidebar_position: 2
|
||||
|
||||
# Install with Docker
|
||||
|
||||
The official images are published on [Docker Hub](https://hub.docker.com/r/gitea/runner/tags) as `docker.io/gitea/runner`.
|
||||
`latest` is the newest release and the `5` tag follows the newest `5.x` release; `nightly` is built from the `main` branch, and every release is also tagged with its exact version.
|
||||
|
||||
In the container the registration and the daemon are combined: the entrypoint registers the runner on first start (when no registration file exists yet) and then execs `gitea-runner daemon`.
|
||||
|
||||
## Image flavours
|
||||
|
||||
All flavours contain the same `gitea-runner` binary and differ only in how a Docker daemon is made available to jobs.
|
||||
|
||||
| Tag | Base image | Docker daemon | Supervisor | Runs as |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `latest`, `5`, `5.1`, `<version>` | `alpine` | none, you provide one | `tini` | `root` |
|
||||
| `latest-dind`, `5-dind` | `docker:dind` | bundled, needs `--privileged` | `s6` | `root` |
|
||||
| `latest-dind-rootless`, `5-dind-rootless` | `docker:dind-rootless` | bundled, rootless | `s6` | `rootless` (UID 1000) |
|
||||
|
||||
The rootless flavour's UID is fixed at 1000 by the upstream base image, and its daemon always listens on `/run/user/1000/docker.sock`, so `--user 1001` does not work. To talk to a *host* rootless daemon under another UID, use the basic flavour and bind-mount that daemon's socket instead.
|
||||
|
||||
## Basic flavour
|
||||
|
||||
The default image ships no daemon of its own, so jobs that use `docker://` images need one from outside the container — usually the host's socket:
|
||||
Runner images are available on [Docker Hub](https://hub.docker.com/r/gitea/runner/tags) as `docker.io/gitea/runner`. On its first start, the container registers and starts the runner:
|
||||
|
||||
```bash
|
||||
docker run -d --name my_runner \
|
||||
-e GITEA_INSTANCE_URL=<instance_url> \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN=<registration_token> \
|
||||
-e GITEA_RUNNER_NAME=<runner_name> \
|
||||
-v $PWD/data:/data \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
docker.io/gitea/runner:5
|
||||
```
|
||||
|
||||
This flavour does not need `--privileged`. The trade-off is that jobs share the host's daemon and can therefore see its other containers and images. A job that can reach the socket can also read the reusable `GITEA_RUNNER_REGISTRATION_TOKEN` from the runner container's `docker inspect` output.
|
||||
|
||||
## Docker-in-Docker
|
||||
|
||||
The `dind` flavour bundles its own daemon, so no socket has to be mounted:
|
||||
|
||||
```bash
|
||||
docker run -d --name my_runner --privileged \
|
||||
-e GITEA_INSTANCE_URL=<instance_url> \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN=<registration_token> \
|
||||
-v $PWD/data:/data \
|
||||
docker run -d --name gitea-runner --restart always --privileged \
|
||||
-e GITEA_INSTANCE_URL=https://gitea.example.com \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN=<token> \
|
||||
-v ./data:/data \
|
||||
-v runner-docker:/var/lib/docker \
|
||||
docker.io/gitea/runner:5-dind
|
||||
```
|
||||
|
||||
`s6` starts `dockerd` first and the runner service waits for it before registering. Use `5-dind-rootless` to run both the daemon and the runner as an unprivileged user; rootless Docker's usual limitations around networking, cgroups and storage drivers apply.
|
||||
The `-dind` image runs its own Docker daemon for jobs. Jobs never get access to the host's Docker daemon socket, which grants the equivalent of root access on the host. The two volumes preserve registration and job images when you replace the container:
|
||||
|
||||
## Volumes
|
||||
- `/data` holds the `.runner` registration file. Without it, a new container registers as another runner.
|
||||
- `/var/lib/docker` holds the images pulled for jobs. Without it, a new container pulls them again.
|
||||
|
||||
Two different pieces of state are worth persisting, and neither implies the other:
|
||||
## Image flavours
|
||||
|
||||
- `/data` is the runner's working directory. It holds the `.runner` registration file and, optionally, the config file. Without it, a recreated container registers itself again as a new runner, leaving a stale entry in Gitea, and fails outright if the token has been reset in the meantime.
|
||||
- the Docker daemon's data root holds the images pulled for jobs. It is **not** under `/data`: for `dind` it is `/var/lib/docker` inside the container, for `dind-rootless` it is `/home/rootless/.local/share/docker`. Give it its own volume, or every new container re-pulls the job images.
|
||||
| Tag | Docker daemon for jobs |
|
||||
| --- | --- |
|
||||
| `5-dind` (recommended) | Bundled. Requires `--privileged`. |
|
||||
| `5-dind-rootless` | Bundled. Runs as UID 1000. Requires `--privileged` and [rootless Docker](https://docs.docker.com/engine/security/rootless/) support on the host. Stores its images in `/home/rootless/.local/share/docker`. |
|
||||
| `5` | None. Mount the host's Docker daemon socket with `-v /var/run/docker.sock:/var/run/docker.sock`, or set `DOCKER_HOST`. |
|
||||
|
||||
## Entrypoint environment variables
|
||||
The `5` tags follow the newest `5.x` release. The `latest` and exact version tags such as `5.2.0` use the same suffixes. The `-dind` flavours are available for amd64 and arm64. The basic image also supports riscv64 and s390x. The images are designed for Docker, not Podman.
|
||||
|
||||
The entrypoint ([`scripts/run.sh`](https://gitea.com/gitea/runner/src/branch/main/scripts/run.sh)) understands:
|
||||
When the basic image uses the host's Docker daemon, jobs share that daemon. Use this setup only for trusted repositories.
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Meaning |
|
||||
| --- | --- |
|
||||
| `GITEA_INSTANCE_URL` | instance to register against, e.g. `https://gitea.example.com/` |
|
||||
| `GITEA_RUNNER_REGISTRATION_TOKEN` | registration token; unset before the daemon starts |
|
||||
| `GITEA_RUNNER_REGISTRATION_TOKEN_FILE` | file to read the token from, for Docker/Kubernetes secrets |
|
||||
| `GITEA_RUNNER_NAME` | runner name, defaults to the container hostname |
|
||||
| `GITEA_RUNNER_LABELS` | labels, passed to both `register` and `daemon` |
|
||||
| `GITEA_RUNNER_EPHEMERAL` | any non-empty value registers the runner as [ephemeral](../registration.md#ephemeral-runners) |
|
||||
| `GITEA_RUNNER_ONCE` | any non-empty value runs a single job, then exits |
|
||||
| `GITEA_MAX_REG_ATTEMPTS` | registration attempts before giving up, default `10` |
|
||||
| `RUNNER_STATE_FILE` | registration file name inside `/data`, default `.runner` |
|
||||
| `CONFIG_FILE` | config file inside the container, passed as `--config` |
|
||||
| `GITEA_INSTANCE_URL` | Gitea instance to register with. |
|
||||
| `GITEA_RUNNER_REGISTRATION_TOKEN` | Registration token, needed only until registration completes. |
|
||||
| `GITEA_RUNNER_REGISTRATION_TOKEN_FILE` | File to read the registration token from, such as a Docker secret. |
|
||||
| `GITEA_RUNNER_NAME` | Runner name. Defaults to the container's hostname. |
|
||||
| `GITEA_RUNNER_LABELS` | Comma-separated [labels](../labels.md), applied on every start. |
|
||||
| `GITEA_RUNNER_EPHEMERAL` | Any nonempty value registers an [ephemeral runner](../registration.md#ephemeral-runners). |
|
||||
| `GITEA_RUNNER_ONCE` | Any nonempty value makes the runner exit after one job. |
|
||||
| `GITEA_MAX_REG_ATTEMPTS` | Maximum number of registration attempts. Unlimited by default, with 5 seconds between attempts. |
|
||||
| `CONFIG_FILE` | Path to a [configuration file](../configuration.md) inside the container. |
|
||||
|
||||
These are entrypoint variables, not runner settings: the runner process itself is configured only through the [config file](../configuration.md).
|
||||
|
||||
Mount the config file when you need one:
|
||||
To use a configuration file, mount it and set `CONFIG_FILE` to its path:
|
||||
|
||||
```bash
|
||||
docker run -v $PWD/config.yaml:/config.yaml -e CONFIG_FILE=/config.yaml ...
|
||||
docker run ... -v ./config.yaml:/config.yaml -e CONFIG_FILE=/config.yaml docker.io/gitea/runner:5-dind
|
||||
```
|
||||
|
||||
A config file can be generated with the image itself:
|
||||
|
||||
```bash
|
||||
docker run --rm --entrypoint="" docker.io/gitea/runner:5 gitea-runner generate-config > config.yaml
|
||||
```
|
||||
|
||||
## docker compose
|
||||
## Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
runner:
|
||||
image: docker.io/gitea/runner:5
|
||||
image: docker.io/gitea/runner:5-dind
|
||||
restart: always
|
||||
privileged: true
|
||||
environment:
|
||||
CONFIG_FILE: /config.yaml
|
||||
GITEA_INSTANCE_URL: "${INSTANCE_URL}"
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: "${REGISTRATION_TOKEN}"
|
||||
GITEA_RUNNER_NAME: "${RUNNER_NAME}"
|
||||
GITEA_RUNNER_LABELS: "${RUNNER_LABELS}"
|
||||
GITEA_INSTANCE_URL: https://gitea.example.com
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: <token>
|
||||
volumes:
|
||||
- ./config.yaml:/config.yaml
|
||||
- ./data:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- runner-docker:/var/lib/docker
|
||||
|
||||
volumes:
|
||||
runner-docker:
|
||||
```
|
||||
|
||||
When Gitea runs in the same compose project, depend on its health check so the runner does not try to register before the instance answers:
|
||||
|
||||
```yaml
|
||||
depends_on:
|
||||
gitea:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
```
|
||||
|
||||
The rootless Docker-in-Docker variant needs a few extra options:
|
||||
The rootless flavour needs these additional settings:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -126,22 +80,21 @@ services:
|
||||
restart: always
|
||||
privileged: true
|
||||
security_opt:
|
||||
# for hosts running AppArmor (Ubuntu, Debian), whose default profile blocks
|
||||
# the user namespace changes the bundled daemon needs
|
||||
- apparmor=rootlesskit
|
||||
volumes:
|
||||
- ./data/runner:/data
|
||||
environment:
|
||||
- GITEA_INSTANCE_URL=<instance_url>
|
||||
- GITEA_RUNNER_REGISTRATION_TOKEN=<registration_token>
|
||||
- DOCKER_HOST=unix:///var/run/user/1000/docker.sock
|
||||
# slirp4netns gives significantly better network throughput than vpnkit
|
||||
- DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns
|
||||
- DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=65520
|
||||
GITEA_INSTANCE_URL: https://gitea.example.com
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: <token>
|
||||
DOCKERD_ROOTLESS_ROOTLESSKIT_NET: slirp4netns
|
||||
DOCKERD_ROOTLESS_ROOTLESSKIT_MTU: 65520
|
||||
volumes:
|
||||
- runner-data:/data
|
||||
|
||||
volumes:
|
||||
runner-data:
|
||||
```
|
||||
|
||||
## Cache from a dockerized runner
|
||||
- Set `security_opt` on AppArmor hosts such as Ubuntu and Debian. Docker's `docker-ce-rootless-extras` package provides the `rootlesskit` profile.
|
||||
- Use `slirp4netns` for better job network throughput than the default.
|
||||
- Make `/data` writable by UID 1000. Use a named volume or a bind-mounted host directory owned by that UID.
|
||||
|
||||
A runner in a container creates a separate network per job by default, so the address it detects for its own cache server is often unreachable from job containers and `actions/cache` fails with a connection timeout. Set `cache.host` and `cache.port` explicitly and publish that port, or put the job containers on a shared network — see [Caching](../cache.md#dockerized-runners).
|
||||
|
||||
More deployment examples live in the [`examples`](https://gitea.com/gitea/runner/src/branch/main/examples) directory of the runner repository.
|
||||
See the runner repository's [examples](https://gitea.com/gitea/runner/src/branch/main/examples) for more deployments.
|
||||
|
||||
@@ -4,46 +4,68 @@ sidebar_position: 3
|
||||
|
||||
# Install on Kubernetes
|
||||
|
||||
Ready-to-adapt manifests live in [`examples/kubernetes`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes) of the runner repository, and a Helm chart is maintained at [gitea/helm-actions](https://gitea.com/gitea/helm-actions).
|
||||
A runner in Kubernetes can run jobs in two ways:
|
||||
|
||||
## Choosing a manifest
|
||||
- **Job pods**: Each job runs in its own pod under the cluster's quotas and policies, without privileged containers. Docker actions and `docker://` steps are not supported.
|
||||
- **Docker-in-Docker**: Jobs run in a Docker daemon alongside the runner. All workflow features are supported. The daemon is privileged, so a job can break out of its container and access the node.
|
||||
|
||||
| Example | Shape | Docker daemon |
|
||||
| --- | --- | --- |
|
||||
| `dind-docker.yaml` | `Deployment` with a native sidecar (`initContainer` with `restartPolicy: Always`, needs Kubernetes 1.29+) | privileged `docker:dind` sidecar, socket shared through an `emptyDir` |
|
||||
| `statefulset-dind.yaml` | `StatefulSet` with `volumeClaimTemplates` | same as above |
|
||||
| `rootless-docker.yaml` | `Deployment` with a single container | bundled rootless daemon of the `dind-rootless` image, reached over `tcp://localhost:2376` with TLS |
|
||||
The manifests below are in the runner repository's [`examples/kubernetes`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes) directory. They read the registration token from the `runner-secret` Secret and store the `.runner` registration file in a volume at `/data`. This preserves registration when the pod restarts.
|
||||
|
||||
Prefer the `StatefulSet` variant when you scale past one replica: each pod then gets a stable identity and its own volume, so it keeps its `.runner` registration across restarts and reschedules instead of registering itself again as a new runner.
|
||||
## Job pods
|
||||
|
||||
## Two volumes, two purposes
|
||||
Deploy [`kubernetes-pods.yaml`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes/kubernetes-pods.yaml). It registers the runner with a `kubernetes` label:
|
||||
|
||||
- `/data` — the runner's working directory, holding the `.runner` registration file and optionally the config file.
|
||||
- the daemon's data root — `/var/lib/docker` for the `dind` sidecar, `/home/rootless/.local/share/docker` for `dind-rootless`. It holds the images pulled for jobs and is *not* under `/data`. Dropping it still works, but every recreated pod re-pulls all job images.
|
||||
|
||||
With the rootless image, both volumes must be writable by UID/GID 1000, which is what `securityContext.fsGroup: 1000` in the example is for.
|
||||
|
||||
## Registration token
|
||||
|
||||
The examples read the token from a `Secret`:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: GITEA_INSTANCE_URL
|
||||
value: http://gitea-http.gitea.svc.cluster.local:3000
|
||||
- name: GITEA_RUNNER_REGISTRATION_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: runner-secret
|
||||
key: token
|
||||
```text
|
||||
ubuntu-latest:kubernetes://docker.gitea.com/runner-images:ubuntu-latest
|
||||
```
|
||||
|
||||
The token stays valid for further registrations until it is reset, but each registration creates another runner entry. For pods that are recreated without their volume, use the instance-wide token configured on the Gitea side, and expect stale runner entries — or start an [ephemeral runner](../registration.md#ephemeral-runners) per job.
|
||||
The runner creates job pods in its own namespace using its service account. The manifest grants the permissions it needs:
|
||||
|
||||
## Privileges
|
||||
| Resource | Verbs |
|
||||
| --- | --- |
|
||||
| `pods` | `create`, `get`, `list`, `delete` |
|
||||
| `pods/exec` | `create`, `get` |
|
||||
| `pods/log` | `get` |
|
||||
| `secrets` | `create`, `delete` |
|
||||
|
||||
Docker-in-Docker needs `securityContext.privileged: true`, which lets a malicious job break out of the container. Weigh that against the alternatives:
|
||||
The cluster must run Kubernetes 1.30 or later. Job images need `sh`, `tar`, `tail`, and `env`. A runner outside the cluster uses the current context from the first file in `$KUBECONFIG`, or from `~/.kube/config` if `$KUBECONFIG` is unset.
|
||||
|
||||
- the rootless flavour, which reduces but does not remove the exposure;
|
||||
- pointing the basic flavour at a daemon outside the cluster;
|
||||
- keeping such runners on a dedicated node pool and only granting them to trusted repositories.
|
||||
Use pod templates to set resources, node selectors, image pull secrets, and other settings for job pods:
|
||||
|
||||
```yaml
|
||||
kubernetes:
|
||||
pod_template:
|
||||
spec:
|
||||
containers:
|
||||
- name: job # merged into the job container
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
- name: $services # merged into every service container
|
||||
resources:
|
||||
limits:
|
||||
memory: 1Gi
|
||||
pod_templates:
|
||||
gpu: # merged on top for jobs with runs-on: gpu
|
||||
spec:
|
||||
nodeSelector:
|
||||
nvidia.com/gpu.present: "true"
|
||||
```
|
||||
|
||||
Services share the job pod's network. Steps reach them by their service ID or `localhost`. Two services cannot use the same port. Only `--health-*` is supported in a service's `options`. Job pods do not receive a service account token unless the template sets `automountServiceAccountToken: true`.
|
||||
|
||||
## Docker-in-Docker
|
||||
|
||||
| Manifest | Deployment type |
|
||||
| --- | --- |
|
||||
| [`dind-docker.yaml`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes/dind-docker.yaml) | `Deployment` with a privileged `docker:dind` sidecar |
|
||||
| [`statefulset-dind.yaml`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes/statefulset-dind.yaml) | `StatefulSet` with a privileged `docker:dind` sidecar, for multiple replicas |
|
||||
| [`rootless-docker.yaml`](https://gitea.com/gitea/runner/src/branch/main/examples/kubernetes/rootless-docker.yaml) | `Deployment` with the `dind-rootless` image |
|
||||
|
||||
Use the `StatefulSet` for multiple replicas so each has its own registration volume. A [Helm chart](https://gitea.com/gitea/helm-actions) is also available.
|
||||
|
||||
The Docker daemon stores images pulled for jobs in `/var/lib/docker`, or `/home/rootless/.local/share/docker` in the rootless image. The manifests mount this directory on a volume so a new pod does not pull every image again.
|
||||
|
||||
## Shutdown
|
||||
|
||||
The manifests set `terminationGracePeriodSeconds` to give a pod three hours to stop. To let running jobs finish, set `runner.shutdown_timeout` a little lower than that grace period. Otherwise, the runner cancels running jobs when the pod stops.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Jobs
|
||||
|
||||
## Service containers
|
||||
|
||||
A job's `services` start before its steps. If a service defines a health check in its image or `options`, the runner waits until the service is healthy:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 5s
|
||||
--health-retries 10
|
||||
```
|
||||
|
||||
If a service is unhealthy, the runner fails the job and shows the service's container log. If a service never becomes healthy, the runner fails the job after `container.service_ready_timeout`, which defaults to `5m`.
|
||||
|
||||
Connect to a service from a step using its ID and listening port, for example `psql -h postgres -p 5432`.
|
||||
|
||||
A job with a `host` label does not start services. Set `container:` on the job if it needs services.
|
||||
|
||||
## Docker inside jobs
|
||||
|
||||
Container jobs can access the runner's Docker daemon, usually through a proxy. Containers started by the job can bind-mount the workspace using its path:
|
||||
|
||||
```bash
|
||||
docker run -v "$PWD:/src" alpine ls /src
|
||||
```
|
||||
|
||||
When the job ends, the proxy removes the containers, networks and volumes the job created, including `docker compose` services. Set `container.sweep: false` when jobs deploy services that should keep running.
|
||||
|
||||
Without the proxy, for example with a remote `DOCKER_HOST`, prefix workspace bind mounts with `GITEA_DOCKER_WORKSPACE`. This variable contains the workspace path as the Docker daemon sees it:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ${GITEA_DOCKER_WORKSPACE:-.}/data:/app/data
|
||||
```
|
||||
|
||||
To keep the Docker socket out of job containers, set `container.docker_host: "-"`.
|
||||
|
||||
## Volumes and privileges
|
||||
|
||||
Workflows can mount only the volumes and host paths allowed by `container.valid_volumes`. The list is empty by default:
|
||||
|
||||
```yaml
|
||||
container:
|
||||
valid_volumes:
|
||||
- data # the volume named data
|
||||
- /src/*.json # * stays within one path segment, ** crosses them
|
||||
- /etc/ssl/certs:ro # read-only mounts only
|
||||
```
|
||||
|
||||
Unless you enable `container.privileged`, the runner drops options in a workflow's `container.options` that could allow the job to escape the container. Examples include `--privileged`, `--cap-add`, `--device` and `--security-opt`. The runner writes a warning in the job log when it drops an option. The runner's own `container.options` always apply.
|
||||
|
||||
## Tool cache
|
||||
|
||||
Setup actions such as `actions/setup-go` install tools in `/opt/hostedtoolcache`. `runner.tool_cache_mode` determines how the runner stores this cache:
|
||||
|
||||
| Mode | Tool cache |
|
||||
| --- | --- |
|
||||
| `none` (default) | Tools included in the job image. Tools installed by a job are removed when it ends. |
|
||||
| `shared` | One volume reused by every job. Use only with `runner.capacity: 1`. Two jobs installing the same tool version at once corrupt the cache. |
|
||||
|
||||
With `none`, include tools in the job image at `/opt/hostedtoolcache/<tool>/<version>/<arch>`. Place an empty `<arch>.complete` file next to the directory. The `-full` variant of the [runner images](https://gitea.com/gitea/runner-images) includes its tools this way.
|
||||
|
||||
## Built-in checkout
|
||||
|
||||
`uses: builtin:checkout` checks out the repository like `actions/checkout`. It does not download an action or require Node in the job image. It runs `git` in the job. See [Requirements](index.md#requirements) and the inputs listed in [builtin-actions.md](https://gitea.com/gitea/runner/src/branch/main/docs/builtin-actions.md).
|
||||
|
||||
## Secrets
|
||||
|
||||
The runner masks secrets and `::add-mask::` values in job logs, job summaries, and the names of containers it creates. The runner does not send job outputs that contain a secret. A `needs.<job>.outputs.<name>` expression that reads such an output is empty.
|
||||
@@ -4,67 +4,38 @@ sidebar_position: 4
|
||||
|
||||
# Labels
|
||||
|
||||
Labels decide **which jobs a runner accepts** and **how it runs them**. A job's `runs-on` value is matched against the runner's label names; the first match wins and selects the execution environment for that job.
|
||||
A runner's labels determine which jobs it accepts and where it runs them. Gitea sends a job to a runner that has the labels specified in the job's `runs-on`. The runner uses the environment of the first matching entry in `runs-on`.
|
||||
|
||||
A label is written as:
|
||||
|
||||
```text
|
||||
<name>[:<schema>[:<args>]]
|
||||
```
|
||||
|
||||
| Part | Meaning |
|
||||
| Label | Job environment |
|
||||
| --- | --- |
|
||||
| `name` | the name a workflow refers to in `runs-on`, e.g. `ubuntu-latest` |
|
||||
| `schema` | either `docker` or `host`, defaulting to `host` when omitted |
|
||||
| `args` | only used by the `docker` schema: the image the job runs in |
|
||||
| `ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest` | Container using the specified image. |
|
||||
| `ubuntu-latest:kubernetes://docker.gitea.com/runner-images:ubuntu-latest` | Pod using the specified image. See [job pods](installation/kubernetes.md#job-pods). |
|
||||
| `macos:host`, or just `macos` | The runner's machine. |
|
||||
|
||||
Two schemas are supported:
|
||||
|
||||
- `docker://<image>` — the job runs in a container created from `<image>`:
|
||||
|
||||
```text
|
||||
ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest
|
||||
```
|
||||
|
||||
- `host` — the job's steps run directly on the machine, with the tools installed there:
|
||||
|
||||
```text
|
||||
macos:host
|
||||
```
|
||||
|
||||
So a runner registered with
|
||||
The label name is the part before the first `:docker`, `:kubernetes` or `:host`. Workflows use this name in `runs-on`. For example:
|
||||
|
||||
```text
|
||||
ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest,macos:host
|
||||
```
|
||||
|
||||
runs `runs-on: ubuntu-latest` jobs in the `runner-images:ubuntu-latest` container and `runs-on: macos` jobs directly on the host.
|
||||
With these labels, `runs-on: ubuntu-latest` jobs run in a container. Jobs with `runs-on: macos` run on the runner's machine.
|
||||
|
||||
Names may themselves contain a colon, for example `pool:e57e18d4-10d4-406f-93bf-60f127221bdd`; only `host` and `docker` are treated as schemas.
|
||||
A job's `container:` image replaces the label's image. The job runs in a container even with a `host` label.
|
||||
|
||||
If a job's `runs-on` matches none of the runner's labels, the job still runs, in the default `docker.gitea.com/runner-images:ubuntu-latest` image. Images maintained for this purpose are listed at [gitea/runner-images](https://gitea.com/gitea/runner-images); community images such as the [act images](https://github.com/nektos/act/blob/master/IMAGES.md) work too.
|
||||
A job whose `runs-on` matches none of the runner's labels uses `runner.default_image`, which defaults to `docker.gitea.com/runner-images:ubuntu-latest`. It runs in a container, as a pod on runners with `kubernetes` but no `docker` labels, or on the host when no Docker daemon is reachable.
|
||||
|
||||
:::note
|
||||
A runner that only exposes `host` labels still needs access to a Docker daemon whenever a job uses a `docker://` action or a service container. `host` labels only change where the job's own steps run.
|
||||
:::
|
||||
## Changing labels
|
||||
|
||||
## Registration versus config labels
|
||||
Labels are set during registration and stored in the registration file. To change them, set them in the configuration file or on the command line, then restart the runner. The runner reports its labels to Gitea at startup:
|
||||
|
||||
Labels are chosen at registration time (`--labels`, or the interactive prompt) and stored in the registration file. Afterwards they can be changed without re-registering, and the most explicit source wins:
|
||||
|
||||
```text
|
||||
--labels / GITEA_RUNNER_LABELS > runner.labels in the config file > labels in the .runner file
|
||||
```bash
|
||||
gitea-runner config set runner.labels 'ubuntu-latest:docker://node:24' 'macos:host'
|
||||
```
|
||||
|
||||
- during `register`, `runner.labels` from the config file takes precedence and the `--labels` flag is ignored;
|
||||
- `daemon --labels` (which defaults to `GITEA_RUNNER_LABELS`) overrides the labels of an already registered runner;
|
||||
- whenever the resulting labels differ from those in the registration file, they are written back to it and re-declared to the instance on startup;
|
||||
- labels that fail to parse are skipped with a warning instead of stopping the runner.
|
||||
|
||||
Labels can also be edited in the Gitea UI under the runner's settings.
|
||||
`daemon --labels` or the `GITEA_RUNNER_LABELS` environment variable takes precedence over `runner.labels`. The `runner.labels` setting takes precedence over labels in the registration file.
|
||||
|
||||
## Choosing images
|
||||
|
||||
- Pick an image that already contains the tools your workflows expect. The default images are small; a job that installs a toolchain on every run is usually better served by a purpose-built image.
|
||||
- Pin images by tag or digest for reproducible jobs. An image pinned by digest is never re-pulled, even with `container.force_pull` enabled.
|
||||
- Use distinct names such as `linux_amd64:host` or `windows:host` for host labels, so a workflow written for GitHub's `ubuntu-latest` does not accidentally run unsandboxed on your machine.
|
||||
- Use the [runner images](https://gitea.com/gitea/runner-images) for tools that common workflows need. To avoid installing a toolchain on every run, choose an image that already includes it.
|
||||
- Pin images by tag or digest for reproducible jobs.
|
||||
- Give host labels distinct names such as `macos-arm64` to prevent workflows written for GitHub's `ubuntu-latest` from running directly on your machine without a sandbox.
|
||||
|
||||
@@ -1,93 +1,81 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Monitoring and health
|
||||
# Monitoring
|
||||
|
||||
## Prometheus metrics
|
||||
## Metrics
|
||||
|
||||
```yaml
|
||||
metrics:
|
||||
enabled: true
|
||||
addr: "127.0.0.1:9101"
|
||||
readiness_grace: 30s
|
||||
```
|
||||
|
||||
With `metrics.enabled`, the runner serves three endpoints on `metrics.addr`:
|
||||
With metrics enabled, the runner serves these endpoints:
|
||||
|
||||
| Endpoint | Purpose |
|
||||
| --- | --- |
|
||||
| `/metrics` | Prometheus exposition of the runner's own metrics |
|
||||
| `/healthz` | liveness: the process is up |
|
||||
| `/readyz` | task admission: `503` while a [health check](#local-health-checks) reports the machine as unavailable, once polling has been failing for longer than `readiness_grace`, or after the runner has been deleted on the instance |
|
||||
| `/metrics` | Prometheus metrics |
|
||||
| `/healthz` | Liveness, always `200` while the process runs |
|
||||
| `/readyz` | Readiness, `503` when a [health check](#health-checks) fails, the runner cannot reach Gitea for longer than `metrics.readiness_grace` (`30s`), or the runner is shutting down |
|
||||
|
||||
There is **no authentication** on this listener. The default address binds to localhost only; expose it more widely (`":9101"`) only behind a firewall or a scrape-only network.
|
||||
The listener has no authentication. If you expose it beyond localhost, for example with `addr: ":9101"`, protect it with a firewall.
|
||||
|
||||
All series are prefixed with `gitea_runner_`, among them:
|
||||
The runner exports these metrics in addition to the standard Go and process metrics:
|
||||
|
||||
| Metric | Meaning |
|
||||
| --- | --- |
|
||||
| `gitea_runner_info` | always `1`, with the version and runner name as labels |
|
||||
| `gitea_runner_uptime_seconds` | seconds since the daemon started |
|
||||
| `gitea_runner_capacity` / `gitea_runner_job_running` / `gitea_runner_job_capacity_utilization_ratio` | configured capacity, jobs in flight, and their ratio |
|
||||
| `gitea_runner_job_total` | jobs by result (`success`, `failure`, `cancelled`, `skipped`, `unknown`) |
|
||||
| `gitea_runner_job_duration_seconds` | job duration histogram |
|
||||
| `gitea_runner_poll_fetch_total` / `gitea_runner_poll_fetch_duration_seconds` | task fetches by result (`task`, `empty`, `error`) and their latency |
|
||||
| `gitea_runner_poll_backoff_seconds` | last polling backoff interval |
|
||||
| `gitea_runner_report_log_total` / `gitea_runner_report_state_total` | log and state reports by result |
|
||||
| `gitea_runner_report_log_buffer_rows` | log rows buffered but not yet sent |
|
||||
| `gitea_runner_client_errors_total` | RPC errors by method |
|
||||
| `gitea_runner_state` | `1` for the current `state`: `busy`, `idle` or `unavailable` |
|
||||
| `gitea_runner_job_running`, `gitea_runner_capacity` | Running jobs and configured capacity |
|
||||
| `gitea_runner_job_capacity_utilization_ratio` | Running jobs divided by capacity |
|
||||
| `gitea_runner_job_total` | Finished jobs by `status`: `success`, `failure`, `cancelled`, `skipped`, `timeout` or `unknown` |
|
||||
| `gitea_runner_job_duration_seconds` | Job duration histogram |
|
||||
| `gitea_runner_poll_fetch_total` | Job fetches by `result`: `task`, `empty` or `error` |
|
||||
| `gitea_runner_client_errors_total` | Failed requests to Gitea by `method` and `code` |
|
||||
|
||||
Useful things to alert on: `gitea_runner_poll_fetch_total{result="error"}` rising (the instance is unreachable or the runner was deleted), a `capacity_utilization_ratio` pinned at `1` (the pool is too small), and a growing `report_log_buffer_rows` (log delivery is falling behind).
|
||||
Consider alerts for `gitea_runner_state{state="unavailable"}`, a rising `gitea_runner_poll_fetch_total{result="error"}`, and a utilization ratio that stays at `1`, which means jobs may be waiting for a free slot.
|
||||
|
||||
## OpenTelemetry tracing
|
||||
## OpenTelemetry
|
||||
|
||||
Setting `OTEL_EXPORTER_OTLP_ENDPOINT` in the runner's environment sends a trace of every job, with a span per step, to an OTLP collector over `http/protobuf`:
|
||||
Set `OTEL_EXPORTER_OTLP_ENDPOINT` in the runner's environment to send traces and the metrics above to an OpenTelemetry collector. Each job has a trace with a span for each step:
|
||||
|
||||
```sh
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
||||
```
|
||||
|
||||
Jobs receive `TRACEPARENT`, so instrumented tools in them join the job's trace. See [docs/telemetry.md](https://gitea.com/gitea/runner/src/branch/main/docs/telemetry.md) for headers, sampling and the security notes.
|
||||
Jobs receive `TRACEPARENT`, so instrumented tools can add spans to the job's trace. See [telemetry.md](https://gitea.com/gitea/runner/src/branch/main/docs/telemetry.md) for all variables and security notes.
|
||||
|
||||
## Local health checks
|
||||
## Health checks
|
||||
|
||||
Health checks let a runner take itself out of rotation when the machine it runs on is not fit for work — most commonly when the disk is full.
|
||||
Health checks stop a runner from accepting new jobs while its machine has a problem, such as a full disk:
|
||||
|
||||
```yaml
|
||||
health_check:
|
||||
enabled: false
|
||||
enabled: true
|
||||
min_free_disk_space_mb: 1024
|
||||
script: ''
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
script: /usr/local/bin/check-runner.sh
|
||||
```
|
||||
|
||||
- while a check fails, the runner stops fetching **new** tasks; jobs already running are unaffected and finish normally;
|
||||
- no check runs while a job is active — the last result is reused until the runner is idle again;
|
||||
- `min_free_disk_space_mb` is measured on the filesystem holding the runner's workspaces, and defaults to 1024 MiB when omitted or zero;
|
||||
- `script` is any executable. A non-zero exit, a timeout, or a failure to start marks the runner unavailable. Its result is cached for `interval` and it is killed after `timeout`;
|
||||
- recovery is automatic and logged (`runner local health recovered, resuming task polling`), and the state is reflected by `/readyz`.
|
||||
- The disk check measures free space on the filesystem containing `host.workdir_parent`, or `container.workdir_parent` when `container.bind_workdir` is enabled.
|
||||
- `script` is optional. The runner becomes unavailable if the script exits with a non-zero status, fails to start, or runs longer than `health_check.timeout` (`10s`). The runner reuses the script's result for `health_check.interval` (`30s`).
|
||||
- Checks only run while the runner is idle. Running jobs are never interrupted.
|
||||
- The runner resumes accepting jobs once the checks pass again.
|
||||
|
||||
## Logs
|
||||
|
||||
The runner logs to stderr; `log.level` controls the verbosity, with `debug` and `trace` adding `file:line` to each line. Under systemd the log ends up in the journal (`journalctl -u gitea-runner`), in Docker in `docker logs`.
|
||||
The runner writes logs to stderr. View them in the systemd journal or with `docker logs` for a runner container. Set `log.level` to control verbosity, from `trace` to `error`.
|
||||
|
||||
The runner log is not the job log: step output is streamed to Gitea and is tuned with the `runner.log_report_*` settings, while things like [post-task script](hooks/post-task-script.md) output only ever appear in the runner log.
|
||||
The runner streams step output to Gitea without including it in its own log. To also keep a local copy of every job log, set a directory:
|
||||
|
||||
```yaml
|
||||
log:
|
||||
job:
|
||||
dir: /var/log/gitea-runner
|
||||
```
|
||||
|
||||
The runner writes each job log to `<start time>-task-<id>.log` in this directory and masks secrets. It keeps the files for `log.job.retention` (`168h`). Only the user running the runner can read them.
|
||||
|
||||
## Reporting a problem
|
||||
|
||||
`gitea-runner bug-report` prints the version, Go version, OS/architecture and CPU count — paste its output into an issue at [gitea/runner](https://gitea.com/gitea/runner/issues):
|
||||
|
||||
```bash
|
||||
gitea-runner bug-report
|
||||
```
|
||||
|
||||
```text
|
||||
Runner version: 5.1.1
|
||||
Go version: go1.26.5
|
||||
OS/Arch: linux/amd64
|
||||
NumCPU: 8
|
||||
```
|
||||
|
||||
To reproduce a workflow locally, without a Gitea instance and without touching the runner's registration, use `gitea-runner exec` — see the [command line reference](reference/cli.md#exec).
|
||||
`gitea-runner bug-report` prints the runner version, Go version, platform and CPU count. Include its output when you open an issue at [gitea/runner](https://gitea.com/gitea/runner/issues).
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# Proxies
|
||||
|
||||
The runner reads the usual proxy variables from its own environment and passes them on to every job:
|
||||
Set proxy variables in the runner's environment. Use `Environment=` in a systemd unit, `docker run -e`, or `env:` in Kubernetes:
|
||||
|
||||
```sh
|
||||
http_proxy=http://proxy.example:3128
|
||||
@@ -12,35 +12,31 @@ https_proxy=http://proxy.example:3128
|
||||
no_proxy=gitea.internal,.example.local
|
||||
```
|
||||
|
||||
Set them where the process is started — `Environment=` in a systemd unit, `docker run -e`, or `env:` in Kubernetes. They are used for the runner's own requests and are given to jobs in both lower and upper case.
|
||||
The runner uses these variables for its own requests. It passes them to every job and service container in lowercase and uppercase. Dockerfile actions receive them as build arguments.
|
||||
|
||||
## What is exempted automatically
|
||||
The runner adds the following to `no_proxy` so jobs reach them directly:
|
||||
|
||||
These are added to `no_proxy` for jobs, so they are always reached directly:
|
||||
|
||||
- the cache server
|
||||
- The runner's cache server
|
||||
- `localhost`, `127.0.0.1` and `::1`
|
||||
- the job's service containers
|
||||
- the Docker daemon, when it is reached over `tcp://`
|
||||
- The job's service containers
|
||||
- The Docker daemon, when reached over `tcp://`
|
||||
|
||||
The Gitea instance is **not** added. Add it to `no_proxy` yourself if it should be reached directly.
|
||||
Add Gitea to `no_proxy` if jobs should reach it directly. The runner does not add it automatically.
|
||||
|
||||
## Overriding per job or per runner
|
||||
## Changing the proxy for jobs
|
||||
|
||||
| Scope | Where to set it |
|
||||
| --- | --- |
|
||||
| one step | the step's `env:` |
|
||||
| one job | the job's `container.env` |
|
||||
| the whole runner | `runner.envs` in the config; a `no_proxy` set there is added to the list above instead of replacing it |
|
||||
| One step | Set the step's `env:`. |
|
||||
| The rest of a job | Write lowercase and uppercase variable names to `$GITHUB_ENV`. |
|
||||
| Every job | Set `runner.envs`. Values in `no_proxy` are added to the list above. |
|
||||
|
||||
Setting proxy variables at workflow or job level (outside `container.env`) has no effect.
|
||||
Proxy values set at the workflow or job level, or in `container.env`, cannot replace the runner's proxy values.
|
||||
|
||||
## The Docker daemon needs its own setting
|
||||
## Docker daemon
|
||||
|
||||
Images are pulled by the daemon, not by the runner, so the daemon needs its own proxy configuration. In the `dind` images the daemon shares the container's environment and picks the variables up; for any other daemon see [the Docker documentation](https://docs.docker.com/engine/daemon/proxy/). The runner logs a warning at startup when it has a proxy configured and the daemon does not.
|
||||
The Docker daemon pulls images and needs its own proxy settings. See [the Docker documentation](https://docs.docker.com/engine/daemon/proxy/). The Docker daemon bundled with the `dind` images reads the runner's proxy variables. The runner warns at startup if it has a proxy but the Docker daemon does not.
|
||||
|
||||
Dockerfile actions are built with these variables passed as build arguments, so their `RUN` steps can reach the network.
|
||||
## Credentials
|
||||
|
||||
## Credentials in proxy URLs
|
||||
|
||||
A password inside a proxy URL is masked in job logs, but any step can still read it: the step is given the proxy URL in its environment. Prefer a proxy that does not need credentials, or one that authenticates by source address.
|
||||
The runner masks passwords in proxy URLs in job logs, but every step can read them from its environment. Prefer a proxy that authenticates by source address.
|
||||
|
||||
@@ -38,7 +38,7 @@ Use "gitea-runner [command] --help" for more information about a command.
|
||||
|
||||
## register
|
||||
|
||||
Registers the runner against a Gitea instance and writes the registration file. Interactive unless `--no-interactive` is given; the token can also come from `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable. See [Registering a runner](../registration.md).
|
||||
Registers the runner with a Gitea instance and writes the registration file. The token comes from `--token`, `--token-file` or the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable, and the command asks for the other settings unless `--no-interactive` is given. See [Registration](../registration.md).
|
||||
|
||||
```text
|
||||
Register a runner to the server
|
||||
@@ -135,7 +135,7 @@ Global Flags:
|
||||
|
||||
## cache-server
|
||||
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys; every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
Runs only the cache server, so several runners can share one cache. `--dir`, `--host` and `--port` override the matching `cache.*` keys. Every other setting, `cache.external_secret` included, has to come from the config file. See [Caching](../cache.md#sharing-a-cache-between-runners).
|
||||
|
||||
```text
|
||||
Start a cache server for the cache action
|
||||
@@ -153,18 +153,137 @@ Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
## generate-config
|
||||
## config
|
||||
|
||||
Prints the commented example configuration on stdout, which is the starting point for a config file: `gitea-runner generate-config > config.yaml`.
|
||||
Writes, reads and edits config files. `config init` writes a minimal `config.yaml`, `config set`, `add` and `remove` change it in place, and `config generate` prints every option. See [Configuration](../configuration.md).
|
||||
|
||||
```text
|
||||
Generate, read and edit config files
|
||||
|
||||
Usage:
|
||||
gitea-runner config [flags]
|
||||
gitea-runner config [command]
|
||||
|
||||
Available Commands:
|
||||
add Append values to a list config key
|
||||
generate Print the example config, which documents every option
|
||||
get Print the value of a config key
|
||||
init Write a minimal config file
|
||||
remove Remove values from a list config key
|
||||
runner-file Print the registration file path used by the runner
|
||||
set Set the value of a config key
|
||||
|
||||
Flags:
|
||||
-h, --help help for config
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
Use "gitea-runner config [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
### config add
|
||||
|
||||
```text
|
||||
Append values to a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config add <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for add
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config generate
|
||||
|
||||
```text
|
||||
Print the example config, which documents every option
|
||||
|
||||
Usage:
|
||||
gitea-runner generate-config [flags]
|
||||
gitea-runner config generate [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for generate-config
|
||||
-h, --help help for generate
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config get
|
||||
|
||||
```text
|
||||
Print the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config get <key> [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for get
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config init
|
||||
|
||||
```text
|
||||
Write a minimal config file, leaving every option at its default.
|
||||
Without --config it writes config.yaml in the working directory.
|
||||
|
||||
Usage:
|
||||
gitea-runner config init [flags]
|
||||
|
||||
Flags:
|
||||
-f, --force overwrite an existing config file
|
||||
-h, --help help for init
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config remove
|
||||
|
||||
```text
|
||||
Remove values from a list config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config remove <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for remove
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config runner-file
|
||||
|
||||
```text
|
||||
Print the registration file path used by the runner
|
||||
|
||||
Usage:
|
||||
gitea-runner config runner-file [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for runner-file
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
```
|
||||
|
||||
### config set
|
||||
|
||||
```text
|
||||
Set the value of a config key
|
||||
|
||||
Usage:
|
||||
gitea-runner config set <key> <value>... [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for set
|
||||
|
||||
Global Flags:
|
||||
-c, --config config Config file path. config subcommands fall back to config.yaml in the working directory or next to the executable
|
||||
|
||||
@@ -7,10 +7,8 @@ description: The commented example configuration of the runner, generated from t
|
||||
|
||||
{/* Generated by update_runner_docs.sh from the gitea/runner sources, do not edit. */}
|
||||
|
||||
This is the output of `gitea-runner generate-config`. It is safe to use unmodified,
|
||||
and it is the authoritative list of every option the runner understands. See
|
||||
[Configuration](../configuration.md) for what the options mean and how the file is
|
||||
loaded.
|
||||
Every option the runner understands, with its default, as printed by `gitea-runner config generate`.
|
||||
See [Configuration](../configuration.md) for how to write and load a config file.
|
||||
|
||||
```yaml
|
||||
# Every option with its default value, all commented out. Read this file, do not copy it.
|
||||
|
||||
@@ -2,84 +2,54 @@
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Registering a runner
|
||||
# Registration
|
||||
|
||||
A runner has to be registered before it can pick up jobs: registration is what tells the runner where to fetch jobs from, and what gives the Gitea instance a stable identity for the runner.
|
||||
Register a runner once with a Gitea instance to get its identity and credentials.
|
||||
|
||||
## Obtain a registration token
|
||||
## Registration token
|
||||
|
||||
Registration tokens are issued by the Gitea instance and can be scoped to the whole instance, an organization/user, or a single repository. See [Actions runners](/usage/actions/runner) for where to find them in the UI and via the API.
|
||||
Gitea issues registration tokens for the whole instance, an organization, a user, or a single repository. A runner accepts jobs within the token's scope. To find a token, see [Gitea Runner](/usage/actions/runner). A token can register any number of runners until it is reset.
|
||||
|
||||
One token can register any number of runners and stays valid until it is reset in the UI or through the API. Instance administrators can also hand Gitea a fixed token with `GITEA_RUNNER_REGISTRATION_TOKEN` / `GITEA_RUNNER_REGISTRATION_TOKEN_FILE` at startup, which is what makes disposable runners practical.
|
||||
|
||||
## Interactive registration
|
||||
## Registering
|
||||
|
||||
```bash
|
||||
gitea-runner register
|
||||
# or with a config file
|
||||
gitea-runner -c config.yaml register
|
||||
gitea-runner register --instance https://gitea.example.com --token <token>
|
||||
```
|
||||
|
||||
The runner asks for:
|
||||
|
||||
- the instance URL, e.g. `https://gitea.com/` or `http://192.168.8.8:3000/` — use the instance's `ROOT_URL`, not `localhost`, when Gitea and the runner are in different containers or hosts;
|
||||
- the registration token;
|
||||
- the runner name, defaulting to the hostname;
|
||||
- the [labels](labels.md), defaulting to the built-in list, or to `runner.labels` when the config file sets it.
|
||||
|
||||
## Non-interactive registration
|
||||
The runner asks for its name. It also asks for its [labels](labels.md) unless you set `runner.labels`. To skip the prompts, use `--no-interactive` and pass the values as flags:
|
||||
|
||||
```bash
|
||||
gitea-runner register --no-interactive \
|
||||
--instance <instance_url> \
|
||||
--token <registration_token> \
|
||||
--name <runner_name> \
|
||||
--labels <runner_labels>
|
||||
--instance https://gitea.example.com \
|
||||
--token <token> \
|
||||
--name my-runner \
|
||||
--labels ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest
|
||||
```
|
||||
|
||||
The token can be kept off the command line, where it would show up in the process list and in shell history:
|
||||
Set `--instance` to the instance's `ROOT_URL`. `localhost` does not work from job containers.
|
||||
|
||||
- `--token-file <path>` reads it from a file, e.g. a Docker or Kubernetes secret;
|
||||
- the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable is used when neither flag is given.
|
||||
To keep the token out of shell history and the process list, pass it with `--token-file <path>` or through the `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable.
|
||||
|
||||
## The registration file
|
||||
|
||||
A successful registration writes a `.runner` file (`runner.file` in the config) into the current working directory. It holds the runner's identity and its API credentials, so:
|
||||
Registration writes the runner's credentials to `.runner` in the working directory, or to the path in `runner.file`:
|
||||
|
||||
- do not edit it by hand, and do not copy it to a second machine;
|
||||
- back it up or put it on a persistent volume, otherwise a recreated runner registers as a *new* runner and leaves a stale entry behind — and fails outright if the token has been reset in the meantime;
|
||||
- if it is lost or corrupted, delete it and register again.
|
||||
|
||||
Each runner process needs its own registration file. Two processes sharing one file are indistinguishable to Gitea and cancel each other's jobs, so the runner takes an advisory lock on `<runner.file>.lock` and refuses to start when another process already holds it. The lock is released by the operating system when the process exits, including after a crash. When the lock cannot be created at all — for example on a read-only mount — the runner logs a warning and starts without the guard.
|
||||
- Keep it on persistent storage. If the file is lost, register again as a new runner.
|
||||
- Give each runner process its own registration file. A second process using the same file refuses to start.
|
||||
- Treat it as a secret.
|
||||
|
||||
## Ephemeral runners
|
||||
|
||||
An ephemeral runner accepts exactly one job and then exits. Once a job has been assigned, its credentials are revoked, so it cannot poll for more work before the job's untrusted code runs; it can still report progress until the job finishes.
|
||||
|
||||
This is how organization-wide or instance-wide runners can be offered without trusting every repository that may use them, provided each runner is a fresh VM or container.
|
||||
An ephemeral runner accepts exactly one job, then exits. Its credentials are revoked as soon as the job is assigned, so the job cannot use them to accept more work. Start each ephemeral runner in a fresh VM or container when running jobs from repositories you do not fully trust.
|
||||
|
||||
```bash
|
||||
gitea-runner register --ephemeral
|
||||
gitea-runner register --no-interactive --ephemeral --instance <instance_url> --token <registration_token>
|
||||
gitea-runner register --ephemeral --instance https://gitea.example.com --token <token>
|
||||
```
|
||||
|
||||
With the Docker images, set `GITEA_RUNNER_EPHEMERAL=1` instead; no `/data` volume is needed, since the credentials are single-use:
|
||||
With the Docker images, set `GITEA_RUNNER_EPHEMERAL=1`. To start a runner for each job, listen for Gitea's `workflow_job` [webhook](/usage/repository/webhooks), which fires when a job is queued.
|
||||
|
||||
```bash
|
||||
docker run -d --name my_runner \
|
||||
-e GITEA_INSTANCE_URL=<instance_url> \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN=<registration_token> \
|
||||
-e GITEA_RUNNER_EPHEMERAL=1 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
docker.io/gitea/runner:5
|
||||
```
|
||||
`gitea-runner daemon --once` also exits after one job, but its credentials stay valid.
|
||||
|
||||
Because a fresh registration is required for every job, ephemeral runners are usually started on demand from the `workflow_job` webhook, which fires when a job is queued.
|
||||
## Removing a runner
|
||||
|
||||
`--ephemeral` is stricter than `daemon --once`: `--once` also stops after one job, but its credentials stay valid for as long as the runner is registered.
|
||||
|
||||
## Re-registering and unregistering
|
||||
|
||||
Running `register` again in a directory that already has a registration file asks whether to overwrite it. To retire a runner, delete it in the Gitea UI (or via the API) and remove its registration file; the daemon shuts itself down once the server no longer knows it.
|
||||
|
||||
Changing labels does not require re-registration — see [Labels](labels.md#registration-versus-config-labels).
|
||||
Delete the runner in Gitea's runner settings, then delete its registration file. The runner exits when it detects that Gitea has removed its registration.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# Upgrading
|
||||
|
||||
A runner upgrade is a binary or image replacement: stop the daemon, swap it, start it again. The registration file stays valid across versions, so a runner keeps its identity and does not have to be registered again.
|
||||
Stop the runner, replace the binary or image, and start it again. The registration file stays valid, so you do not need to register the runner again.
|
||||
|
||||
```bash
|
||||
sudo systemctl stop gitea-runner
|
||||
@@ -12,77 +12,15 @@ sudo install -m 0755 gitea-runner-<version>-linux-amd64 /usr/local/bin/gitea-run
|
||||
sudo systemctl start gitea-runner
|
||||
```
|
||||
|
||||
With `runner.shutdown_timeout` set, `stop` lets the jobs in flight finish first; without it, they are cancelled and Gitea reschedules them.
|
||||
Stopping the runner cancels running jobs unless `runner.shutdown_timeout` gives them time to finish. The runner logs a warning for unknown configuration keys and ignores them. Run `gitea-runner config generate` to list all configuration options.
|
||||
|
||||
Config files are read leniently: keys the running version does not know are reported as a warning and ignored, so one file can be shared by runners of different versions. Compare your file with `gitea-runner generate-config` after an upgrade to pick up new options.
|
||||
## Breaking changes in 5.0
|
||||
|
||||
## 5.0
|
||||
- **Git 2.34.1 or later is required** on the runner and in job images that use `builtin:checkout`.
|
||||
- **`builtin:checkout` works like `actions/checkout`.** It removes untracked and ignored files unless `clean: false` is set. It fails if the triggering tag moved after the workflow started.
|
||||
- **Configuration values expand `${NAME}`** from the runner's environment. The configuration fails to load if `NAME` is unset. Write `$${NAME}` for a literal `${NAME}`, for example in a shell command in a Kubernetes `pod_template`.
|
||||
- **Jobs require `runs-on`.** A job without `runs-on` fails, as it does on GitHub. Jobs that call a reusable workflow are exempt.
|
||||
- **OpenTelemetry metrics follow the semantic conventions**, which changed their names, units and attributes. See [telemetry.md](https://gitea.com/gitea/runner/src/branch/main/docs/telemetry.md#metrics). On `/metrics`, `gitea_runner_client_errors_total` gained a `code` label, and `gitea_runner_job_total` counts jobs stopped by `runner.timeout` as `timeout`.
|
||||
- **Unprivileged runners drop more workflow options.** Unless `container.privileged` is set, `--log-driver`, `--log-opt`, `--oom-score-adj` and `--oom-kill-disable` are removed from a job's `container.options` with a warning.
|
||||
|
||||
### Breaking
|
||||
|
||||
- **Git 2.34.1 or newer is required.** Actions and reusable workflows are downloaded with Git, so the runner needs `git` on its `PATH`. `builtin:checkout` runs Git inside the job too, so job images need Git, and the job must reach Gitea and trust its certificate. The official runner images include Git.
|
||||
- **`builtin:checkout` works like `actions/checkout`.** It removes untracked and ignored files from the checkout directory unless `clean: false` is set, and fails when the triggering tag was moved after the workflow started. In exchange it gains SSH keys, LFS, submodules, sparse checkout, partial clones, the `fetch-tags`, `clean`, `show-progress` and `set-safe-directory` inputs, and the `ref` and `commit` outputs.
|
||||
- **Config values expand `${NAME}`.** A value containing `${NAME}` reads that variable from the runner's environment, and the config fails to load when it is unset. Write `$${NAME}` to keep a literal `${NAME}`, for example in a shell command inside a Kubernetes `pod_template`.
|
||||
- **Jobs require `runs-on`.** A job without `runs-on`, or with an empty one, fails instead of running in `runner.default_image`, like on GitHub. Jobs that call a reusable workflow are exempt.
|
||||
- **Metrics follow the OpenTelemetry semantic conventions.** OTLP metric names, units, types and attributes change, see [docs/telemetry.md](https://gitea.com/gitea/runner/src/branch/main/docs/telemetry.md#metrics). On `/metrics`, `gitea_runner_client_errors_total` gains a `code` label, and `gitea_runner_job_total` counts jobs stopped by `runner.timeout` as `timeout`.
|
||||
- **Unprivileged runners ignore log and OOM options from workflows.** Unless `container.privileged` is set, `--log-driver`, `--log-opt`, `--oom-score-adj` and `--oom-kill-disable` are dropped from a job's `container.options` with a warning.
|
||||
|
||||
### Also new
|
||||
|
||||
- Mutual TLS to Gitea (`runner.client_cert_file`, `runner.client_key_file`) and `runner.extra_headers` for headers a reverse proxy in front of Gitea requires.
|
||||
- SHA-256 repositories for actions, reusable workflows and `builtin:checkout`.
|
||||
- `:ro` entries in `container.valid_volumes`, which only allow read-only mounts, and `container.sweep: false` to keep services that jobs deploy to the runner's Docker daemon.
|
||||
- The `gitea_runner_state` metric, reporting whether the runner is busy, idle or unavailable.
|
||||
- From `5.1`: action `pre` and `post` steps shown as their own steps on Gitea versions that support it, startup retried while Gitea is unreachable, and `runner.log_report_level` to set the level of runner messages in the job log independently of `log.level`.
|
||||
|
||||
## 4.0
|
||||
|
||||
### Breaking
|
||||
|
||||
- **Jobs reach the cache through their runner.** With `cache.external_server` set, jobs send their cache requests to their runner, which forwards them; only the runner has to reach the external server, and that server no longer has to reach Gitea. Jobs that cannot reach their runner, such as on a remote `DOCKER_HOST`, need `cache.host` and `cache.port` set to an address they can reach.
|
||||
- **`container.network: bridge` cuts jobs off from a containerized runner.** Jobs on the default `bridge` network cannot reach a runner container outside it, so their cache and artifact uploads fail. Leave `container.network` empty or use a user-defined network.
|
||||
- **`*` in `container.valid_volumes` no longer matches across `/`.** A host pattern that relied on `*` matching nested paths needs `**`, for example `/data/**` instead of `/data/*`.
|
||||
|
||||
### Also new
|
||||
|
||||
- `builtin:checkout`, which needs neither a download nor Node in the job image, see [docs/builtin-actions.md](https://gitea.com/gitea/runner/src/branch/main/docs/builtin-actions.md), and the `self:` prefix for actions hosted on the runner's own instance.
|
||||
- S3-compatible storage as a cache backend (`cache.s3` in the [example configuration](reference/config-example.md)), shared between runners without a cache server.
|
||||
- [OpenTelemetry tracing](monitoring.md#opentelemetry-tracing) of jobs and steps, and from `4.1` the Prometheus metrics exported through OpenTelemetry as well.
|
||||
- A Kubernetes backend that runs jobs as pods (`4.1`), see [docs/kubernetes.md](https://gitea.com/gitea/runner/src/branch/main/docs/kubernetes.md).
|
||||
- A runner container on the jobs' Docker daemon joins every job network, so jobs reach its cache without `cache.host`, and `--umask` is accepted in `container.options`.
|
||||
|
||||
## 3.0
|
||||
|
||||
### Breaking
|
||||
|
||||
- **Container options from workflows are filtered.** While `container.privileged` is disabled, options in a job's `container.options` that would escape the container are stripped with a warning: `--pid`, `--ipc`, `--uts`, `--cgroupns`, `--userns`, `--cap-add`, `--security-opt`, `--device`, `--device-cgroup-rule`, `--gpus`, `--volumes-from`, `--runtime`, `--cgroup-parent`, `--sysctl`. Workflows that relied on them need a runner with privileged mode enabled.
|
||||
- **One process per registration file.** The daemon takes an advisory lock on `<runner.file>.lock` and refuses to start when another process already uses that file. Setups that started several runners from one directory must give each its own `runner.file` (or its own working directory).
|
||||
- **Cache service v2 is served and enabled by default.** `actions/[email protected]` and later, and the stock `actions/upload-artifact` / `download-artifact` from `v4.4.0` on, reach it through a patch the runner applies to the action's own bundle. Jobs are pointed at the runner's cache server as their results service, which then forwards artifact calls to Gitea. Set `cache.v2: false` to keep to v1.
|
||||
|
||||
### Also new
|
||||
|
||||
- [Job hooks](hooks/job-hooks.md) (`runner.hooks.job_started` / `job_completed`) running inside the job environment.
|
||||
- [Proxy variables](proxy.md) propagated to jobs, service containers and Dockerfile action builds.
|
||||
- Secrets are masked in the log even when a job prints them in an encoded form.
|
||||
- The tool cache can be relocated, and runner-managed paths can be mounted over, via `container.options`.
|
||||
|
||||
## 2.0
|
||||
|
||||
### Breaking
|
||||
|
||||
- **`DOCKER_USERNAME` / `DOCKER_PASSWORD` are no longer implicit pull credentials.** They used to be attached to every image pull, which sent private-registry credentials to Docker Hub for public images. They are ordinary secrets now. Migrate to:
|
||||
- `container.credentials` (and service `credentials`) in the workflow for private images;
|
||||
- a `docker login` performed on the runner host, or a [job hook](hooks/job-hooks.md), for private `uses: docker://...` actions.
|
||||
- **`container.force_pull` now defaults to `false`** in the generated example config, so images already present are reused unless you ask for a pull.
|
||||
- **No environment variable overrides for the config.** `GITEA_DEBUG`, `GITEA_TRACE`, `GITEA_RUNNER_CAPACITY`, `GITEA_RUNNER_FILE`, `GITEA_RUNNER_ENVIRON` and `GITEA_RUNNER_ENV_FILE` are ignored; use a config file. The Docker images' [entrypoint variables](installation/docker.md#entrypoint-environment-variables) are unaffected.
|
||||
|
||||
### Also new
|
||||
|
||||
- [Post-task script](hooks/post-task-script.md) (`runner.post_task_script`) for host housekeeping between jobs.
|
||||
- [Health checks](monitoring.md#local-health-checks) (`health_check.*`) that pause task admission on low disk space or a failing script.
|
||||
- `register --token-file`, and `GITEA_RUNNER_LABELS` honoured by `daemon`, so labels can change without re-registering.
|
||||
- `jobs.<job_id>.timeout-minutes` and `jobs.<job_id>.continue-on-error` support, job summaries, shallow action clones (`runner.action_shallow_clone`), `ssh://` action URLs, IPv4/IPv6 options for auto-created networks, `--platform` and `--pull` in `container.options`, `cache.external_secret_file`, a GitHub-style "Set up job" log section, and pre/post entrypoints of Docker actions.
|
||||
|
||||
## Downgrading
|
||||
|
||||
Downgrading a runner is possible — the registration file format has not changed — but a config file written for a newer version may carry keys the older one ignores, and features such as cache service v2 stop being served, so jobs that came to rely on them fail. Test a downgrade with a spare runner before doing it on a busy pool.
|
||||
Release notes for every version are on the [release page](https://gitea.com/gitea/runner/releases).
|
||||
|
||||
Reference in New Issue
Block a user