diff --git a/roles/docker/README.md b/roles/docker/README.md index b7f38e1..0a28265 100644 --- a/roles/docker/README.md +++ b/roles/docker/README.md @@ -16,7 +16,10 @@ None. ## Optional Arguments -None. +- `docker__gvisor_setup`: Whether or not to set up [gVisor](https://gvisor.dev/) (`runsc` runtime). + > Note: gVisor doesn't work with the embedded DNS server Docker forces for user-defined bridges (see the [relevant GitHub issue](https://github.com/google/gvisor/issues/7469)). A workaround would be to bind mount a `resolv.conf` not relying on localhost DNS (note however that this still doesn't provide local container name resolution). When enabling this option such a helper `resolv.conf` pointing to Quad9 gets deployed to `/etc/gvisor-helper-resolv.conf` for bind-mounting. See the file for usage instructions. + + Defaults to `false`. ## Links & Resources diff --git a/roles/docker/defaults/main.yaml b/roles/docker/defaults/main.yaml new file mode 100644 index 0000000..351f397 --- /dev/null +++ b/roles/docker/defaults/main.yaml @@ -0,0 +1 @@ +docker__gvisor_setup: false diff --git a/roles/docker/files/gvisor-helper-resolv.conf b/roles/docker/files/gvisor-helper-resolv.conf new file mode 100644 index 0000000..f047a80 --- /dev/null +++ b/roles/docker/files/gvisor-helper-resolv.conf @@ -0,0 +1,9 @@ +# resolv.conf pointing to Quad9 for bind-mounting into containers on user-defined bridges and using the gVisor runsc runtime. +# Example: docker run --runtime runsc --mount type=bind,src=/etc/gvisor-helper-resolv.conf,dst=/etc/resolv.conf,ro=true --network your-user-defined-network -it --rm docker.io/library/debian /bin/bash + +nameserver 9.9.9.9 +nameserver 149.112.112.112 +nameserver 2620:fe::fe +nameserver 2620:fe::9 + +options edns0 diff --git a/roles/docker/handlers/main.yaml b/roles/docker/handlers/main.yaml index ada2426..6c37581 100644 --- a/roles/docker/handlers/main.yaml +++ b/roles/docker/handlers/main.yaml @@ -2,3 +2,9 @@ ansible.builtin.systemd_service: daemon_reload: true become: true + +- name: restart the docker service + ansible.builtin.systemd: + name: docker.service + state: restarted + become: true diff --git a/roles/docker/meta/argument_specs.yaml b/roles/docker/meta/argument_specs.yaml new file mode 100644 index 0000000..6549387 --- /dev/null +++ b/roles/docker/meta/argument_specs.yaml @@ -0,0 +1,6 @@ +argument_specs: + main: + options: + docker__gvisor_setup: + type: bool + required: false diff --git a/roles/docker/tasks/main/01_repo_setup.yaml b/roles/docker/tasks/main/01_repo_setup.yaml index 63bdb91..6105627 100644 --- a/roles/docker/tasks/main/01_repo_setup.yaml +++ b/roles/docker/tasks/main/01_repo_setup.yaml @@ -1,15 +1,36 @@ -- name: Ensure Dockers GPG key is added - ansible.builtin.get_url: - url: https://download.docker.com/linux/debian/gpg - dest: /etc/apt/trusted.gpg.d/docker.asc - mode: "0644" - owner: root - group: root - become: true +- name: ensure Docker repo + block: + - name: Ensure Dockers GPG key is added + ansible.builtin.get_url: + url: https://download.docker.com/linux/debian/gpg + dest: /etc/apt/trusted.gpg.d/docker.asc + mode: "0644" + owner: root + group: root + become: true -- name: Ensure Docker APT repository is added - ansible.builtin.apt_repository: - repo: "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/docker.asc] https://download.docker.com/linux/debian {{ ansible_facts['distribution_release'] }} stable" - filename: docker - state: present - become: true + - name: Ensure Docker APT repository is added + ansible.builtin.apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/docker.asc] https://download.docker.com/linux/debian {{ ansible_facts['distribution_release'] }} stable" + filename: docker + state: present + become: true + +- name: ensure gVisor repo + when: docker__gvisor_setup + block: + - name: Ensure gVisors GPG key is added + ansible.builtin.get_url: + url: https://gvisor.dev/archive.key + dest: /etc/apt/keyrings/gvisor.asc + mode: "0644" + owner: root + group: root + become: true + + - name: Ensure gVisors APT repository is added + ansible.builtin.apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/gvisor.asc] https://storage.googleapis.com/gvisor/releases release main" + filename: gvisor + state: present + become: true diff --git a/roles/docker/tasks/main/02_docker_install.yaml b/roles/docker/tasks/main/02_docker_install.yaml index f2ae880..b7334e1 100644 --- a/roles/docker/tasks/main/02_docker_install.yaml +++ b/roles/docker/tasks/main/02_docker_install.yaml @@ -9,3 +9,12 @@ state: present update_cache: true become: true + +- name: Ensure gVisors packages are installed + when: docker__gvisor_setup + ansible.builtin.apt: + name: + - runsc + state: present + update_cache: true + become: true diff --git a/roles/docker/tasks/main/03_docker_config.yaml b/roles/docker/tasks/main/03_docker_config.yaml index 639e8fa..8c145b2 100644 --- a/roles/docker/tasks/main/03_docker_config.yaml +++ b/roles/docker/tasks/main/03_docker_config.yaml @@ -2,10 +2,21 @@ # - log to systemd journal # https://docs.docker.com/engine/logging/drivers/journald/ - name: Ensure Docker daemon configuration - ansible.builtin.copy: - src: daemon.json + ansible.builtin.template: + src: daemon.json.j2 dest: /etc/docker/daemon.json owner: root group: root mode: "0644" become: true + notify: restart the docker service + +- name: Ensure helper gVisor resolv.conf is deployed + when: docker__gvisor_setup + ansible.builtin.copy: + src: gvisor-helper-resolv.conf + dest: /etc/gvisor-helper-resolv.conf + owner: root + group: root + mode: "0644" + become: true diff --git a/roles/docker/files/daemon.json b/roles/docker/templates/daemon.json.j2 similarity index 59% rename from roles/docker/files/daemon.json rename to roles/docker/templates/daemon.json.j2 index d55e4cb..b6f6025 100644 --- a/roles/docker/files/daemon.json +++ b/roles/docker/templates/daemon.json.j2 @@ -1,7 +1,7 @@ { "log-driver": "journald", "log-opts": { - "tag": "{{.Name}}" + "tag": "{{ '{{.Name}}' }}" }, "ipv6": true, "ip6tables": true, @@ -10,5 +10,10 @@ "bridge": { "com.docker.network.enable_ipv6":"true" } - } + }{% if docker__gvisor_setup %}, + "runtimes": { + "runsc": { + "path": "/usr/bin/runsc" + } + }{% endif %} } diff --git a/roles/forgejo_runner/README.md b/roles/forgejo_runner/README.md new file mode 100644 index 0000000..ed53e8b --- /dev/null +++ b/roles/forgejo_runner/README.md @@ -0,0 +1,9 @@ +# `forgejo_runner` + +Ensures Forgejo Runner is installed and set up. +See: https://forgejo.org/docs/latest/admin/actions/ + +## Required Arguments + +- `forgejo_runner__config`: The configuration to run the Forgejo Runner with. + A configuration can be generated using `forgejo-runner generate-config`. Also see the [relevant docs](https://forgejo.org/docs/latest/admin/actions/configuration/). diff --git a/roles/forgejo_runner/files/EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc b/roles/forgejo_runner/files/EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc new file mode 100644 index 0000000..b18e74c --- /dev/null +++ b/roles/forgejo_runner/files/EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc @@ -0,0 +1,71 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: EB11 4F5E 6C0D C2BC DD18 3550 A4B6 1A2D C592 3710 +Comment: Forgejo +Comment: Forgejo Releases + +xjMEY3T/yhYJKwYBBAHaRw8BAQdAVxqCQrSbpDNrx8CiTM8PUAVqdCyv2UmBDhpP +HZIpoIDNHUZvcmdlam8gPGNvbnRhY3RAZm9yZ2Vqby5vcmc+wsB+BBMWCgDmAhsD +BQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEE6xFPXmwNwrzdGDVQpLYaLcWS +NxAFAmSc08VBFIAAAAAAEAAocHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vY29kZWJl +cmcub3JnL2Zvcmdlam8vZ2l0ZWFfcHJvb2Y2FIAAAAAAEAAdcHJvb2ZAYXJpYWRu +ZS5pZGh0dHBzOi8vZmxvc3Muc29jaWFsL0Bmb3JnZWpvMRSAAAAAABAAGHByb29m +QGFyaWFkbmUuaWRkbnM6Zm9yZ2Vqby5vcmc/dHlwZT1UWFQACgkQpLYaLcWSNxDM +2wEA6bOel3R25z3YUXL4hI2S8jRkJbOQawq0vgUnYNgS9hcBAK2zq4Zt4ctvSB+x +TqhR6Zi6aqSD3QrRnUVvV1xZhdkEwsCABBMWCgDoAhsDBQsJCAcDBRUKCQgLBRYC +AwEAAh4BAheAAhkBFiEE6xFPXmwNwrzdGDVQpLYaLcWSNxAFAmScz7JDFIAAAAAA +EAAqcHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vY29kZWJlcmcub3JnL2Zvcmdlam8v +Zm9yZ2Vqb19wcm9vZjYUgAAAAAAQAB1wcm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9m +bG9zcy5zb2NpYWwvQGZvcmdlam8xFIAAAAAAEAAYcHJvb2ZAYXJpYWRuZS5pZGRu +czpmb3JnZWpvLm9yZz90eXBlPVRYVAAKCRCkthotxZI3EBJ1AP9UeN1HFGz90r34 +PGrOj1225HfJzdWgamEUkEKEwShcIQD+K/o7sLJM+C/mJXaCixAZgvRd9/rYq27T +9Y2rTQybSwnCwH4EExYKAOYCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4ACGQEW +IQTrEU9ebA3CvN0YNVCkthotxZI3EAUCY3spkjYUgAAAAAAQAB1wcm9vZkBhcmlh +ZG5lLmlkaHR0cHM6Ly9mbG9zcy5zb2NpYWwvQGZvcmdlam8xFIAAAAAAEAAYcHJv +b2ZAYXJpYWRuZS5pZGRuczpmb3JnZWpvLm9yZz90eXBlPVRYVEEUgAAAAAAQAChw +cm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9jb2RlYmVyZy5vcmcvZm9yZ2Vqby9naXRl +YV9wcm9vZgAKCRCkthotxZI3EC+hAQCxsUupyqMChFMqk/74PqzSlmCd6RXtbezP +W66YostSbgD9G+N+c9or1cBkcSejREOSy7TFrDrvek+ZhdZVhCp1UALCwEcEExYK +AK8CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4ACGQEWIQTrEU9ebA3CvN0YNVCk +thotxZI3EAUCY3inA0EUgAAAAAAQAChwcm9vZkBhcmlhZG5lLmlkaHR0cHM6Ly9j +b2RlYmVyZy5vcmcvZm9yZ2Vqby9naXRlYV9wcm9vZjEUgAAAAAAQABhwcm9vZkBh +cmlhZG5lLmlkZG5zOmZvcmdlam8ub3JnP3R5cGU9VFhUAAoJEKS2Gi3FkjcQNV8B +AJfcHBzskW78lJVJeQwCI70qorOhC/QUp80jjNzs5lO7AQCujYgrae3vZb/476sc +wM33ufSpBguNwTLbCI6C5g8+B80mRm9yZ2VqbyBSZWxlYXNlcyA8cmVsZWFzZUBm +b3JnZWpvLm9yZz7CkAQTFgoAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYh +BOsRT15sDcK83Rg1UKS2Gi3FkjcQBQJjeKH0AAoJEKS2Gi3FkjcQC5YBAKwCGFDD +SpX0JwBrzIP8W8ElwHvdBz2XDg8LwyQgr722AP9r01rbFwY4axDxpNj+BUFxwD5F +hza1cE3932eTsSOPDsKQBBMWCAA4FiEE6xFPXmwNwrzdGDVQpLYaLcWSNxAFAmN4 +k+kCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQpLYaLcWSNxBHrQD+PFo/ +ii8p72HP0KsJbHPGnS/Sk9pFGd16fs1Hd88JHj0A/10XNyGQgwbe+X+K/a97vWW8 +vAzA1EtFIMfCGhIO8EoIzjMEY3UANBYJKwYBBAHaRw8BAQdAKvAs2Ij2RamYUzz4 +sBgsc2J+4fEwvSMcTp6rPZizRhfCwDUEGBYIACYWIQTrEU9ebA3CvN0YNVCkthot +xZI3EAUCY3UANAIbAgUJAeEzgACBCRCkthotxZI3EHYgBBkWCAAdFiEE98vwIJTn +Zl4X7WxE44G/PlDVNwcFAmN1ADQACgkQ44G/PlDVNwdIlgD+K15nuEec+VTFdP7Y +Y3SxM8Rjg2EtXk007+LM7XQfN9sBAOLjBTzIdaaKOpoAkGQ9Th/IphSUOnPYZVO5 +a6cN+wAM458A/itf3urQehI5SbKtbRqIDhqQZQVAcEeG2eQFunuofjDWAQDt/gE5 +XgTiQgnkTcqAX7GQeE74O/Q5vDtX10NjbzV7D84zBGeOav0WCSsGAQQB2kcPAQEH +QI2JXHjIx25g9WZHNyjkdUiRBPl5Y1JjjJCPvXM0/9RjwsA1BBgWCAAmFiEE6xFP +XmwNwrzdGDVQpLYaLcWSNxAFAmeOav0CGwIFCQO1OAAAgQkQpLYaLcWSNxB2IAQZ +FggAHRYhBA9SfPk6PQ0JJdPFXtCoIAUOFgnlBQJnjmr9AAoJENCoIAUOFgnljUwA ++wSjU/mk4xGIlwzJdPnnNzIsiMeqtuYokbSrOIxXIhP1AP93qtVr+kOu3pDs9JC+ +8CYG0DK1QD1LmlGP59WRGevSCXChAQDy6SCfnfcr5P4fYaz04+Tl0CDUkFOGP+sV +S/isPTssbAD9H2hKJKEmwuAd2MeFA3Bo3z5rUVWkfAcnv7Oy7u+OWQfOMwRlfHnh +FgkrBgEEAdpHDwEBB0DGoKPPOOx7rnqT318eykUkMJbk83MhcBqrecOADO3i2sLA +NQQYFggAJhYhBOsRT15sDcK83Rg1UKS2Gi3FkjcQBQJlfHnhAhsCBQkCx+oAAIEJ +EKS2Gi3FkjcQdiAEGRYIAB0WIQTfMxnqNtWZwdSmg9SzsfYKxXfyogUCZXx54QAK +CRCzsfYKxXfyoocRAP48OQpiBTkwC7kLLyuqVlP1t0hBQddr4i4rIV8Ug5tHzwEA +pl8Q+S4k/ROQS5FOhy7GBC337SncJFJYDD0pTcSecw+J3AEAn4qax72Oyfb0vaPY +m+WdqsfVBd2Hd2vJIwCjglp55B0BALIJE6nvACcKzTRUj7AQSLGvELGfJfM320xX +E0ZVBZkKzjMEaUFtxRYJKwYBBAHaRw8BAQdA1AZR9j6PksmArHjaoqOHIOQ4H1iw +0KZyLKLgu1onR8fCwDUEGBYIACYWIQTrEU9ebA3CvN0YNVCkthotxZI3EAUCaUFt +xQIbAgUJAsfqAACBCRCkthotxZI3EHYgBBkWCAAdFiEEO/ToE/hIEkEdoB5bxBht +9m9LZ1AFAmlBbcUACgkQxBht9m9LZ1DQHAD9EUEM23tJJUae0L1DbGnWEp3GnZOQ +G3Z34uWv16wRV3EA+gJuHa9Zr1TXAEXXBwQzZIrAFby+7I5smWPVM84c7xYA/qEA +/2dQMMZcRelFC0fIPvGQMGfYeBr8bkHKlJBQOTdukeSPAQCcd9rqJT7NNZlPtJ1T +wNAfAa3L23bdp/dEtKhE+d09CM44BGN0/8oSCisGAQQBl1UBBQEBB0CZnRfIHxTV +hOF8kdhbe4YJsePyVFi8USfuDXy4HgIHRgMBCAfCeAQYFggAIBYhBOsRT15sDcK8 +3Rg1UKS2Gi3FkjcQBQJjdP/KAhsMAAoJEKS2Gi3FkjcQdroA/jHFqt7y/r/5zdK4 +TYYp+5jlOgM5ZI7pNhWhtIFbqmx9AQCKSJf2YgPBLNJSL/86vpE9b6IvTE/8ENR/ +7xYaIA7oAg== +=D+4T +-----END PGP PUBLIC KEY BLOCK----- diff --git a/roles/forgejo_runner/files/forgejo-runner.service b/roles/forgejo_runner/files/forgejo-runner.service new file mode 100644 index 0000000..0e33bcd --- /dev/null +++ b/roles/forgejo_runner/files/forgejo-runner.service @@ -0,0 +1,19 @@ +# Source: https://code.forgejo.org/forgejo/runner/src/branch/main/contrib/forgejo-runner.service +[Unit] +Description=Forgejo Runner +Documentation=https://forgejo.org/docs/latest/admin/actions/ +After=docker.service +Requires=docker.service + +[Service] +ExecStart=/usr/local/bin/forgejo-runner daemon -c /etc/forgejo-runner-config.yaml +ExecReload=/bin/kill -s HUP $MAINPID + +User=runner +WorkingDirectory=/home/runner +Restart=on-failure +TimeoutSec=0 +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/roles/forgejo_runner/handlers/main.yaml b/roles/forgejo_runner/handlers/main.yaml new file mode 100644 index 0000000..3234eb2 --- /dev/null +++ b/roles/forgejo_runner/handlers/main.yaml @@ -0,0 +1,10 @@ +- name: systemd daemon reload + ansible.builtin.systemd_service: + daemon_reload: true + become: true + +- name: restart the forgejo-runner service + ansible.builtin.systemd: + name: forgejo-runner.service + state: restarted + become: true diff --git a/roles/forgejo_runner/meta/argument_specs.yaml b/roles/forgejo_runner/meta/argument_specs.yaml new file mode 100644 index 0000000..5c7570e --- /dev/null +++ b/roles/forgejo_runner/meta/argument_specs.yaml @@ -0,0 +1,6 @@ +argument_specs: + main: + options: + forgejo_runner__config: + type: str + required: true diff --git a/roles/forgejo_runner/meta/main.yaml b/roles/forgejo_runner/meta/main.yaml new file mode 100644 index 0000000..cb7d8e0 --- /dev/null +++ b/roles/forgejo_runner/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: docker diff --git a/roles/forgejo_runner/tasks/main.yaml b/roles/forgejo_runner/tasks/main.yaml new file mode 100644 index 0000000..281f665 --- /dev/null +++ b/roles/forgejo_runner/tasks/main.yaml @@ -0,0 +1,7 @@ +- name: Ensure Forgejo Runner is installed + ansible.builtin.import_tasks: + file: main/01_install.yaml + +- name: Ensure Forgejo Runner is set up + ansible.builtin.import_tasks: + file: main/02_setup.yaml diff --git a/roles/forgejo_runner/tasks/main/01_install.yaml b/roles/forgejo_runner/tasks/main/01_install.yaml new file mode 100644 index 0000000..cb309a6 --- /dev/null +++ b/roles/forgejo_runner/tasks/main/01_install.yaml @@ -0,0 +1,96 @@ +- name: get latest release info + ansible.builtin.uri: + url: "https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest" + return_content: true + register: forgejo_runner__latest_release_info + +- name: set latest version + ansible.builtin.set_fact: + forgejo_runner__latest_version: "{{ forgejo_runner__latest_release_info.json.name | replace('v', '') }}" + +- name: set latest version forgejo-runner binary path + ansible.builtin.set_fact: + forgejo_runner__latest_version_binary_path: "/usr/local/bin/forgejo-runner-{{ forgejo_runner__latest_version }}" + +- name: check if latest version forgejo-runner binary is installed already + ansible.builtin.stat: + path: "{{ forgejo_runner__latest_version_binary_path }}" + register: forgejo_runner_latest_version_binary_stat + +- name: download and install latest version, if not already present + when: not forgejo_runner_latest_version_binary_stat.stat.exists + block: + - name: set download url + ansible.builtin.set_fact: + forgejo_runner__download_url: "https://code.forgejo.org/forgejo/runner/releases/download/v{{ forgejo_runner__latest_version }}/forgejo-runner-{{ forgejo_runner__latest_version }}-linux-amd64" + + - name: temporary directory for download + ansible.builtin.tempfile: + state: directory + suffix: forgejo_runner_download + become: true + register: forgejo_runner__download_tempdir + + - name: download the forgejo-runner binary + ansible.builtin.get_url: + url: "{{ forgejo_runner__download_url }}" + dest: "{{ forgejo_runner__download_tempdir.path }}/forgejo-runner" + owner: root + group: root + mode: "0755" + become: true + + - name: download the signature + ansible.builtin.get_url: + url: "{{ forgejo_runner__download_url }}.asc" + dest: "{{ forgejo_runner__download_tempdir.path }}/forgejo-runner.asc" + owner: root + group: root + mode: "0644" + become: true + + - name: copy key for verification + ansible.builtin.copy: + src: "EB114F5E6C0DC2BCDD183550A4B61A2DC5923710.asc" + dest: "{{ forgejo_runner__download_tempdir.path }}/forgejo-runner-key.asc" + owner: root + group: root + mode: "0644" + become: true + + - name: ensure sq (Sequoia-PGP) is installed + ansible.builtin.apt: + name: sq + become: true + + - name: verify signature + ansible.builtin.command: + cmd: /usr/bin/sq verify --signer-file ./forgejo-runner-key.asc --signature-file forgejo-runner.asc --signatures 1 forgejo-runner + chdir: "{{ forgejo_runner__download_tempdir.path }}" + become: true + changed_when: false + + - name: install forgejo-runner binary of this latest version + ansible.builtin.copy: + remote_src: true + src: "{{ forgejo_runner__download_tempdir.path }}/forgejo-runner" + dest: "{{ forgejo_runner__latest_version_binary_path }}" + owner: root + group: root + mode: "0755" + become: true + + - name: ensure symlink points to binary of this latest version + ansible.builtin.file: + src: "{{ forgejo_runner__latest_version_binary_path }}" + dest: "/usr/local/bin/forgejo-runner" + state: link + owner: root + group: root + become: true + always: + - name: delete temporary download directory + ansible.builtin.file: + path: "{{ forgejo_runner__download_tempdir.path }}" + state: absent + become: true diff --git a/roles/forgejo_runner/tasks/main/02_setup.yaml b/roles/forgejo_runner/tasks/main/02_setup.yaml new file mode 100644 index 0000000..c83c057 --- /dev/null +++ b/roles/forgejo_runner/tasks/main/02_setup.yaml @@ -0,0 +1,46 @@ +- name: ensure runner group exists + ansible.builtin.group: + name: runner + system: true + become: true + +- name: ensure runner user exists + ansible.builtin.user: + name: runner + group: runner + password: '!' + system: true + create_home: true + groups: + - docker + become: true + +- name: ensure the configuration is deployed + ansible.builtin.copy: + content: "{{ forgejo_runner__config }}" + dest: /etc/forgejo-runner-config.yaml + owner: root + group: runner + mode: "0640" + become: true + notify: + - restart the forgejo-runner service + +- name: ensure systemd service exists + ansible.builtin.copy: + src: forgejo-runner.service + dest: /etc/systemd/system/forgejo-runner.service + owner: root + group: root + mode: "0644" + become: true + notify: + - systemd daemon reload + - restart the forgejo-runner service + +- name: ensure systemd service is started and enabled + ansible.builtin.systemd_service: + name: forgejo-runner.service + state: started + enabled: true + become: true