--- # SPDX-License-Identifier: AGPL-3.0-or-later # # shithubd-runner role: installs the runner binary, config, default # container image, and systemd unit. Docker itself is a host prerequisite. - name: Runner token is configured assert: that: - shithub_runner_token | length > 0 - shithub_runner_engine == "docker" fail_msg: >- shithub_runner_token is required and the Ansible role supports shithub_runner_engine=docker. Generate a token with `shithubd admin runner register`, store it in the inventory or vault, and keep Docker installed on the runner host. no_log: true - name: Runner workspace is inside the systemd write path assert: that: - (shithub_runner_workspace_root | string) is match("^/var/lib/shithubd-runner(/|$)") fail_msg: >- shithub_runner_workspace_root must stay under /var/lib/shithubd-runner unless the shithubd-runner systemd unit's ReadWritePaths= hardening is updated with the matching path. - name: Runner Docker bridge name fits Linux interface limit assert: that: - (shithub_runner_network_bridge | string | length) <= 15 fail_msg: >- shithub_runner_network_bridge must be 15 characters or fewer because Linux interface names are capped by IFNAMSIZ. - name: Docker group exists getent: database: group key: docker when: shithub_runner_engine == "docker" - name: Runner network firewall packages apt: name: - dnsmasq - ipset - iptables state: present update_cache: yes when: shithub_runner_engine == "docker" - name: Runner group group: name: shithub-runner system: yes - name: Runner user user: name: shithub-runner group: shithub-runner groups: docker append: yes system: yes create_home: no home: /var/lib/shithubd-runner shell: /usr/sbin/nologin - name: Runner directories file: path: "{{ item.path }}" state: directory owner: "{{ item.owner }}" group: "{{ item.group }}" mode: "{{ item.mode }}" loop: - { path: /etc/shithubd-runner, owner: root, group: shithub-runner, mode: "0750" } - { path: /var/lib/shithubd-runner, owner: shithub-runner, group: shithub-runner, mode: "0750" } - { path: "{{ shithub_runner_workspace_root }}", owner: shithub-runner, group: shithub-runner, mode: "0750" } - { path: /var/lib/shithubd-runner/binaries, owner: shithub-runner, group: shithub-runner, mode: "0750" } - name: Inspect Actions Docker network command: "{{ shithub_runner_engine }} network inspect {{ shithub_runner_network }}" register: shithub_runner_network_inspect failed_when: shithub_runner_network_inspect.rc not in [0, 1] changed_when: false when: shithub_runner_engine == "docker" and not ansible_check_mode - name: Create Actions Docker network command: >- {{ shithub_runner_engine }} network create --driver bridge --subnet {{ shithub_runner_network_subnet }} --gateway {{ shithub_runner_network_gateway }} --opt com.docker.network.bridge.name={{ shithub_runner_network_bridge }} {{ shithub_runner_network }} when: - shithub_runner_engine == "docker" - not ansible_check_mode - shithub_runner_network_inspect.rc == 1 - name: Inspect Actions Docker network after converge command: "{{ shithub_runner_engine }} network inspect {{ shithub_runner_network }}" register: shithub_runner_network_final changed_when: false when: shithub_runner_engine == "docker" and not ansible_check_mode - name: Record Actions Docker network facts set_fact: shithub_runner_network_info: "{{ (shithub_runner_network_final.stdout | from_json)[0] }}" when: shithub_runner_engine == "docker" and not ansible_check_mode - name: Actions Docker network matches runner firewall config assert: that: - shithub_runner_network_info.Driver == "bridge" - shithub_runner_network_info.Options["com.docker.network.bridge.name"] == shithub_runner_network_bridge - shithub_runner_network_info.IPAM.Config[0].Subnet == shithub_runner_network_subnet - shithub_runner_network_info.IPAM.Config[0].Gateway == shithub_runner_network_gateway fail_msg: >- Existing Docker network {{ shithub_runner_network }} does not match the configured Actions subnet/gateway/bridge. Remove or rename the network before re-running the role so firewall rules target the correct bridge. when: shithub_runner_engine == "docker" and not ansible_check_mode - name: Upload candidate shithubd-runner binary (built by `make build` locally) copy: src: "{{ playbook_dir }}/../../bin/shithubd-runner" dest: /var/lib/shithubd-runner/binaries/shithubd-runner-candidate mode: "0755" owner: root group: root - name: Candidate runner binary executes on target command: /var/lib/shithubd-runner/binaries/shithubd-runner-candidate version register: shithubd_runner_version changed_when: false - name: Promote candidate shithubd-runner binary copy: src: /var/lib/shithubd-runner/binaries/shithubd-runner-candidate dest: /usr/local/bin/shithubd-runner remote_src: true mode: "0755" owner: root group: root notify: restart shithubd-runner - name: Archive a versioned runner binary copy shell: cp /usr/local/bin/shithubd-runner /var/lib/shithubd-runner/binaries/shithubd-runner-$(date +%Y%m%d-%H%M%S) args: creates: /var/lib/shithubd-runner/binaries/shithubd-runner-{{ ansible_date_time.iso8601_basic_short }} - name: Runner config file template: src: config.toml.j2 dest: /etc/shithubd-runner/config.toml owner: root group: shithub-runner mode: "0640" notify: restart shithubd-runner - name: Runner env file template: src: runner.env.j2 dest: /etc/shithubd-runner/runner.env owner: shithub-runner group: shithub-runner mode: "0600" no_log: true notify: restart shithubd-runner - name: Runner seccomp profile copy: src: "{{ playbook_dir }}/../runner-config/seccomp.json" dest: "{{ shithub_runner_seccomp_profile }}" owner: root group: shithub-runner mode: "0640" notify: restart shithubd-runner - name: Runner DNS allowlist template template: src: "{{ playbook_dir }}/../runner-config/dnsmasq.conf.j2" dest: "{{ shithub_runner_dnsmasq_config }}" owner: root group: root mode: "0644" notify: restart dnsmasq - name: Runner firewall script template: src: "{{ playbook_dir }}/../runner-config/firewall.sh.j2" dest: "{{ shithub_runner_firewall_script }}" owner: root group: root mode: "0755" notify: restart shithub-runner-firewall - name: Runner firewall systemd unit copy: src: "{{ playbook_dir }}/../systemd/shithub-runner-firewall.service" dest: /etc/systemd/system/shithub-runner-firewall.service mode: "0644" notify: [daemon-reload, restart shithub-runner-firewall] - name: Enable + start runner firewall systemd: name: shithub-runner-firewall state: started enabled: yes daemon_reload: yes - name: Enable + start runner dnsmasq systemd: { name: dnsmasq, state: started, enabled: yes } - name: Runner systemd unit copy: src: "{{ playbook_dir }}/../systemd/shithubd-runner.service" dest: /etc/systemd/system/shithubd-runner.service mode: "0644" notify: [daemon-reload, restart shithubd-runner] - name: Pull default runner image command: "{{ shithub_runner_engine }} pull {{ shithub_runner_default_image }}" changed_when: false when: not ansible_check_mode - name: Enable + start shithubd-runner systemd: { name: shithubd-runner, state: started, enabled: yes }