Initial commit: nult - Ansible deployment toolkit

Merged from veridion-gitea and veridion-act-runner-gitea repos.

nult (Null-T) - instant teleportation from Strugatsky's Noon Universe.
Like Null-T, this toolkit instantly deploys infrastructure.

Roles:
- gitea: Gitea server with PostgreSQL (Docker Compose)
- act_runner: Gitea Actions runner

Playbooks:
- gitea.yml: Deploy Gitea server
- act-runner.yml: Deploy Act Runner
- site.yml: Deploy all services

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-15 15:34:07 +01:00
commit a9554f3e5d
29 changed files with 2029 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
---
# =============================================================================
# Gitea Act Runner - Role Default Variables
# =============================================================================
#
# This file defines configurable variables for the act_runner role.
# Override these in group_vars/all.yml or inventory host_vars as needed.
#
# REQUIRED VARIABLES (must be set in vault - not defined here):
# - gitea_instance_url : URL of your Gitea instance
# - act_runner_token : Registration token from Gitea
# - gitea_packages_token : PAT for package registry access
# - gitea_registry : Package registry hostname
# - gitea_actions_user : Service account username
#
# See group_vars/vault.yml.example for how to set these secrets.
# See: https://docs.gitea.com/usage/actions/act-runner
# =============================================================================
# -----------------------------------------------------------------------------
# Act Runner Binary Configuration
# -----------------------------------------------------------------------------
# Version of act_runner to install.
# Check available versions at: https://dl.gitea.com/act_runner/
# Format: semantic version string without 'v' prefix.
act_runner_version: "0.2.13"
# Target CPU architecture for the binary download.
# Valid values: "amd64" (x86_64), "arm64" (aarch64)
act_runner_arch: "amd64"
# Whether to verify SHA256 checksum after downloading the binary.
# STRONGLY RECOMMENDED: Leave as true for security.
act_runner_verify_checksum: true
# Filesystem path where the act_runner binary will be installed.
# /usr/local/bin is the standard FHS location for locally installed binaries.
act_runner_bin_path: "/usr/local/bin/act_runner"
# -----------------------------------------------------------------------------
# System User Configuration
# -----------------------------------------------------------------------------
# Unix username for running the act_runner service.
# Will be created as a system user if it doesn't exist.
act_runner_user: "act_runner"
# Unix group for the act_runner user.
act_runner_group: "act_runner"
# Home directory for the act_runner user.
# Stores: .runner file, cache, working directories.
act_runner_home: "/home/act_runner"
# Directory for act_runner configuration files.
# Stores: config.yaml
act_runner_config_dir: "/etc/act_runner"
# -----------------------------------------------------------------------------
# Node.js Configuration
# -----------------------------------------------------------------------------
# Node.js major version to install via NodeSource.
# Required for JavaScript-based GitHub Actions.
# Valid values: "18", "20", "22", "24"
# See: https://nodejs.org/en/about/previous-releases
act_runner_nodejs_version: "24"
# -----------------------------------------------------------------------------
# Runner Configuration
# -----------------------------------------------------------------------------
# Human-readable name for this runner instance.
# Displayed in Gitea UI under Actions > Runners.
# Default: server's hostname
act_runner_name: "{{ ansible_facts['hostname'] }}"
# Labels determine which jobs this runner can execute.
# Format: "label-name:executor"
# Executors:
# - "host" : Run directly on the host system
# - "docker://image" : Run in Docker container
#
# Examples:
# - "ubuntu-latest:host"
# - "ubuntu-latest:docker://node:24"
# - "self-hosted:host"
act_runner_labels:
- "ubuntu-latest:host"
# -----------------------------------------------------------------------------
# Container Behavior
# -----------------------------------------------------------------------------
# Whether to always pull container images before running jobs.
# true: Ensures latest image (recommended for CI/CD)
# false: Uses cached image if available (faster)
act_runner_container_force_pull: true

View File

@@ -0,0 +1,26 @@
---
# =============================================================================
# Gitea Act Runner - Ansible Handlers
# =============================================================================
#
# Handlers are triggered by 'notify' in tasks and run once at the end of play.
# They provide a way to restart services only when configuration changes.
#
# Usage in tasks:
# - name: Deploy config
# template: ...
# notify: restart act_runner
#
# =============================================================================
# Reload systemd configuration after unit file changes.
# Required before systemctl can see updated unit files.
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
# Restart the act_runner service to apply configuration changes.
- name: Restart act_runner
ansible.builtin.systemd:
name: act_runner
state: restarted

View File

@@ -0,0 +1,88 @@
---
# =============================================================================
# Gitea Act Runner - Binary Installation
# =============================================================================
#
# Downloads and installs the act_runner binary from:
# https://dl.gitea.com/act_runner/
#
# Security: Binary integrity is verified via SHA256 checksum.
#
# =============================================================================
# Construct download URLs based on version and architecture.
- name: Set act_runner download URLs
ansible.builtin.set_fact:
act_runner_download_url: >-
https://dl.gitea.com/act_runner/{{ act_runner_version }}/act_runner-{{ act_runner_version }}-linux-{{ act_runner_arch }}
act_runner_checksum_url: >-
https://dl.gitea.com/act_runner/{{ act_runner_version }}/act_runner-{{ act_runner_version }}-linux-{{ act_runner_arch }}.sha256
# Download the act_runner binary to a temporary location.
- name: Download act_runner binary
ansible.builtin.get_url:
url: "{{ act_runner_download_url }}"
dest: /tmp/act_runner
mode: '0755'
# Download checksum file for verification (when enabled).
- name: Download act_runner checksum
ansible.builtin.get_url:
url: "{{ act_runner_checksum_url }}"
dest: /tmp/act_runner.sha256
mode: '0644'
when: act_runner_verify_checksum
# Read the expected checksum from the downloaded file.
- name: Read expected checksum
ansible.builtin.slurp:
src: /tmp/act_runner.sha256
register: act_runner_expected_checksum_file
when: act_runner_verify_checksum
# Parse the checksum (format: "checksum filename").
- name: Parse expected checksum
ansible.builtin.set_fact:
act_runner_expected_checksum: "{{ (act_runner_expected_checksum_file.content | b64decode).split()[0] }}"
when: act_runner_verify_checksum
# Calculate actual checksum of downloaded binary.
- name: Calculate actual checksum
ansible.builtin.stat:
path: /tmp/act_runner
checksum_algorithm: sha256
register: act_runner_actual_checksum
when: act_runner_verify_checksum
# Verify checksums match (fail if tampered).
- name: Verify checksum matches
ansible.builtin.assert:
that:
- act_runner_actual_checksum.stat.checksum == act_runner_expected_checksum
fail_msg: >-
Checksum verification FAILED!
Expected: {{ act_runner_expected_checksum }}
Actual: {{ act_runner_actual_checksum.stat.checksum }}
The downloaded binary may have been tampered with.
success_msg: "Checksum verified: {{ act_runner_expected_checksum }}"
when: act_runner_verify_checksum
# Install binary to final location.
- name: Install act_runner binary
ansible.builtin.copy:
src: /tmp/act_runner
dest: "{{ act_runner_bin_path }}"
remote_src: true
owner: root
group: root
mode: '0755'
notify: Restart act_runner
# Clean up temporary files.
- name: Clean up temporary files
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /tmp/act_runner
- /tmp/act_runner.sha256

View File

@@ -0,0 +1,56 @@
---
# =============================================================================
# Gitea Act Runner - Configuration and Registration
# =============================================================================
#
# Deploys the runner configuration and registers with Gitea.
# Registration is idempotent: only runs if .runner file doesn't exist.
#
# The .runner file contains the runner's identity after registration.
# DO NOT DELETE this file or re-registration will be required.
#
# =============================================================================
# Deploy configuration file from template.
- name: Deploy act_runner configuration
ansible.builtin.template:
src: config.yaml.j2
dest: "{{ act_runner_config_dir }}/config.yaml"
owner: "{{ act_runner_user }}"
group: "{{ act_runner_group }}"
mode: '0640' # Restrictive: contains secrets
notify: Restart act_runner
# Check if runner is already registered.
# The .runner file is created during registration and persists.
- name: Check if runner is already registered
ansible.builtin.stat:
path: "{{ act_runner_home }}/.runner"
register: act_runner_runner_file
# Register the runner with Gitea (only if not already registered).
# This is a one-time operation that creates the .runner file.
- name: Register runner with Gitea
ansible.builtin.command:
cmd: >-
{{ act_runner_bin_path }} register
--no-interactive
--config {{ act_runner_config_dir }}/config.yaml
--instance {{ gitea_instance_url }}
--token {{ act_runner_token }}
--name {{ act_runner_name }}
--labels {{ act_runner_labels | join(',') }}
chdir: "{{ act_runner_home }}"
become: true
become_user: "{{ act_runner_user }}"
when: not act_runner_runner_file.stat.exists
register: act_runner_registration_result
changed_when: act_runner_registration_result.rc == 0
# Don't show token in logs
no_log: true
# Display registration result (without sensitive data).
- name: Display registration status
ansible.builtin.debug:
msg: >-
Runner registration: {{ 'NEW - registered successfully' if act_runner_registration_result.changed | default(false) else 'EXISTING - already registered' }}

View File

@@ -0,0 +1,91 @@
---
# =============================================================================
# Gitea Act Runner - Docker Installation
# =============================================================================
#
# Installs Docker CE following the official Docker documentation:
# https://docs.docker.com/engine/install/ubuntu/
#
# Uses DEB822 format (.sources) as per current Docker documentation.
#
# =============================================================================
# Remove old/conflicting Docker packages that may interfere.
- name: Remove conflicting Docker packages
ansible.builtin.apt:
name:
- docker.io
- docker-doc
- docker-compose
- docker-compose-v2
- podman-docker
- containerd
- runc
state: absent
failed_when: false
# Install packages required to add Docker's APT repository.
- name: Install Docker prerequisites
ansible.builtin.apt:
name:
- ca-certificates
- curl
state: present
# Create directory for APT keyrings.
- name: Create keyrings directory
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: '0755'
# Download Docker's official GPG key.
- name: Download Docker GPG key
ansible.builtin.get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /etc/apt/keyrings/docker.asc
mode: '0644'
# Get the dpkg architecture for the repository URL.
- name: Get dpkg architecture
ansible.builtin.command: dpkg --print-architecture
register: act_runner_dpkg_arch
changed_when: false
# Add Docker's APT repository using DEB822 format.
# This is the modern format recommended by Docker documentation.
- name: Add Docker APT repository (DEB822 format)
ansible.builtin.copy:
dest: /etc/apt/sources.list.d/docker.sources
mode: '0644'
content: |
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: {{ ansible_facts['distribution_release'] }}
Components: stable
Architectures: {{ act_runner_dpkg_arch.stdout }}
Signed-By: /etc/apt/keyrings/docker.asc
# Update apt cache after adding repository.
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 0 # Force update since we just added a new repo
# Install Docker CE and related packages.
- name: Install Docker packages
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
state: present
# Ensure Docker service is running and enabled on boot.
- name: Ensure Docker service is started and enabled
ansible.builtin.systemd:
name: docker
state: started
enabled: true

View File

@@ -0,0 +1,75 @@
---
# =============================================================================
# Gitea Act Runner - Main Task Orchestration
# =============================================================================
#
# This file orchestrates the act_runner installation in the correct order.
# Each include_tasks imports a focused task file for better maintainability.
#
# Execution order matters:
# 1. Validate inputs (fail fast on missing required values)
# 2. Install Docker (required for container operations in Actions)
# 3. Install Node.js (required for JavaScript-based GitHub Actions)
# 4. Download act_runner binary (the core component)
# 5. Create system user (security: run as unprivileged user)
# 6. Configure and register (connect to Gitea instance)
# 7. Setup systemd service (enable automatic startup)
# 8. Verify installation (ensure everything works)
#
# =============================================================================
# Fail early if required variables are not set.
# This prevents partial installations that would be harder to debug.
- name: Validate required variables are defined
ansible.builtin.assert:
that:
- gitea_instance_url is defined
- gitea_instance_url | length > 0
- act_runner_token is defined
- act_runner_token | length > 0
- gitea_packages_token is defined
- gitea_packages_token | length > 0
- gitea_registry is defined
- gitea_registry | length > 0
- gitea_actions_user is defined
- gitea_actions_user | length > 0
fail_msg: >-
Missing required variables. Ensure these are set in vault:
gitea_instance_url, act_runner_token, gitea_packages_token,
gitea_registry, gitea_actions_user.
See group_vars/vault.yml.example for details.
success_msg: "All required variables are defined"
# Docker is needed even for host execution because many GitHub Actions
# use Docker internally (e.g., actions/checkout uses node in container).
- name: Install and configure Docker
ansible.builtin.include_tasks: docker.yml
# Node.js is required for JavaScript-based GitHub Actions.
# Many popular actions (checkout, cache, upload-artifact) need Node.js.
- name: Install Node.js runtime
ansible.builtin.include_tasks: nodejs.yml
# Download and install the act_runner binary with checksum verification.
- name: Install act_runner binary
ansible.builtin.include_tasks: binary.yml
# Create dedicated system user for security isolation.
# The runner should not run as root.
- name: Create act_runner system user
ansible.builtin.include_tasks: user.yml
# Deploy configuration and register with Gitea instance.
# Registration only happens if .runner file doesn't exist (idempotent).
- name: Configure and register runner
ansible.builtin.include_tasks: config.yml
# Deploy systemd unit file for service management.
# Enables automatic startup on boot and easy service control.
- name: Setup systemd service
ansible.builtin.include_tasks: systemd.yml
# Run verification checks to ensure installation succeeded.
# Fails the playbook if any critical component is not working.
- name: Verify installation
ansible.builtin.include_tasks: verify.yml

View File

@@ -0,0 +1,54 @@
---
# =============================================================================
# Gitea Act Runner - Node.js Installation
# =============================================================================
#
# Installs Node.js LTS via NodeSource:
# https://github.com/nodesource/distributions
#
# Node.js is required because:
# - Many GitHub Actions are written in JavaScript
# - Popular actions like checkout, cache, upload-artifact need Node.js
# - The runner itself may need Node.js for certain operations
#
# =============================================================================
# Install prerequisites for NodeSource setup script.
- name: Install Node.js prerequisites
ansible.builtin.apt:
name:
- ca-certificates
- curl
- gnupg
state: present
# Download NodeSource setup script.
# This script adds the NodeSource APT repository.
- name: Download NodeSource setup script
ansible.builtin.get_url:
url: "https://deb.nodesource.com/setup_{{ act_runner_nodejs_version }}.x"
dest: /tmp/nodesource_setup.sh
mode: '0755'
# Execute the NodeSource setup script to configure APT repository.
# Script is safe to re-run (idempotent).
- name: Execute NodeSource setup script
ansible.builtin.command:
cmd: /tmp/nodesource_setup.sh
args:
creates: /etc/apt/sources.list.d/nodesource.list
register: act_runner_nodesource_result
changed_when: act_runner_nodesource_result.rc == 0
# Install Node.js from NodeSource repository.
- name: Install Node.js
ansible.builtin.apt:
name: nodejs
state: present
update_cache: true
# Clean up setup script.
- name: Remove NodeSource setup script
ansible.builtin.file:
path: /tmp/nodesource_setup.sh
state: absent

View File

@@ -0,0 +1,37 @@
---
# =============================================================================
# Gitea Act Runner - Systemd Service Setup
# =============================================================================
#
# Creates and enables the systemd service for act_runner.
# This ensures the runner:
# - Starts automatically on boot
# - Restarts if it crashes
# - Can be controlled via systemctl
#
# =============================================================================
# Deploy systemd service unit file from template.
- name: Deploy systemd service file
ansible.builtin.template:
src: act_runner.service.j2
dest: /etc/systemd/system/act_runner.service
owner: root
group: root
mode: '0644'
notify:
- Reload systemd
- Restart act_runner
# Reload systemd to pick up the new/changed unit file.
# This is immediate (not via handler) to ensure service can be started.
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true
# Enable and start the act_runner service.
- name: Enable and start act_runner service
ansible.builtin.systemd:
name: act_runner
state: started
enabled: true

View File

@@ -0,0 +1,54 @@
---
# =============================================================================
# Gitea Act Runner - System User Setup
# =============================================================================
#
# Creates a dedicated system user for running the act_runner service.
# Running as an unprivileged user improves security by:
# - Limiting what the service can access
# - Isolating it from other services
# - Following the principle of least privilege
#
# =============================================================================
# Create the act_runner system group.
- name: Create act_runner group
ansible.builtin.group:
name: "{{ act_runner_group }}"
state: present
system: true
# Create the act_runner system user.
- name: Create act_runner user
ansible.builtin.user:
name: "{{ act_runner_user }}"
group: "{{ act_runner_group }}"
# Add to docker group for container access.
groups: docker
append: true
# Use bash shell for better compatibility with actions.
shell: /bin/bash
# Home directory for runner data.
home: "{{ act_runner_home }}"
create_home: true
# System user (no login, low UID).
system: true
state: present
# Ensure home directory has correct permissions.
- name: Set permissions on home directory
ansible.builtin.file:
path: "{{ act_runner_home }}"
state: directory
owner: "{{ act_runner_user }}"
group: "{{ act_runner_group }}"
mode: '0750'
# Create configuration directory.
- name: Create configuration directory
ansible.builtin.file:
path: "{{ act_runner_config_dir }}"
state: directory
owner: "{{ act_runner_user }}"
group: "{{ act_runner_group }}"
mode: '0750'

View File

@@ -0,0 +1,80 @@
---
# =============================================================================
# Gitea Act Runner - Installation Verification
# =============================================================================
#
# Verifies that all components were installed correctly.
# Fails the playbook if any critical check doesn't pass.
#
# Verification order:
# 1. Docker daemon is running and accessible
# 2. Node.js is installed at the expected version
# 3. act_runner binary is executable and reports version
# 4. act_runner systemd service is active
#
# =============================================================================
# Verify Docker daemon is running and accessible.
- name: Verify Docker daemon is accessible
ansible.builtin.command: docker info
changed_when: false
register: act_runner_docker_info_result
- name: Display Docker status
ansible.builtin.debug:
msg: "Docker is running: {{ act_runner_docker_info_result.stdout_lines[0] | default('OK') }}"
# Verify Node.js is installed at the expected major version.
- name: Verify Node.js installation
ansible.builtin.command: node --version
changed_when: false
register: act_runner_node_version_result
- name: Verify Node.js major version matches expected
ansible.builtin.assert:
that:
- act_runner_node_version_result.stdout is match('^v' ~ act_runner_nodejs_version ~ '\\.')
fail_msg: >-
Node.js version mismatch!
Expected: v{{ act_runner_nodejs_version }}.x
Actual: {{ act_runner_node_version_result.stdout }}
success_msg: "Node.js {{ act_runner_node_version_result.stdout }} installed correctly"
# Verify act_runner binary is installed and executable.
- name: Verify act_runner binary
ansible.builtin.command: "{{ act_runner_bin_path }} --version"
changed_when: false
register: act_runner_version_result
- name: Display act_runner version
ansible.builtin.debug:
msg: "act_runner version: {{ act_runner_version_result.stdout }}"
# Verify the systemd service is running.
- name: Get act_runner service status
ansible.builtin.systemd:
name: act_runner
register: act_runner_service_status
- name: Verify act_runner service is active
ansible.builtin.assert:
that:
- act_runner_service_status.status.ActiveState == "active"
fail_msg: >-
act_runner service is NOT running!
State: {{ act_runner_service_status.status.ActiveState }}
Check logs: journalctl -u act_runner -n 50
success_msg: "act_runner service is running (PID: {{ act_runner_service_status.status.MainPID }})"
# Final summary.
- name: Verification complete
ansible.builtin.debug:
msg:
- "=========================================="
- "All verification checks PASSED!"
- "=========================================="
- "Docker: running"
- "Node.js: {{ act_runner_node_version_result.stdout }}"
- "act_runner: {{ act_runner_version_result.stdout }}"
- "Service: active (PID {{ act_runner_service_status.status.MainPID }})"
- "=========================================="

View File

@@ -0,0 +1,71 @@
# =============================================================================
# Gitea Act Runner - Systemd Service Unit
# =============================================================================
# Managed by Ansible - DO NOT EDIT MANUALLY
#
# Common commands:
# systemctl status act_runner - Check service status
# systemctl restart act_runner - Restart the service
# journalctl -u act_runner -f - Follow service logs
#
# See: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
# =============================================================================
[Unit]
# Human-readable description
Description=Gitea Actions runner
# Documentation link
Documentation=https://gitea.com/gitea/act_runner
# Start after Docker and network are available
After=docker.service network-online.target
# Request network-online.target to be started
Wants=network-online.target
[Service]
# Simple type: process runs in foreground
Type=simple
# Main command
ExecStart={{ act_runner_bin_path }} daemon --config {{ act_runner_config_dir }}/config.yaml
# Reload command (sends HUP signal)
ExecReload=/bin/kill -s HUP $MAINPID
# Working directory
WorkingDirectory={{ act_runner_home }}
# No timeout for start/stop (jobs may take long)
TimeoutSec=0
# Wait before restarting after failure
RestartSec=10
# Always restart on any exit
Restart=always
# Run as unprivileged user
User={{ act_runner_user }}
Group={{ act_runner_group }}
# ---------------------------------------------------------------------------
# Security Hardening
# ---------------------------------------------------------------------------
# No new privileges via setuid/setgid
NoNewPrivileges=true
# Make /usr, /boot, /efi read-only
ProtectSystem=strict
# Allow writes only to these paths
ReadWritePaths={{ act_runner_home }} {{ act_runner_config_dir }}
# Private /tmp directory
PrivateTmp=true
[Install]
# Start on normal boot
WantedBy=multi-user.target

View File

@@ -0,0 +1,113 @@
# =============================================================================
# Gitea Act Runner - Configuration File
# =============================================================================
# Managed by Ansible - DO NOT EDIT MANUALLY
#
# To modify settings, update the role variables and re-run the playbook.
#
# Reference: https://docs.gitea.com/usage/actions/act-runner
# =============================================================================
# -----------------------------------------------------------------------------
# Logging Configuration
# -----------------------------------------------------------------------------
log:
# Log verbosity level.
# Valid values: trace, debug, info, warn, error, fatal
level: info
# -----------------------------------------------------------------------------
# Runner Core Configuration
# -----------------------------------------------------------------------------
runner:
# Path to the runner registration state file.
# Created during 'act_runner register'. DO NOT DELETE.
file: {{ act_runner_home }}/.runner
# Maximum number of concurrent jobs.
capacity: 1
# Environment variables injected into every job.
envs:
# Package registry hostname
registry: {{ gitea_registry }}
# Service account username
actions_user: {{ gitea_actions_user }}
# PAT for package registry authentication
PACKAGES_TOKEN: {{ gitea_packages_token }}
# Optional file for additional environment variables.
env_file: .env
# Maximum job duration (also limited by Gitea instance).
timeout: 3h
# Grace period for jobs during shutdown.
shutdown_timeout: 0s
# Skip TLS verification. WARNING: Security risk if true.
insecure: false
# Job polling settings.
fetch_timeout: 5s
fetch_interval: 2s
# Labels determine which jobs this runner handles.
labels:
{% for label in act_runner_labels %}
- "{{ label }}"
{% endfor %}
# -----------------------------------------------------------------------------
# Cache Server Configuration
# -----------------------------------------------------------------------------
cache:
# Enable built-in cache server for actions/cache.
enabled: true
# Cache storage directory (empty = default).
dir: ""
# Network settings (empty = auto-detect).
host: ""
port: 0
# External cache server URL (empty = use built-in).
external_server: ""
# -----------------------------------------------------------------------------
# Container Execution Configuration
# -----------------------------------------------------------------------------
container:
# Docker network (empty = isolated per job).
network: ""
# Privileged mode. WARNING: Security risk if true.
privileged: false
# Additional docker run options.
options:
# Working directory inside containers.
workdir_parent:
# Allowed volume mounts (empty = none, ["**"] = any).
valid_volumes: []
# Docker daemon (empty = auto-detect).
docker_host: ""
# Always pull images before jobs.
force_pull: {{ act_runner_container_force_pull | lower }}
# Rebuild images even if they exist.
force_rebuild: false
# -----------------------------------------------------------------------------
# Host Execution Configuration
# -----------------------------------------------------------------------------
host:
# Working directory for host execution.
workdir_parent: