From 179e47bbb2b5958b82220900284bbd7c95d5b49e Mon Sep 17 00:00:00 2001 From: kireto Date: Wed, 5 Aug 2026 23:57:25 +0000 Subject: [PATCH] GRM-158: fix: pre-configure daemon.json before rootless setuptool + add DBUS_SESSION_BUS_ADDRESS Co-authored-by: kireto --- ansible/roles/gitea_runner/defaults/main.yml | 4 +- .../roles/gitea_runner/tasks/deregister.yml | 1 + .../roles/gitea_runner/tasks/healthcheck.yml | 2 + .../gitea_runner/tasks/integration_test.yml | 1 + .../gitea_runner/tasks/pre_pull_images.yml | 1 + ansible/roles/gitea_runner/tasks/prune.yml | 2 + ansible/roles/gitea_runner/tasks/register.yml | 1 + .../gitea_runner/tasks/rootless_docker.yml | 79 +++++++++++++++---- ansible/roles/gitea_runner/tasks/service.yml | 2 + .../gitea_runner/tasks/update_runner.yml | 1 + ansible/roles/gitea_runner/tasks/validate.yml | 1 + 11 files changed, 76 insertions(+), 19 deletions(-) diff --git a/ansible/roles/gitea_runner/defaults/main.yml b/ansible/roles/gitea_runner/defaults/main.yml index 8522194..92f8111 100644 --- a/ansible/roles/gitea_runner/defaults/main.yml +++ b/ansible/roles/gitea_runner/defaults/main.yml @@ -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). diff --git a/ansible/roles/gitea_runner/tasks/deregister.yml b/ansible/roles/gitea_runner/tasks/deregister.yml index 517eabe..26ff643 100644 --- a/ansible/roles/gitea_runner/tasks/deregister.yml +++ b/ansible/roles/gitea_runner/tasks/deregister.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/healthcheck.yml b/ansible/roles/gitea_runner/tasks/healthcheck.yml index 1189437..a85d4e1 100644 --- a/ansible/roles/gitea_runner/tasks/healthcheck.yml +++ b/ansible/roles/gitea_runner/tasks/healthcheck.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/integration_test.yml b/ansible/roles/gitea_runner/tasks/integration_test.yml index 36a8c39..cdadd8c 100644 --- a/ansible/roles/gitea_runner/tasks/integration_test.yml +++ b/ansible/roles/gitea_runner/tasks/integration_test.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/pre_pull_images.yml b/ansible/roles/gitea_runner/tasks/pre_pull_images.yml index f543928..ed0f265 100644 --- a/ansible/roles/gitea_runner/tasks/pre_pull_images.yml +++ b/ansible/roles/gitea_runner/tasks/pre_pull_images.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/prune.yml b/ansible/roles/gitea_runner/tasks/prune.yml index 3494632..e668a67 100644 --- a/ansible/roles/gitea_runner/tasks/prune.yml +++ b/ansible/roles/gitea_runner/tasks/prune.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/register.yml b/ansible/roles/gitea_runner/tasks/register.yml index fd8c7d1..152d921 100644 --- a/ansible/roles/gitea_runner/tasks/register.yml +++ b/ansible/roles/gitea_runner/tasks/register.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/rootless_docker.yml b/ansible/roles/gitea_runner/tasks/rootless_docker.yml index 94b40c6..8f087dc 100644 --- a/ansible/roles/gitea_runner/tasks/rootless_docker.yml +++ b/ansible/roles/gitea_runner/tasks/rootless_docker.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/service.yml b/ansible/roles/gitea_runner/tasks/service.yml index 8b63486..62a02b9 100644 --- a/ansible/roles/gitea_runner/tasks/service.yml +++ b/ansible/roles/gitea_runner/tasks/service.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/update_runner.yml b/ansible/roles/gitea_runner/tasks/update_runner.yml index 5b306e7..dbd10f7 100644 --- a/ansible/roles/gitea_runner/tasks/update_runner.yml +++ b/ansible/roles/gitea_runner/tasks/update_runner.yml @@ -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 diff --git a/ansible/roles/gitea_runner/tasks/validate.yml b/ansible/roles/gitea_runner/tasks/validate.yml index 7a3327b..d6ba1f2 100644 --- a/ansible/roles/gitea_runner/tasks/validate.yml +++ b/ansible/roles/gitea_runner/tasks/validate.yml @@ -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