From 00de271dccbc724f76d14d7d36ce5b3f459cf884 Mon Sep 17 00:00:00 2001 From: Peter Kurfer <peter@icb4dc0.de> Date: Sat, 5 Apr 2025 09:02:47 +0200 Subject: [PATCH] feat: prepare custom images for Forgejo runners --- configs/ci-runner/10-runcwd | 1 - configs/ci-runner/runner-flatcar.yaml | 104 ----------------- dns.tf | 2 +- forgejo-runner_machines.tf | 108 +++--------------- .../configs}/50unattended-upgrades | 0 images/forgejo-runner/configs/cloud-init.yaml | 104 +++++++++++++++++ .../configs}/forgejo-runner.service | 1 + .../configs}/runner-config.yaml | 0 images/forgejo-runner/packer.pkr.hcl | 84 ++++++++++++++ images/forgejo-runner/scripts/cleanup.sh | 56 +++++++++ images/forgejo-runner/scripts/upgrade.sh | 7 ++ 11 files changed, 266 insertions(+), 201 deletions(-) delete mode 100644 configs/ci-runner/10-runcwd delete mode 100644 configs/ci-runner/runner-flatcar.yaml rename {configs/ci-runner => images/forgejo-runner/configs}/50unattended-upgrades (100%) create mode 100644 images/forgejo-runner/configs/cloud-init.yaml rename {configs/ci-runner => images/forgejo-runner/configs}/forgejo-runner.service (96%) rename {configs/ci-runner => images/forgejo-runner/configs}/runner-config.yaml (100%) create mode 100644 images/forgejo-runner/packer.pkr.hcl create mode 100644 images/forgejo-runner/scripts/cleanup.sh create mode 100644 images/forgejo-runner/scripts/upgrade.sh diff --git a/configs/ci-runner/10-runcwd b/configs/ci-runner/10-runcwd deleted file mode 100644 index e5e28d6..0000000 --- a/configs/ci-runner/10-runcwd +++ /dev/null @@ -1 +0,0 @@ -Defaults runcwd=* diff --git a/configs/ci-runner/runner-flatcar.yaml b/configs/ci-runner/runner-flatcar.yaml deleted file mode 100644 index 04b962a..0000000 --- a/configs/ci-runner/runner-flatcar.yaml +++ /dev/null @@ -1,104 +0,0 @@ -variant: flatcar -version: 1.1.0 - -systemd: - units: - - name: forgejo-runner-install.service - enabled: true - contents: | - [Unit] - Description=Run Forgejo runner install script - Wants = network-online.target - After = network.target network-online.target - ConditionPathExists=/opt/forgejo-runner-install.sh - ConditionPathExists=!/opt/bin/forgejo-runner - [Service] - Type=oneshot - TimeoutStartSec=180 - RemainAfterExit=yes - KillMode=process - ExecStart=/usr/bin/sh -c "/opt/forgejo-runner-install.sh" - [Install] - WantedBy=multi-user.target - - - name: forgejo-runner.service - enabled: false - contents: | - [Unit] - Description=Run Forgejo runner - Wants = network-online.target - After = network.target network-online.target - ConditionPathExists=/opt/bin/forgejo-runner - [Service] - Type=simple - TimeoutStartSec=180 - KillMode=process - ExecStart=/opt/bin/forgejo-runner daemon --config /etc/act/config.yaml - [Install] - WantedBy=multi-user.target - -storage: - files: - - path: /etc/hostname - mode: 0644 - contents: - inline: ${host} - - path: /opt/forgejo-runner-install.sh - mode: 0777 - contents: - inline: | - #!/bin/bash - set -ex - wget -O /opt/bin/forgejo-runner https://data.forgejo.org/forgejo/runner/releases/download/v${runner_version}/forgejo-runner-${runner_version}-linux-${arch} - chmod +x /opt/bin/forgejo-runner - sudo -u runner /opt/bin/forgejo-runner register --config /etc/act/config.yaml --no-interactive --token ${runner_secret} --name ${host} --instance ${forgejo_instance_url} --labels docker:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64,ubuntu-latest:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64,ubuntu-22.04:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64,ubuntu-20.04:docker://code.icb4dc0.de/infrastructure/images/act_runtime:20.04-arm64 - - - path: /etc/act/config.yaml - mode: 0644 - contents: - inline: | - # You don't have to copy this file to your instance, - # just run `forgejo-runner generate-config > config.yaml` to generate a config file. - log: - # The level of logging, can be trace, debug, info, warn, error, fatal - level: info - - runner: - file: /home/runner/.runner - capacity: 1 - timeout: 30m - fetch_timeout: 5s - fetch_interval: 2s - labels: - - "docker:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64" - - "ubuntu-latest:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64" - - "ubuntu-22.04:docker://code.icb4dc0.de/infrastructure/images/act_runtime:arm64" - - "ubuntu-20.04:docker://code.icb4dc0.de/infrastructure/images/act_runtime:20.04-arm64" - - cache: - enabled: true - dir: "" - host: "" - port: 0 - external_server: "" - - container: - network: "" - enable_ipv6: false - privileged: false - options: - workdir_parent: - valid_volumes: [] - docker_host: "unix:///var/run/docker.sock" - force_pull: true - - host: - workdir_parent: - -passwd: - users: - - name: runner - ssh_authorized_keys: ${ssh_keys} - home_dir: /home/runner - groups: - - docker diff --git a/dns.tf b/dns.tf index 170ffd9..2a66f94 100644 --- a/dns.tf +++ b/dns.tf @@ -4,7 +4,7 @@ resource "cloudflare_zone" "icb4dc0de" { } name = "icb4dc0.de" type = "full" - + lifecycle { ignore_changes = [account.id] } diff --git a/forgejo-runner_machines.tf b/forgejo-runner_machines.tf index 5cfc71d..ba5195d 100644 --- a/forgejo-runner_machines.tf +++ b/forgejo-runner_machines.tf @@ -19,13 +19,21 @@ resource "hcloud_placement_group" "forgejo_runners" { } } +data "hcloud_image" "forgejo_runner_snapshot_arm64" { + id = "228451454" +} + +data "hcloud_image" "forgejo_runner_snapshot_amd64" { + id = "228451463" +} + resource "hcloud_server" "forgejo_runner" { for_each = var.forgejo_runners name = each.key server_type = each.value.server_type location = each.value.location - image = "ubuntu-24.04" - placement_group_id = hcloud_placement_group.k3s_machines.id + image = startswith(each.value.server_type, "cax") ? data.hcloud_image.forgejo_runner_snapshot_arm64.id : data.hcloud_image.forgejo_runner_snapshot_amd64.id + placement_group_id = hcloud_placement_group.forgejo_runners.id backups = false @@ -88,62 +96,10 @@ data "cloudinit_config" "runner_config" { gzip = true base64_encode = true - part { - content_type = "text/cloud-config" - content = <<-EOF - groups: - - docker - users: - - name: runner - homedir: /var/lib/runner - groups: docker - package_update: true - package_upgrade: true - package_reboot_if_required: true - packages: - - git - - uidmap - - dbus-user-session - - ca-certificates - - curl - - gnupg - - lsb-release - - docker-ce - - docker-ce-cli - - docker-ce-rootless-extras - - containerd.io - - docker-compose-plugin - apt: - sources: - docker.list: - source: "deb [arch=${startswith(each.value.server_type, "cax") ? "arm64" : "amd64"} signed-by=$KEY_FILE] https://download.docker.com/linux/ubuntu $RELEASE stable" - keyid: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 - EOF - } - part { content_type = "text/cloud-config" content = <<-EOF write_files: - - encoding: gzip+base64 - content: ${base64gzip(file("configs/ci-runner/10-runcwd"))} - path: /etc/sudoers.d/10-runcwd - owner: root:root - permissions: "0644" - - - encoding: gzip+base64 - content: ${base64gzip(file("configs/ci-runner/50unattended-upgrades"))} - path: /etc/apt/apt.conf.d/50unattended-upgrades - owner: root:root - permissions: "0644" - - - encoding: gzip+base64 - content: ${base64gzip(file("configs/ci-runner/forgejo-runner.service"))} - path: /etc/systemd/user/forgejo-runner.service - owner: runner:runner - permissions: "0640" - defer: true - - encoding: gzip+base64 content: ${base64gzip(file("configs/ci-runner/docker-buildx-cleanup.service"))} path: /lib/systemd/system/docker-buildx-cleanup.service @@ -156,22 +112,6 @@ data "cloudinit_config" "runner_config" { path: /lib/systemd/system/docker-buildx-cleanup.timer owner: root:root permissions: "0640" - defer: true - - - encoding: gzip+base64 - content: ${base64gzip(templatefile("configs/ci-runner/runner-config.yaml", { - arch = startswith(each.value.server_type, "cax") ? "arm64" : "amd64" -}))} - path: /etc/act/config.yaml - owner: runner:runner - permissions: "0640" - defer: true - - - encoding: gzip+base64 - content: ${base64gzip(file("configs/ci-runner/daemon.json"))} - path: /etc/docker/daemon.json - owner: root:root - permissions: "0640" defer: true - encoding: gzip+base64 @@ -180,17 +120,10 @@ data "cloudinit_config" "runner_config" { owner: runner:runner permissions: "0640" defer: true - - - encoding: gzip+base64 - content: ${base64gzip(file("configs/ci-runner/daemon.json"))} - path: /var/lib/runner/.config/docker/daemon.json - owner: runner:runner - permissions: "0640" - defer: true - encoding: gzip+base64 content: ${base64gzip(templatefile("configs/ci-runner/docker-rootless-config.json", { - registry_auth: base64encode("${data.azurerm_key_vault_secret.harbor_minion_username.value}:${data.azurerm_key_vault_secret.harbor_minion_token.value}") + registry_auth : base64encode("${data.azurerm_key_vault_secret.harbor_minion_username.value}:${data.azurerm_key_vault_secret.harbor_minion_token.value}") }))} path: /var/lib/runner/.docker/config.json owner: runner:runner @@ -205,23 +138,8 @@ part { runcmd: - | set -e - loginctl enable-linger runner - - docker run --privileged --rm tonistiigi/binfmt --install all - - sleep 10 - - sudo -u runner DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus XDG_RUNTIME_DIR=/run/user/1000 /usr/bin/dockerd-rootless-setuptool.sh install --force - - curl -L -o /usr/local/bin/forgejo-runner https://data.forgejo.org/forgejo/runner/releases/download/v${var.forgejo_runner_version}/forgejo-runner-${var.forgejo_runner_version}-linux-${startswith(each.value.server_type, "cax") ? "arm64" : "amd64"} - curl -L -o /tmp/forgejo-runner.asc https://data.forgejo.org/forgejo/runner/releases/download/v${var.forgejo_runner_version}/forgejo-runner-${var.forgejo_runner_version}-linux-${startswith(each.value.server_type, "cax") ? "arm64" : "amd64"}.asc - gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710 - gpg --verify /tmp/forgejo-runner.asc /usr/local/bin/forgejo-runner - chmod +x /usr/local/bin/forgejo-runner - - sudo -u runner DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus XDG_RUNTIME_DIR=/run/user/1000 systemctl --user enable --now forgejo-runner.service - systemctl enable --now docker-buildx-cleanup.timer - systemctl restart unattended-upgrades.service + systemctl daemon-reload + systemctl enable --now forgejo-runner.service EOF } } diff --git a/configs/ci-runner/50unattended-upgrades b/images/forgejo-runner/configs/50unattended-upgrades similarity index 100% rename from configs/ci-runner/50unattended-upgrades rename to images/forgejo-runner/configs/50unattended-upgrades diff --git a/images/forgejo-runner/configs/cloud-init.yaml b/images/forgejo-runner/configs/cloud-init.yaml new file mode 100644 index 0000000..4a5206d --- /dev/null +++ b/images/forgejo-runner/configs/cloud-init.yaml @@ -0,0 +1,104 @@ +#cloud-config + +growpart: + mode: "off" +resize_rootfs: false + +groups: + - docker +users: + - name: runner + homedir: /var/lib/runner + groups: docker +package_update: true +package_upgrade: true +package_reboot_if_required: false +packages: + - git + - uidmap + - dbus-user-session + - ca-certificates + - curl + - gnupg + - lsb-release + - docker-ce + - docker-ce-cli + - docker-ce-rootless-extras + - containerd.io + - docker-compose-plugin +apt: + sources: + docker.list: + source: "deb [arch=${arch} signed-by=$KEY_FILE] https://download.docker.com/linux/ubuntu $RELEASE stable" + keyid: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 + +write_files: + - content: | + Defaults runcwd=* + path: /etc/sudoers.d/10-runcwd + owner: root:root + permissions: "0644" + + - encoding: gzip+base64 + content: ${unattended_upgrades_config} + path: /etc/apt/apt.conf.d/50unattended-upgrades + owner: root:root + permissions: "0644" + + - encoding: gzip+base64 + content: ${forgejo_runner_service} + path: /lib/systemd/system/forgejo-runner.service + owner: runner:runner + permissions: "0640" + defer: true + + - encoding: gzip+base64 + content: ${forgejo_runner_config} + path: /etc/act/config.yaml + owner: runner:runner + permissions: "0640" + defer: true + + - content: | + { + "features": { + "containerd-snapshotter": true + } + } + + path: /etc/docker/daemon.json + owner: root:root + permissions: "0640" + defer: true + + - content: | + { + "features": { + "containerd-snapshotter": true + } + } + path: /var/lib/runner/.config/docker/daemon.json + owner: runner:runner + permissions: "0640" + defer: true + +runcmd: + - | + set -e + loginctl enable-linger runner + + docker run --privileged --rm tonistiigi/binfmt --install all + + sleep 10 + + sudo -u runner DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus XDG_RUNTIME_DIR=/run/user/1000 /usr/bin/dockerd-rootless-setuptool.sh install --force + + curl -L -o /usr/local/bin/forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v${forgejo_runner_version}/forgejo-runner-${forgejo_runner_version}-linux-${arch} + + curl -L -o /tmp/forgejo-runner.asc https://code.forgejo.org/forgejo/runner/releases/download/v${forgejo_runner_version}/forgejo-runner-${forgejo_runner_version}-linux-${arch}.asc + + gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710 + gpg --verify /tmp/forgejo-runner.asc /usr/local/bin/forgejo-runner + chmod +x /usr/local/bin/forgejo-runner + + systemctl restart unattended-upgrades.service diff --git a/configs/ci-runner/forgejo-runner.service b/images/forgejo-runner/configs/forgejo-runner.service similarity index 96% rename from configs/ci-runner/forgejo-runner.service rename to images/forgejo-runner/configs/forgejo-runner.service index dd52802..f7c5cc0 100644 --- a/configs/ci-runner/forgejo-runner.service +++ b/images/forgejo-runner/configs/forgejo-runner.service @@ -7,6 +7,7 @@ ConditionPathExists=/run/user/1000/docker.sock [Service] TimeoutStartSec=180 KillMode=process +User=runner ExecStart=forgejo-runner daemon --config /etc/act/config.yaml WorkingDirectory=/var/lib/runner diff --git a/configs/ci-runner/runner-config.yaml b/images/forgejo-runner/configs/runner-config.yaml similarity index 100% rename from configs/ci-runner/runner-config.yaml rename to images/forgejo-runner/configs/runner-config.yaml diff --git a/images/forgejo-runner/packer.pkr.hcl b/images/forgejo-runner/packer.pkr.hcl new file mode 100644 index 0000000..3b09f7e --- /dev/null +++ b/images/forgejo-runner/packer.pkr.hcl @@ -0,0 +1,84 @@ +packer { + required_plugins { + hcloud = { + source = "github.com/hetznercloud/hcloud" + version = ">= 1.6.0" + } + } +} + +variable "hcloud_location" { + type = string + default = "hel1" +} + +variable "forgejo_runner_version" { + type = string + default = "6.3.1" +} + +source "hcloud" "base-arm64" { + image = "ubuntu-24.04" + location = var.hcloud_location + server_type = "cax11" + ssh_username = "root" + snapshot_name = "forgejo-runner-${var.forgejo_runner_version}" + snapshot_labels = { + name = "forgejo_runner" + base = "ubuntu-24.04", + arch = "arm64" + runner_version = var.forgejo_runner_version + } + + user_data = templatefile("configs/cloud-init.yaml", { + arch = "arm64" + unattended_upgrades_config = base64gzip(file("configs/50unattended-upgrades")) + forgejo_runner_service = base64gzip(file("configs/forgejo-runner.service")) + forgejo_runner_version = var.forgejo_runner_version + forgejo_runner_config = base64gzip(templatefile("configs/runner-config.yaml", { + arch = "arm64" + })) + }) +} + +source "hcloud" "base-amd64" { + image = "ubuntu-24.04" + location = var.hcloud_location + server_type = "cx22" + ssh_keys = ["Yubikey", "Default Management"] + ssh_username = "root" + snapshot_name = "forgejo-runner-${var.forgejo_runner_version}" + snapshot_labels = { + name = "forgejo_runner" + base = "ubuntu-24.04", + version = "v1.0.0", + arch = "amd64" + runner_version = var.forgejo_runner_version + } + + user_data = templatefile("configs/cloud-init.yaml", { + arch = "amd64" + unattended_upgrades_config = base64gzip(file("configs/50unattended-upgrades")) + forgejo_runner_service = base64gzip(file("configs/forgejo-runner.service")) + forgejo_runner_version = var.forgejo_runner_version + forgejo_runner_config = base64gzip(templatefile("configs/runner-config.yaml", { + arch = "amd64" + })) + }) +} + +build { + sources = ["source.hcloud.base-arm64", "source.hcloud.base-amd64"] + + provisioner "shell" { + inline = ["cloud-init status --wait --long"] + valid_exit_codes = [0, 2] + } + + provisioner "shell" { + scripts = [ + "scripts/upgrade.sh", + "scripts/cleanup.sh", + ] + } +} diff --git a/images/forgejo-runner/scripts/cleanup.sh b/images/forgejo-runner/scripts/cleanup.sh new file mode 100644 index 0000000..3d1f1f0 --- /dev/null +++ b/images/forgejo-runner/scripts/cleanup.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -eux + +clean_cloud_init() { + cloud-init clean --logs --machine-id --seed --configs all + + rm -rf /run/cloud-init/* + rm -rf /var/lib/cloud/* +} + +clean_apt() { + export DEBIAN_FRONTEND=noninteractive + + apt-get -y autopurge + apt-get -y clean + + rm -rf /var/lib/apt/lists/* +} + +clean_ssh_keys() { + rm -f /etc/ssh/ssh_host_*_key /etc/ssh/ssh_host_*_key.pub +} + +clean_logs() { + journalctl --flush + journalctl --rotate --vacuum-time=0 + + find /var/log -type f -exec truncate --size 0 {} \; # truncate system logs + find /var/log -type f -name '*.[1-9]' -delete # remove archived logs + find /var/log -type f -name '*.gz' -delete # remove compressed archived logs +} + +clean_root() { + unset HISTFILE + + rm -rf /root/.cache + rm -rf /root/.ssh + rm -f /root/.bash_history + rm -f /root/.lesshst + rm -f /root/.viminfo +} + +flush_disk() { + dd if=/dev/zero of=/zero bs=4M || true + sync + rm -f /zero +} + +clean_cloud_init +clean_apt +clean_ssh_keys +clean_logs +clean_root + +flush_disk diff --git a/images/forgejo-runner/scripts/upgrade.sh b/images/forgejo-runner/scripts/upgrade.sh new file mode 100644 index 0000000..f68a992 --- /dev/null +++ b/images/forgejo-runner/scripts/upgrade.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -eux + +export DEBIAN_FRONTEND=noninteractive + +apt-get autoremove -y --purge