1
0

add forgejo-runner provisioning and installation

This commit is contained in:
cuqmbr 2025-07-01 23:33:13 +03:00
parent 19cf4294d4
commit 993fc0b1d0
Signed by: cuqmbr
GPG Key ID: 1F62396D020F375C
19 changed files with 612 additions and 0 deletions

View File

@ -1,3 +1,4 @@
### Todo ### Todo
- Create role for installing and configuring Valkey - Create role for installing and configuring Valkey
- Add docker role to forgejo_runner role dependency lis

View File

@ -0,0 +1,17 @@
---
- hosts: forgejo_runner
gather_facts: false
pre_tasks:
- name: Update apt cache.
ansible.builtin.apt:
update_cache: true
cache_valid_time: 86400
roles:
- role: roles/init
- role: roles/fluent_bit
- role: roles/prometheus_node_exporter
- role: roles/docker
- role: roles/forgejo_runner

View File

@ -66,6 +66,12 @@ prometheus_options:
labels: labels:
env: dev env: dev
hostname: forgejo hostname: forgejo
- targets:
# forgejo
- 192.168.0.21:9100
labels:
env: dev
hostname: forgejo-runner
- targets: - targets:
# bastion # bastion
- 192.168.0.254:9100 - 192.168.0.254:9100

View File

@ -0,0 +1,75 @@
---
users:
- name: admin
password_hash: !vault |
$ANSIBLE_VAULT;1.1;AES256
30623138653735643561343061356531373430393662383764633038383238383837626636393432
3138653539356430306266663864343563616332656131310a343632323363653665646363366437
66643430626437333461656231303339656435346261336238313036306431396333643965666631
3665393163623266320a373838313538626438623330393533353931336331623464613664633430
32303734396634376431383936643431313561303864343930393363623130663236666636353637
63613237383666656263316661333031643032323266636464313839653065316138343035346161
64313037336666353136383462333832373031623637636630326330313832333265386632343139
30306638356434376635346637346134653064613236326333656566383137353166393063333563
32623638343263313463313062303465626439356461613235656661623364656138
ssh_public_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKNzJdo6/c7uXrg0lqVwyXOhcNxO/BnylyJeqoBe4rAO5fhjwWLsvMAeCEmYa/3i8ITSvurFEou7BELo25vM58dNfGQHig52LrA/GU/jwDAhHyTXP3AvqqgIFa0ysMaHasYny6oqXi+eb2w/KimtgOhe5/oUdNBe/KgqZ+hP3qlTchxBl5MEzZIKgXTXQeYJpYYrnFb0l/R8qSkFBJv2xzxVJxEamN71SG7OIsi9m14D6hd2pNDHDDqHgKBVbN5irxDuJAzHN5upzfziXiYCOusud23tX6/nNv8t03CbB7FW0OxaCGhAjbavTFAf164L9GM7j76BGsLwWSh2HhG9G9lKs2bEI3IQudllMc6p9N6j2FhMOCKK6YYekdAOVc3ozTFc73VLkXtN8pnTC8OCSavthSt5jOUd0qTsQGH91lWlEkVe0bWi+s9nggfeWFM7HMVmqsR1jYlOXoi5s7xYwKLUdeUjRk3/rkzIFoOxquE5sVVuNDRNCaqcpPVY4k0gE= openpgp:0x8880F3E0"
- "ssh-ed25519 \
AAAAC3NzaC1lZDI1NTE5AAAAIJRnXU2My2iMXl1yCIEoASZYAUW0q1qn3P5tSUI0B0+4 \
openpgp:0xAD2BFD7F"
opendoas_settings: "permit persist admin as root"
- name: ansible
password_hash: ""
ssh_public_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKNzJdo6/c7uXrg0lqVwyXOhcNxO/BnylyJeqoBe4rAO5fhjwWLsvMAeCEmYa/3i8ITSvurFEou7BELo25vM58dNfGQHig52LrA/GU/jwDAhHyTXP3AvqqgIFa0ysMaHasYny6oqXi+eb2w/KimtgOhe5/oUdNBe/KgqZ+hP3qlTchxBl5MEzZIKgXTXQeYJpYYrnFb0l/R8qSkFBJv2xzxVJxEamN71SG7OIsi9m14D6hd2pNDHDDqHgKBVbN5irxDuJAzHN5upzfziXiYCOusud23tX6/nNv8t03CbB7FW0OxaCGhAjbavTFAf164L9GM7j76BGsLwWSh2HhG9G9lKs2bEI3IQudllMc6p9N6j2FhMOCKK6YYekdAOVc3ozTFc73VLkXtN8pnTC8OCSavthSt5jOUd0qTsQGH91lWlEkVe0bWi+s9nggfeWFM7HMVmqsR1jYlOXoi5s7xYwKLUdeUjRk3/rkzIFoOxquE5sVVuNDRNCaqcpPVY4k0gE= openpgp:0x8880F3E0"
- "ssh-ed25519 \
AAAAC3NzaC1lZDI1NTE5AAAAIJRnXU2My2iMXl1yCIEoASZYAUW0q1qn3P5tSUI0B0+4 \
openpgp:0xAD2BFD7F"
opendoas_settings: "permit nopass ansible"
forgejo_runner_settings:
version: 6.4.0
instance: http://git.dev.cuqmbr.home
token: !vault |
$ANSIBLE_VAULT;1.1;AES256
37363965303034663465373839646165323137363133653334333066303934316632666632323332
6236343531656331306363376366663436323934353263380a303434303364363938353263313031
34366663356361643865386363336632393932336334333632333933303839376432326665653630
3166633131353861650a346162333934373331386134663763646534396362303261643531363362
62616638383239653733383265663538613637303837633734383933363937383439666133373365
3231376635356132656636616662663266343837613364356232
name: forgejo-runner
fluentbit_settings:
service:
flush: 1
daemon: false
log_level: info
http_server: false
pipeline:
inputs:
- name: systemd
tag: systemd_input
filters:
- name: rewrite_tag
match: systemd_input
rule: $_SYSTEMD_UNIT ^(forgejo-runner.service)$ forgejo-runner false
- name: rewrite_tag
match: systemd_input
rule: $_SYSTEMD_UNIT ^(forgejo-runner.service.+|(?!forgejo-runner.service).*)$ systemd false
- name: record_modifier
match: forgejo-runner
allowlist_key:
- MESSAGE
outputs:
- name: loki
host: 192.168.0.252
labels: "env=dev,hostname=forgejo-runner,service_name=forgejo-runner"
match: forgejo-runner
- name: loki
host: 192.168.0.252
labels: "env=dev,hostname=forgejo-runner,service_name=systemd"
match: systemd

View File

@ -13,3 +13,6 @@ all:
forgejo: forgejo:
hosts: hosts:
192.168.0.20: 192.168.0.20:
forgejo_runner:
hosts:
192.168.0.21:

View File

@ -0,0 +1,10 @@
---
galaxy_info:
role_name: docker
author: cuqmbr-homelab
description: Install Docker Container Engine.
# issue_tracker_url: http://example.com/issue/tracker
license: MIT
min_ansible_version: "2.1"
galaxy_tags: []
dependencies: []

View File

@ -0,0 +1,14 @@
---
- name: Converge
hosts: all
gather_facts: false
pre_tasks:
- name: Update apt cache.
ansible.builtin.apt:
update_cache: true
cache_valid_time: 86400
roles:
- docker

View File

@ -0,0 +1,12 @@
---
driver:
name: docker
platforms:
- name: cuqmbr-homelab.docker_debian-12
image: docker.io/geerlingguy/docker-debian12-ansible:latest
pre_build_image: true
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
privileged: true

View File

@ -0,0 +1,36 @@
---
- name: Create apt keys installation directory.
ansible.builtin.file:
path: "/etc/apt/keyrings"
state: directory
mode: "0755"
- name: Add docker apt key.
ansible.builtin.get_url:
url: "https://download.docker.com/linux/ubuntu/gpg"
dest: "/etc/apt/keyrings/docker.asc"
mode: "0444"
- name: Add docker apt repository.
ansible.builtin.apt_repository:
repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/debian bookworm stable"
filename: docker
state: present
update_cache: true
- name: Install docker apt packages.
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
- name: Start and enable docker service.
ansible.builtin.service:
name: docker
state: started
enabled: true

View File

@ -0,0 +1,139 @@
---
forgejo_runner_default_settings:
clean_binaries: false
force_register: false
version: 6.4.0
instance: http://git.dev.cuqmbr.home
token: eGzS4vae9XrtkInvrhywiD5oXtndgm4ES9Wl3rSv
name: forgejo-runner
config:
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info
# The level of logging for jobs, can be trace,
# debug, info, earn, error, fatal
job_level: info
runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 4
# Extra environment variables to run jobs.
envs:
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .env
# The timeout for a job to be finished.
# Please note that the Forgejo instance also has a
# timeout (3h by default) for the job.
# So the job could be stopped by the Forgejo instance
# if it's timeout is shorter than this.
timeout: 3h
# The timeout for the runner to wait for running jobs to finish when
# shutting down because a TERM or INT signal has been received. Any
# running jobs that haven't finished after this timeout will be
# cancelled.
# If unset or zero the jobs will be cancelled immediately.
shutdown_timeout: 3h
# Whether skip verifying the TLS certificate of the instance.
insecure: false
# The timeout for fetching the job from the Forgejo instance.
fetch_timeout: 5s
# The interval for fetching the job from the Forgejo instance.
fetch_interval: 2s
# The interval for reporting the job status and
# logs to the Forgejo instance.
report_interval: 1s
# The labels of a runner are used to determine which
# jobs the runner can run, and how to run them.
# Like: ["macos-arm64:host", "ubuntu-latest:docker://node:20-bookworm",
# "ubuntu-22.04:docker://node:20-bookworm"]
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when executing the `daemon`,
# it will use labels in the `.runner` file.
labels:
- debian-slim-latest:docker://debian-slim:latest
- debian-slim-12:docker://debian-slim:12
- debian-slim-11:docker://debian-slim:11
- ubuntu-latest:docker://ubuntu:latest
- ubuntu-24.04:docker://ubuntu:24.04
- ubuntu-22.04:docker://ubuntu:22.04
cache:
# Enable cache server to use actions/cache.
enabled: true
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address
# to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: ""
# The port of the cache server.
# 0 means to use a random available port.
port: 0
# The port of the cache proxy.
# 0 means to use a random available port.
proxy_port: 0
# The external cache server URL. Valid only when enable is true.
# If it's specified, it will be used to set the ACTIONS_CACHE_URL
# environment variable. The URL should generally end with "/".
# Otherwise it will be set to the the URL of the internal cache server.
external_server: ""
# The shared cache secret. When communicating with a cache server,
# the runner uses this secret to verify the
# authenticity of the cache requests.
# When using an external cache server it is required to
# set the same secret for the runner and the cache server.
secret: ""
# Overrides the ACTIONS_CACHE_URL passed to workflow containers.
# This should only be used if the runner host is not reachable from the
# workflow containers, and requires further setup.
actions_cache_url_override: ""
container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, create a network automatically.
network: ""
# Whether to create networks with IPv6 enabled.
# Requires the Docker daemon to be set up accordingly.
# Only takes effect if "network" is set to "".
enable_ipv6: false
# Whether to use privileged mode or not when launching task containers
# (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container
# is started (eg, --add-host=my.forgejo.url:host-gateway).
options:
# The parent directory of a job's working directory.
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers.
# Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty,
# no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume
# and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: []
# overrides the docker client host with the specified one.
# If "-" or "", an available docker host will automatically be found.
# If "automount", an available docker host will automatically be
# found and mounted in the job container (e.g. /var/run/docker.sock).
# Otherwise the specified docker host will be used and an
# error will be returned if it doesn't work.
docker_host: "-"
# Pull docker image(s) even if already present
force_pull: false
# Rebuild local docker image(s) even if already present
force_rebuild: false
host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:

View File

@ -0,0 +1,18 @@
# Managed with Ansible
[Unit]
Description=Forgejo Runner
Documentation=https://forgejo.org/docs/latest/admin/actions/
After=docker.service
[Service]
ExecStart=/usr/local/bin/forgejo-runner daemon
ExecReload=/bin/kill -s HUP $MAINPID
User=forgejo-runner
WorkingDirectory=/var/lib/forgejo-runner
Restart=on-failure
TimeoutSec=0
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,6 @@
---
- name: Restart forgejo-runner service.
ansible.builtin.service:
name: forgejo-runner
state: restarted

View File

@ -0,0 +1,10 @@
---
galaxy_info:
role_name: forgejo_runner
author: cuqmbr-homelab
description: Install and configure Forgejo Runner.
# issue_tracker_url: http://example.com/issue/tracker
license: MIT
min_ansible_version: "2.1"
galaxy_tags: []
dependencies: []

View File

@ -0,0 +1,19 @@
---
- name: Converge
hosts: all
gather_facts: false
pre_tasks:
- name: Update apt cache.
ansible.builtin.apt:
update_cache: true
cache_valid_time: 86400
vars:
forgejo_runner_settings:
version: 6.4.0
roles:
- docker
- forgejo_runner

View File

@ -0,0 +1,12 @@
---
driver:
name: docker
platforms:
- name: cuqmbr-homelab.forgejo-runner_debian-12
image: docker.io/geerlingguy/docker-debian12-ansible:latest
pre_build_image: true
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
privileged: true

View File

@ -0,0 +1,122 @@
---
- name: Combine default and user settings, decrypt vault.
ansible.builtin.set_fact:
forgejo_runner_settings: "{{ forgejo_runner_default_settings |
ansible.builtin.combine(forgejo_runner_settings, recursive=true) }}"
no_log: true
- name: Create forgejo-runner user.
ansible.builtin.user:
name: forgejo-runner
groups:
- docker
password: '!'
system: true
state: present
- name: Create forgejo-runner config directory.
ansible.builtin.file:
path: /etc/forgejo-runner
owner: root
group: forgejo-runner
mode: "0770"
state: directory
- name: Create forgejo-runner data directory.
ansible.builtin.file:
path: /var/lib/forgejo-runner
owner: forgejo-runner
group: forgejo-runner
mode: "0750"
state: directory
- name: Clean forgejo-runner binaries.
when: forgejo_runner_settings.clean_binaries
block:
- name: Get all forgejo binaries.
ansible.builtin.find:
paths: /usr/local/bin/
patterns: forgejo-runner*
register: forgejo_runner_binary_find
- name: Delete forgejo-runner binary files.
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ forgejo_runner_binary_find.files }}"
- name: Download forgejo-runner binary.
ansible.builtin.get_url:
url: "https://code.forgejo.org/forgejo/runner/releases/download\
/v{{ forgejo_runner_settings.version }}\
/forgejo-runner-{{ forgejo_runner_settings.version }}-linux-amd64"
dest: "/usr/local/bin/forgejo-runner-{{ forgejo_runner_settings.version }}"
owner: root
group: root
mode: "0555"
- name: Create symlink to forgejo-runner binary.
ansible.builtin.file:
src: "/usr/local/bin/forgejo-runner-{{ forgejo_runner_settings.version }}"
dest: /usr/local/bin/forgejo-runner
owner: root
group: root
mode: "0555"
state: link
notify:
- Restart forgejo-runner service.
- name: Install forgejo service file.
ansible.builtin.copy:
src: forgejo-runner.service
dest: /etc/systemd/system/forgejo-runner.service
owner: root
group: root
mode: "0644"
- name: Install forgejo-runner configuration file.
ansible.builtin.template:
src: config.yml.j2
dest: /etc/forgejo-runner/config.yml
owner: root
group: forgejo-runner
mode: "0640"
notify:
- Restart forgejo-runner service.
- name: Remove forgejo-runner registration file.
ansible.builtin.file:
path: "/var/lib/forgejo-runner\
/{{ forgejo_runner_settings.config.runner.file }}"
state: absent
when: forgejo_runner_settings.force_register
notify:
- Restart forgejo-runner service.
- name: Register forgejo-runner.
ansible.builtin.command:
chdir: /var/lib/forgejo-runner/
cmd: "/usr/local/bin/forgejo-runner --config \
/etc/forgejo-runner/config.yml register --no-interactive \
--name {{ forgejo_runner_settings.name }} \
--instance {{ forgejo_runner_settings.instance }} \
--token {{ forgejo_runner_settings.token }}"
creates: "{{ forgejo_runner_settings.config.runner.file }}"
no_log: true
- name: Change forgejo-runner registration file ownership.
ansible.builtin.file:
path: "/var/lib/forgejo-runner\
/{{ forgejo_runner_settings.config.runner.file }}"
owner: forgejo-runner
group: forgejo-runner
mode: "0640"
- name: Enable and start forgejo-runner service.
ansible.builtin.service:
name: forgejo-runner
state: started
enabled: true

View File

@ -0,0 +1,7 @@
---
# Managed with Ansible
{{
forgejo_runner_settings.config |
ansible.builtin.to_nice_yaml(indent=2, width=80)
}}

View File

@ -37,6 +37,11 @@ resource "proxmox_virtual_environment_firewall_ipset" "dev_loggers" {
name = "192.168.0.20" name = "192.168.0.20"
comment = "forgejo" comment = "forgejo"
} }
cidr {
name = "192.168.0.21"
comment = "forgejo-runner"
}
} }
resource "proxmox_virtual_environment_firewall_ipset" "dev_postgres_clients" { resource "proxmox_virtual_environment_firewall_ipset" "dev_postgres_clients" {

View File

@ -0,0 +1,100 @@
resource "proxmox_virtual_environment_container" "forgejo-runner" {
node_name = "pve"
vm_id = 1051
tags = ["dev"]
unprivileged = true
cpu {
cores = 1
}
memory {
dedicated = 1024
}
disk {
datastore_id = var.datastore_id
size = 16
}
network_interface {
bridge = var.internal_network_bridge_name
name = "eth-dev"
firewall = true
enabled = true
}
initialization {
hostname = "forgejo-runner"
ip_config {
ipv4 {
address = "192.168.0.21/24"
gateway = "192.168.0.1"
}
}
user_account {
keys = [var.ssh_public_key]
}
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
type = "debian"
}
started = true
startup {
order = 500
up_delay = 0
down_delay = 0
}
features {
nesting = true
}
}
resource "proxmox_virtual_environment_firewall_options" "forgejo-runner" {
depends_on = [proxmox_virtual_environment_container.forgejo-runner]
node_name = proxmox_virtual_environment_container.forgejo-runner.node_name
vm_id = proxmox_virtual_environment_container.forgejo-runner.vm_id
enabled = true
dhcp = true
input_policy = "DROP"
output_policy = "ACCEPT"
}
resource "proxmox_virtual_environment_firewall_rules" "forgejo-runner" {
depends_on = [proxmox_virtual_environment_container.forgejo-runner]
node_name = proxmox_virtual_environment_container.forgejo-runner.node_name
vm_id = proxmox_virtual_environment_container.forgejo-runner.vm_id
rule {
type = "in"
source = split("/", data.terraform_remote_state.common.outputs.bastion_ct.initialization[0].ip_config[1].ipv4[0].address)[0]
proto = "tcp"
dport = "22"
action = "ACCEPT"
comment = "SSH from Bastion."
}
rule {
type = "in"
proto = "icmp"
dport = "8"
action = "ACCEPT"
comment = "Ping."
}
rule {
security_group = data.terraform_remote_state.common.outputs.prometheus_node_exporter_sg.name
comment = "Allow Prometheus server to pull Prometheus node exporter from Monitoring Node."
}
}