Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
340222e041 | ||
|
|
179e47bbb2 | ||
|
|
68d16577b3 | ||
|
|
38607d9f29 | ||
|
|
90139b306b | ||
|
|
dd475bec0d |
@@ -2,6 +2,18 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.18.6] - 2026-08-05
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Pre-configure daemon.json before rootless setuptool + add DBUS_SESSION_BUS_ADDRESS
|
||||
|
||||
## [0.18.5] - 2026-08-05
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Pin Docker 28.x + disable containerd snapshotter + tune prune/disk
|
||||
|
||||
## [0.18.4] - 2026-08-05
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Why GRM?
|
||||
|
||||
|
||||
@@ -18,7 +18,11 @@ gitea_runner_binary_path: "/usr/local/bin/gitea_runner"
|
||||
|
||||
# Prune configuration
|
||||
gitea_runner_prune_until: "24h"
|
||||
gitea_runner_prune_schedule: "daily"
|
||||
# Every 6 hours — daily is insufficient for CI runners that build dozens
|
||||
# of images per day. Accumulation between daily runs can trigger Docker
|
||||
# daemon instability (containerd snapshotter GC holds locks, blocking
|
||||
# container operations).
|
||||
gitea_runner_prune_schedule: "*-*-* 00/6:00:00"
|
||||
gitea_runner_prune_label: "gitea-runner=true"
|
||||
|
||||
# Service configuration
|
||||
@@ -30,7 +34,7 @@ gitea_runner_service_restart_sec: "5"
|
||||
# jobs in the window between healthcheck runs.
|
||||
gitea_runner_healthcheck_interval: "2min"
|
||||
gitea_runner_healthcheck_boot_delay: "2min"
|
||||
gitea_runner_healthcheck_disk_threshold: 85
|
||||
gitea_runner_healthcheck_disk_threshold: 75
|
||||
gitea_runner_healthcheck_script_path: "{{ gitea_runner_config_dir }}/healthcheck.sh"
|
||||
|
||||
# Docker daemon resilience settings (applied to daemon.json).
|
||||
@@ -46,7 +50,7 @@ gitea_runner_docker_live_restore: true
|
||||
gitea_runner_docker_shutdown_timeout: 30
|
||||
gitea_runner_docker_max_concurrent_downloads: 3
|
||||
gitea_runner_docker_max_concurrent_uploads: 3
|
||||
gitea_runner_docker_default_nofile: 1048576
|
||||
gitea_runner_docker_default_nofile: 65536
|
||||
|
||||
# Admin token for runner deregistration via Gitea API.
|
||||
# If not set, falls back to registration_token (which likely lacks admin scope).
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock"
|
||||
when:
|
||||
- gitea_runner_file_stat.stat.exists | default(false) | bool
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
@@ -40,6 +41,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
register: gitea_runner_service_check
|
||||
changed_when: false
|
||||
retries: 10
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
environment:
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
register: gitea_runner_pre_pull_result
|
||||
changed_when: "'Status: Downloaded' in gitea_runner_pre_pull_result.stdout or 'Status: Downloaded' in gitea_runner_pre_pull_result.stderr"
|
||||
retries: 3
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
@@ -32,6 +33,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default(0) }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default(0) }}/docker.sock"
|
||||
when: not gitea_runner_registered.stat.exists
|
||||
register: gitea_runner_register_output
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
- ansible_facts['os_family'] == 'Debian'
|
||||
- gitea_runner_docker_apt_repo is changed
|
||||
|
||||
# Install Docker packages from the upstream Docker APT repository.
|
||||
# We do NOT pin to 28.x because recent Ubuntu releases (e.g. 26.04/plucky)
|
||||
# may not have 28.x packages in the Docker repo, and Docker 29 is safe
|
||||
# for rootless mode when the daemon.json disables the containerd snapshotter
|
||||
# and sets a conservative default nofile ulimit (see daemon.json tasks below).
|
||||
- name: Install rootless Docker dependencies (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
@@ -45,6 +50,7 @@
|
||||
- docker-compose-plugin
|
||||
- rsync
|
||||
state: present
|
||||
register: gitea_runner_docker_install
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Update pacman cache (Arch Linux)
|
||||
@@ -133,8 +139,57 @@
|
||||
content: |
|
||||
[Service]
|
||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET={{ gitea_runner_docker_rootless_net_driver }}"
|
||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit"
|
||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER={{ 'implicit' if gitea_runner_docker_rootless_net_driver == 'pasta' else 'builtin' }}"
|
||||
{% if gitea_runner_docker_rootless_net_driver == 'pasta' %}
|
||||
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6"
|
||||
{% endif %}
|
||||
mode: "0644"
|
||||
owner: "{{ gitea_runner_service_user }}"
|
||||
group: "{{ gitea_runner_service_user }}"
|
||||
when:
|
||||
- gitea_runner_docker_rootless_setup
|
||||
- not gitea_runner_rootless_docker_check.stat.exists
|
||||
|
||||
# Write daemon.json BEFORE the setuptool starts dockerd, so Docker 29
|
||||
# starts with containerd snapshotter disabled from the very first boot.
|
||||
# Without this, Docker 29 uses containerd snapshots by default, which
|
||||
# causes instability in rootless mode.
|
||||
- name: Ensure Docker config directory exists (pre-setup)
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home }}/.config/docker"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: "{{ gitea_runner_service_user }}"
|
||||
group: "{{ gitea_runner_service_user }}"
|
||||
when:
|
||||
- gitea_runner_docker_rootless_setup
|
||||
- not gitea_runner_rootless_docker_check.stat.exists
|
||||
|
||||
- name: Pre-configure rootless Docker daemon.json (disable containerd snapshotter)
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ gitea_runner_home }}/.config/docker/daemon.json"
|
||||
content: |
|
||||
{
|
||||
"live-restore": {{ gitea_runner_docker_live_restore | to_json }},
|
||||
"shutdown-timeout": {{ gitea_runner_docker_shutdown_timeout }},
|
||||
"max-concurrent-downloads": {{ gitea_runner_docker_max_concurrent_downloads }},
|
||||
"max-concurrent-uploads": {{ gitea_runner_docker_max_concurrent_uploads }},
|
||||
"default-ulimits": {
|
||||
"nofile": {"Name": "nofile", "Hard": {{ gitea_runner_docker_default_nofile }}, "Soft": {{ gitea_runner_docker_default_nofile }}}
|
||||
},
|
||||
"features": {
|
||||
"containerd-snapshotter": false
|
||||
},
|
||||
{% if gitea_runner_docker_rootless_net_driver == 'pasta' %}
|
||||
"ipv6": true,
|
||||
"ip6tables": true,
|
||||
"fixed-cidr-v6": "{{ gitea_runner_docker_ipv6_cidr }}",
|
||||
"dns": ["10.0.2.3", "8.8.8.8"]
|
||||
{% else %}
|
||||
"ipv6": false,
|
||||
"dns": ["8.8.8.8", "1.1.1.1"]
|
||||
{% endif %}
|
||||
}
|
||||
mode: "0644"
|
||||
owner: "{{ gitea_runner_service_user }}"
|
||||
group: "{{ gitea_runner_service_user }}"
|
||||
@@ -150,6 +205,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
DOCKERD_ROOTLESS_ROOTLESSKIT_NET: "{{ gitea_runner_docker_rootless_net_driver }}"
|
||||
when:
|
||||
- gitea_runner_docker_rootless_setup
|
||||
@@ -161,6 +217,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
changed_when: true
|
||||
when: gitea_runner_docker_rootless_setup
|
||||
|
||||
@@ -170,6 +227,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
changed_when: true
|
||||
when: gitea_runner_docker_rootless_setup
|
||||
|
||||
@@ -204,6 +262,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_docker_rootless_setup
|
||||
@@ -221,6 +280,9 @@
|
||||
"default-ulimits": {
|
||||
"nofile": {"Name": "nofile", "Hard": {{ gitea_runner_docker_default_nofile }}, "Soft": {{ gitea_runner_docker_default_nofile }}}
|
||||
},
|
||||
"features": {
|
||||
"containerd-snapshotter": false
|
||||
},
|
||||
{% if gitea_runner_docker_rootless_net_driver == 'pasta' %}
|
||||
"ipv6": true,
|
||||
"ip6tables": true,
|
||||
@@ -243,6 +305,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_docker_rootless_setup
|
||||
@@ -255,6 +318,7 @@
|
||||
environment:
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid }}/bus"
|
||||
register: gitea_runner_docker_ready
|
||||
until: gitea_runner_docker_ready.rc == 0
|
||||
retries: 10
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
@@ -24,6 +25,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
changed_when: true
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
become_user: "{{ gitea_runner_service_user }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
when:
|
||||
- gitea_runner_systemd_available.stat.exists | default(false) | bool
|
||||
- gitea_runner_docker_rootless_setup
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
environment:
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid }}/docker.sock"
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ gitea_runner_uid | default(0) }}/bus"
|
||||
register: gitea_runner_docker_version_output
|
||||
changed_when: false
|
||||
when: gitea_runner_docker_rootless_setup
|
||||
|
||||
+6
-6
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
|
||||
|
||||
__version__ = "0.18.4"
|
||||
__version__ = "0.18.6"
|
||||
|
||||
Reference in New Issue
Block a user