Initial commit
Some checks failed
/ ansible-docsmith (push) Successful in 25s
/ molecule (certbot) (push) Failing after 59s
/ molecule (galene) (push) Failing after 1m7s
/ molecule (golang) (push) Failing after 1m11s

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2026-02-16 18:57:09 +01:00 committed by Julien Riou
commit e0bd2f80a9
Signed by: jriou
GPG key ID: 9A099EDA51316854
92 changed files with 3534 additions and 0 deletions

View file

@ -0,0 +1,118 @@
# Ansible Role Forgejo Runners
Ansible role to manage [Forgejo](https://forgejo.org/) runners.
## Configuration
See [Variable
precedence](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#ansible-variable-precedence)
to find where you should put your own variables.
Then define at least `forgejo_db_password` with a strong and secure password,
encrypted using
[ansible-vault](https://docs.ansible.com/ansible/latest/cli/ansible-vault.html).
## Table of Content
<!-- ANSIBLE DOCSMITH TOC START -->
* [Role variables](#variables)
* [`forgejo_runners_version`](#variable-forgejo_runners_version)
* [`forgejo_runners_config_dir`](#variable-forgejo_runners_config_dir)
* [`forgejo_runners_instance`](#variable-forgejo_runners_instance)
* [`forgejo_runners_settings`](#variable-forgejo_runners_settings)
<!-- ANSIBLE DOCSMITH TOC END -->
<!-- ANSIBLE DOCSMITH MAIN START -->
## Role variables<a id="variables"></a>
The following variables can be configured for this role:
| Variable | Type | Required | Default | Description (abstract) |
|----------|------|----------|---------|------------------------|
| `forgejo_runners_version` | `str` | No | `"9.1.1"` | Version of the runners |
| `forgejo_runners_config_dir` | `path` | No | `"/etc/forgejo-runners"` | Path to the configuration directory of the runners |
| `forgejo_runners_instance` | `str` | No | N/A | URL of the Forgejo instance to register the runners |
| `forgejo_runners_settings` | `dict` | No | N/A | Dict of runners to configure<br><br>The key is the name of the repository on the instance<br><br>The value is a dict with a `token` key and optionally a dict of `labels` |
### `forgejo_runners_version`<a id="variable-forgejo_runners_version"></a>
[*⇑ Back to ToC ⇑*](#toc)
Version of the runners
- **Type**: `str`
- **Required**: No
- **Default**: `"9.1.1"`
### `forgejo_runners_config_dir`<a id="variable-forgejo_runners_config_dir"></a>
[*⇑ Back to ToC ⇑*](#toc)
Path to the configuration directory of the runners
- **Type**: `path`
- **Required**: No
- **Default**: `"/etc/forgejo-runners"`
### `forgejo_runners_instance`<a id="variable-forgejo_runners_instance"></a>
[*⇑ Back to ToC ⇑*](#toc)
URL of the Forgejo instance to register the runners
- **Type**: `str`
- **Required**: No
### `forgejo_runners_settings`<a id="variable-forgejo_runners_settings"></a>
[*⇑ Back to ToC ⇑*](#toc)
Dict of runners to configure
The key is the name of the repository on the instance
The value is a dict with a `token` key and optionally a dict of `labels`
- **Type**: `dict`
- **Required**: No
<!-- ANSIBLE DOCSMITH MAIN END -->
## Usage
Example of a basic playbook:
```yaml
- hosts: forgejo_runners
roles:
- forgejo_runners
vars:
forgejo_runners_instance: https://codeberg.org # FIXME
forgejo_runners:
my_runner:
token: **redacted**
labels:
node-latest: docker://data.forgejo.org/oci/node:latest
```
Then run the playbook:
```
ansible-playbook forgejo_runners.yml
```
## Donate
As we all love FOSS projects, you should consider [donating to
Codeberg](https://donate.codeberg.org/), the non-profit organization behind
Forgejo.

View file

@ -0,0 +1 @@
Focus on runners only

View file

@ -0,0 +1,25 @@
---
# Version of the runners
#
# - Type: str
# - Required: No
# - Default: 9.1.1
forgejo_runners_version: 9.1.1
# Path to the configuration directory of the runners
#
# - Type: path
# - Required: No
# - Default: /etc/forgejo-runners
forgejo_runners_config_dir: /etc/forgejo-runners
# Dict of runners to configure
#
# The key is the name of the repository on the instance
#
# The value is a dict with a `token` key and optionally a dict of `labels`
#
# - Type: dict
# - Required: No
forgejo_runners_settings: {}

View file

@ -0,0 +1,17 @@
---
- name: save iptables
ansible.builtin.shell:
cmd: netfilter-persistent save
- name: start runners
community.docker.docker_compose_v2:
project_src: "{{ forgejo_runners_config_dir }}"
files:
- docker-compose.yml
- name: restart runners
community.docker.docker_compose_v2:
project_src: "{{ forgejo_runners_config_dir }}"
files:
- docker-compose.yml
state: restarted

View file

@ -0,0 +1,30 @@
---
argument_specs:
main:
short_description: Install and configure Forgejo runners
description:
- Install and configure [Forgejo](https://forgejo.org/) runners.
author:
- jriou
options:
forgejo_runners_version:
description:
- Version of the runners
default: 9.1.1
forgejo_runners_config_dir:
description:
- Path to the configuration directory of the runners
type: path
default: /etc/forgejo-runners
forgejo_runners_instance:
description:
- URL of the Forgejo instance to register the runners
forgejo_runners_settings:
description:
- Dict of runners to configure
- The key is the name of the repository on the instance
- The value is a dict with a `token` key and optionally a dict of `labels`
type: dict

View file

@ -0,0 +1,3 @@
---
dependencies:
- role: geerlingguy.docker

View file

@ -0,0 +1,20 @@
---
- name: register runners
ansible.builtin.include_tasks: register-runner.yml
loop: "{{ forgejo_runners | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: create runners configuration
ansible.builtin.template:
src: "runners/docker-compose.yml.j2"
dest: "{{ forgejo_runners_config_dir }}/docker-compose.yml"
owner: root
group: root
mode: "0644"
- name: start runners service
community.docker.docker_compose_v2:
project_src: "{{ forgejo_runners_config_dir }}"
files:
- docker-compose.yml

View file

@ -0,0 +1,61 @@
---
- name: check database password
ansible.builtin.assert:
that: forgejo_db_password is defined
- name: create directories
ansible.builtin.file:
state: directory
path: "{{ item }}"
owner: forgejo
group: forgejo
mode: "0755"
loop: &forgejo_directories
- "{{ forgejo_config_dir }}"
- "{{ forgejo_home_dir }}"
- "{{ forgejo_home_dir }}/server"
- "{{ forgejo_home_dir }}/db"
- name: ensure permissions on those directories
ansible.builtin.command:
cmd: "chown -R forgejo:forgejo {{ item }}"
loop: *forgejo_directories
- name: create docker-compose configuration
ansible.builtin.template:
src: "{{ item.name }}.j2"
dest: "{{ forgejo_config_dir }}/{{ item.name }}"
owner: root
group: root
mode: "{{ item.mode }}"
loop:
- name: docker-compose.yml
mode: "0644"
- name: server.env
mode: "0600"
- name: db.env
mode: "0600"
- name: start service
community.docker.docker_compose_v2:
project_src: "{{ forgejo_config_dir }}"
files:
- docker-compose.yml
- name: allow with iptables
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
source: "{{ item }}"
destination_ports:
- "{{ forgejo_web_port }}"
- "{{ forgejo_ssh_port }}"
jump: ACCEPT
comment: forgejo
loop: "{{ forgejo_allowed_sources }}"
notify: save iptables
when: forgejo_manage_iptables
- name: deploy runners
ansible.builtin.include_tasks: deploy-runners.yml
when: forgejo_runners

View file

@ -0,0 +1,21 @@
---
- name: add forgejo user
ansible.builtin.user:
name: forgejo
system: yes
password: '!'
home: "{{ forgejo_home_dir }}"
create_home: no
- name: read forgejo attributes
ansible.builtin.getent:
database: passwd
key: forgejo
- name: deploy server
ansible.builtin.include_tasks: deploy-server.yml
when: forgejo_server
- name: deploy runners
ansible.builtin.include_tasks: deploy-runners.yml
when: forgejo_runners is defined

View file

@ -0,0 +1,39 @@
---
- name: check variables
ansible.builtin.assert:
that:
- forgejo_runners_instance is defined
- forgejo_runners_version is defined
- forgejo_runners_config_dir is defined
- "'key' in item"
- "'value' in item"
- name: create runner subdirectory
ansible.builtin.file:
path: "{{ forgejo_runners_config_dir }}/{{ item.key }}"
state: directory
mode: "0755"
owner: forgejo
group: forgejo
- name: register runner
ansible.builtin.command:
cmd: >-
docker run
-v /var/run/docker.sock:/var/run/docker.sock
-v {{ forgejo_runners_config_dir }}/{{ item.key }}:/data
--rm
--user {{ ansible_facts.getent_passwd.forgejo[1] }}:{{ ansible_facts.getent_passwd.forgejo[2] }}
code.forgejo.org/forgejo/runner:{{ forgejo_runners_version }}
forgejo-runner register --no-interactive
--token {{ item.value.token }}
--name {{ item.key }}
--instance {{ forgejo_runners_instance }}
creates: "{{ forgejo_runners_config_dir }}/{{ item.key }}/.runner"
notify: start runners
- name: create runner configuration
ansible.builtin.template:
src: runners/config.yml.j2
dest: "{{ forgejo_runners_config_dir }}/{{ item.key }}/config.yml"
notify: restart runners

View file

@ -0,0 +1,6 @@
{{ ansible_managed | comment }}
POSTGRES_USER="{{ forgejo_db_username }}"
POSTGRES_PASSWORD="{{ forgejo_db_password }}"
POSTGRES_DB="{{ forgejo_db_database }}"
POSTGRES_INITDB_ARGS="--data-checksums"
POSTGRES_HOST_AUTH_METHOD=scram-sha-256

View file

@ -0,0 +1,35 @@
---
{{ ansible_managed | comment }}
services:
server:
image: codeberg.org/forgejo/forgejo:{{ forgejo_version }}
container_name: forgejo-server
env_file: {{ forgejo_config_dir }}/server.env
restart: always
networks:
- forgejo
volumes:
- "{{ forgejo_home_dir }}/server:/data"
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "{{ forgejo_web_port }}:3000"
- "{{ forgejo_ssh_port }}:22"
depends_on:
- db
db:
image: postgres:17
hostname: db
container_name: forgejo-db
restart: always
env_file: {{ forgejo_config_dir }}/db.env
user: "{{ ansible_facts.getent_passwd.forgejo[1] }}:{{ ansible_facts.getent_passwd.forgejo[2] }}"
networks:
- forgejo
volumes:
- "{{ forgejo_home_dir }}/db:/var/lib/postgresql/data"
networks:
forgejo:
external: false

View file

@ -0,0 +1,44 @@
{{ ansible_managed | comment }}
log:
level: info
job_level: info
runner:
file: .runner
capacity: 1
timeout: 3h
shutdown_timeout: 3h
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
report_interval: 1s
{% if item.value.labels | default({}) %}
labels:
{% for label_name, label_value in item.value.labels.items() %}
- "{{ label_name }}:{{ label_value }}"
{% endfor %}
{% endif %}
cache:
enabled: true
port: 0
dir: ""
external_server: ""
secret: ""
host: ""
proxy_port: 0
actions_cache_url_override: ""
container:
network: ""
enable_ipv6: false
privileged: false
options:
workdir_parent:
valid_volumes: []
docker_host: "-"
force_pull: false
force_rebuild: false
host:
workdir_parent:

View file

@ -0,0 +1,27 @@
---
{{ ansible_managed | comment }}
services:
docker:
image: docker:dind
privileged: true
restart: always
volumes:
- certs:/certs
{% for runner in forgejo_runners %}
runner-{{ runner }}:
image: code.forgejo.org/forgejo/runner:{{ forgejo_runners_version }}
user: {{ ansible_facts.getent_passwd.forgejo[1] }}:{{ ansible_facts.getent_passwd.forgejo[2] }}
environment:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_VERIFY: 1
DOCKER_CERT_PATH: /certs/client
restart: always
volumes:
- {{ forgejo_runners_config_dir }}/{{ runner }}:/data
- certs:/certs
command: 'forgejo-runner --config config.yml daemon'
{% endfor %}
volumes:
certs:

View file

@ -0,0 +1,19 @@
{{ ansible_managed | comment }}
USER_UID={{ ansible_facts.getent_passwd.forgejo[1] }}
USER_GID={{ ansible_facts.getent_passwd.forgejo[2] }}
FORGEJO__server__SSH_PORT={{ forgejo_ssh_port }}
FORGEJO__database__DB_TYPE=postgres
FORGEJO__database__HOST=db:5432
FORGEJO__database__NAME="{{ forgejo_db_database }}"
FORGEJO__database__USER="{{ forgejo_db_username }}"
FORGEJO__database__PASSWD="{{ forgejo_db_password }}"
{% if forgejo_mailer %}
{% for k, v in forgejo_mailer.items() %}
FORGEJO__mailer__{{ k | upper }}="{{ v }}"
{% endfor %}
{% endif %}
{% if forgejo_service %}
{% for k, v in forgejo_service.items() %}
FORGEJO__service__{{ k | upper }}="{{ v }}"
{% endfor %}
{% endif %}