GRM-158: Fix rootless Docker 29 setup on Arch Linux runners #243

Merged
emo merged 3 commits from GRM-158-rootless-docker-29-arch-fixes into master 2026-08-05 23:57:28 +00:00
11 changed files with 76 additions and 19 deletions
+2 -2
View File
@@ -22,7 +22,7 @@ gitea_runner_prune_until: "24h"
# 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: "*-* * */6:00:00"
gitea_runner_prune_schedule: "*-*-* 00/6:00:00"
gitea_runner_prune_label: "gitea-runner=true"
# Service configuration
@@ -50,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,22 +31,11 @@
- ansible_facts['os_family'] == 'Debian'
- gitea_runner_docker_apt_repo is changed
# Pin Docker to 28.x — Docker 29 enables the containerd image store
# (containerd snapshotter) by default, which has critical instability
# issues with rootless Docker: "context deadline exceeded" when starting
# dockerd with many images, snapshot GC holding locks for 30+ seconds
# blocking container operations, and broken rootless overlayfs on
# kernels < 5.11. See moby/moby issues #48569, #11021, #53029.
- name: Pin Docker to 28.x to avoid containerd snapshotter instability (Debian/Ubuntu)
ansible.builtin.copy:
dest: /etc/apt/preferences.d/docker-pin
content: |
Package: docker-ce docker-ce-cli docker-ce-rootless-extras containerd.io
Pin: version 5:28.*
Pin-Priority: 1000
mode: "0644"
when: ansible_facts['os_family'] == 'Debian'
# 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:
@@ -61,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)
@@ -149,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 }}"
@@ -166,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
@@ -177,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
@@ -186,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
@@ -220,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
@@ -262,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
@@ -274,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