Skip to content
Try Gitea Cloud ☁️ for 30 days → Accelerate your Development & Deploys!

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.

Terminal window
gitea-runner generate-config > config.yaml
gitea-runner -c config.yaml register
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.

Values with a duration type accept Go duration strings such as 30s, 10m, 3h.

Controls the runner’s own log, not how step output is streamed to the UI.

Option Default Description
log.level info trace, debug, info, warn, error, fatal or panic. trace and debug add the caller’s file:line.
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 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.
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.

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.

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.

See Caching 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/cache@v4.2 and later.

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 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. Needed for jobs that use docker compose with bind mounts under Docker-in-Docker. The parent directory must then be mounted into the runner container and listed in valid_volumes.
Option Default Description
host.workdir_parent $HOME/.cache/act/ parent directory of a job’s working directory for host-mode jobs.

Both are covered in Monitoring.

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.

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.