From c61900f9e6d4f574418df64992d5a453cf238d22 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:17:59 +0000 Subject: [PATCH 1/9] feat: add gitea-runner namespace manifest --- manifests/gitea-runner/namespace.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 manifests/gitea-runner/namespace.yaml diff --git a/manifests/gitea-runner/namespace.yaml b/manifests/gitea-runner/namespace.yaml new file mode 100644 index 0000000..79e8af0 --- /dev/null +++ b/manifests/gitea-runner/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: gitea-runner From ca25dde7802aecc25e166a44c0a9bd58429050a9 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:01 +0000 Subject: [PATCH 2/9] feat: add gitea-runner FluxCD HelmRelease --- manifests/gitea-runner/chart.yaml | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 manifests/gitea-runner/chart.yaml diff --git a/manifests/gitea-runner/chart.yaml b/manifests/gitea-runner/chart.yaml new file mode 100644 index 0000000..7e6ee5d --- /dev/null +++ b/manifests/gitea-runner/chart.yaml @@ -0,0 +1,58 @@ +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: gitea +spec: + interval: "24h" + url: https://dl.gitea.com/charts/ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: gitea-runner + namespace: gitea-runner +spec: + interval: 10m + chart: + spec: + chart: act_runner + version: "0.2.5" + sourceRef: + kind: HelmRepository + name: gitea + interval: "1h" + values: + rbac: + create: true + serviceAccount: + create: true + # FIXME: The gitea-runner Secret (key: token) must be created by Greg via agenix + # before this HelmRelease will deploy successfully. + gitea: + instanceURL: https://src.thehellings.com + runnerToken: + existingSecret: gitea-runner + existingSecretKey: token + imagePullSecrets: + - name: image-pull-secrets + config: + runner: + labels: + # Ubuntu + - "ubuntu-22.04:docker://ubuntu:22.04" + - "ubuntu-24.04:docker://ubuntu:24.04" + - "ubuntu-24.10:docker://ubuntu:24.10" + # Fedora + - "fedora-41:docker://fedora:41" + - "fedora-42:docker://fedora:42" + # CentOS Stream + - "centos-stream-9:docker://quay.io/centos/centos:stream9" + - "centos-stream-10:docker://quay.io/centos/centos:stream10" + # Nix + - "nix:docker://nixos/nix:latest" + # ci-images (internal registry: src.thehellings.com/greg) + - "ci-builder:docker://src.thehellings.com/greg/builder:latest" + - "ci-vm-test:docker://src.thehellings.com/greg/vm-test:latest" + - "ci-sword:docker://src.thehellings.com/greg/sword-container-builder:latest" + - "ci-bitwarden:docker://src.thehellings.com/greg/bitwarden:latest" + - "ci-immich:docker://src.thehellings.com/greg/immich:latest" From 87bc9a21d9e093c892f1752c8f7d7be319aa3ba8 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:04 +0000 Subject: [PATCH 3/9] feat: add gitea-runner kustomization --- manifests/gitea-runner/kustomization.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 manifests/gitea-runner/kustomization.yaml diff --git a/manifests/gitea-runner/kustomization.yaml b/manifests/gitea-runner/kustomization.yaml new file mode 100644 index 0000000..cdbf9fe --- /dev/null +++ b/manifests/gitea-runner/kustomization.yaml @@ -0,0 +1,6 @@ +namespace: gitea-runner + +resources: + - namespace.yaml + - secrets.yaml + - chart.yaml From d65dcb51a3eb78cfee58d6147a0e6029ec00ac36 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:07 +0000 Subject: [PATCH 4/9] feat: add gitea-runner secret placeholder --- manifests/gitea-runner/secrets.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 manifests/gitea-runner/secrets.yaml diff --git a/manifests/gitea-runner/secrets.yaml b/manifests/gitea-runner/secrets.yaml new file mode 100644 index 0000000..60c00ed --- /dev/null +++ b/manifests/gitea-runner/secrets.yaml @@ -0,0 +1,16 @@ +# FIXME: This Secret is a placeholder only! +# Greg must generate a runner registration token from the Gitea web UI +# (Site Administration → Actions → Runners → Create Runner Token), +# then store it in agenix and wire it up to populate this Secret. +# The Secret should have key: token +# +# Until this Secret exists in the cluster, the gitea-runner HelmRelease +# will fail to deploy. +apiVersion: v1 +kind: Secret +metadata: + name: gitea-runner + namespace: gitea-runner +stringData: + # FIXME: Replace with actual runner token (managed via agenix / external-secrets) + token: "REPLACE_ME_WITH_ACTUAL_TOKEN" From b2728bf1de627677acdaed39b430165863a54558 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:10 +0000 Subject: [PATCH 5/9] feat: add gitea-runner NixOS module --- modules/nixos/gitea-runner.nix | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 modules/nixos/gitea-runner.nix diff --git a/modules/nixos/gitea-runner.nix b/modules/nixos/gitea-runner.nix new file mode 100644 index 0000000..ada7a8c --- /dev/null +++ b/modules/nixos/gitea-runner.nix @@ -0,0 +1,65 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.greg.gitea-runner; + hostname = config.networking.hostName; + + # Determine extra labels based on host role + roleLabels = + if builtins.elem hostname [ "isaiah" "jeremiah" "zeke" ] then + [ "bare-metal" ] + else if hostname == "linode" then + [ "linode" ] + else + [ ]; +in +{ + options.greg.gitea-runner = { + enable = lib.mkEnableOption "Enable Gitea Actions runner (exec/shell mode)"; + + hostnameLabel = lib.mkOption { + type = lib.types.str; + default = config.networking.hostName; + description = "Label identifying this host in the runner pool (defaults to hostname)"; + }; + + tokenFile = lib.mkOption { + type = lib.types.path; + description = '' + Path to the file containing the runner registration token. + Wire in your agenix secret path here, e.g.: + config.age.secrets.gitea-runner-token.path + ''; + }; + + threads = lib.mkOption { + type = lib.types.int; + default = 4; + description = "Maximum number of concurrent jobs"; + }; + }; + + config = lib.mkIf cfg.enable { + services.gitea-actions-runner = { + package = pkgs.gitea-actions-runner; + instances.${hostname} = { + enable = true; + url = "https://src.thehellings.com"; + tokenFile = cfg.tokenFile; + labels = + [ + "self-hosted" + cfg.hostnameLabel + ] + ++ roleLabels; + settings = { + runner.capacity = cfg.threads; + }; + }; + }; + }; +} From e8beb7f2a932ffa6d5330829c26f4b9c3c152b75 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:12 +0000 Subject: [PATCH 6/9] feat: add update-flake-lock workflow --- .gitea/workflows/update-flake-lock.yaml | 51 +++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .gitea/workflows/update-flake-lock.yaml diff --git a/.gitea/workflows/update-flake-lock.yaml b/.gitea/workflows/update-flake-lock.yaml new file mode 100644 index 0000000..cb2535e --- /dev/null +++ b/.gitea/workflows/update-flake-lock.yaml @@ -0,0 +1,51 @@ +name: Update flake.lock + +on: + schedule: + - cron: "0 0 * * 0" # Every Sunday at midnight UTC + workflow_dispatch: + +jobs: + update-flake-lock: + runs-on: [self-hosted, nix] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Update flake.lock + run: nix flake update + + - name: Create PR if changed + env: + GITEA_TOKEN: ${{ secrets.KLAATU_TOKEN }} + GITEA_URL: https://src.thehellings.com + REPO: greg/nixos + run: | + if git diff --quiet flake.lock; then + echo "flake.lock unchanged, nothing to do" + exit 0 + fi + + BRANCH="auto/update-flake-lock-$(date +%Y%m%d)" + git config user.email "klaatu@thehellings.com" + git config user.name "klaatu" + git checkout -b "$BRANCH" + git add flake.lock + git commit -m "chore: update flake.lock $(date +%Y-%m-%d)" + + # Push branch using token auth + git remote set-url origin "https://klaatu:${GITEA_TOKEN}@${GITEA_URL#https://}/${REPO}.git" + git push origin "$BRANCH" + + # Create PR via Gitea API + curl -s -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + "${GITEA_URL}/api/v1/repos/${REPO}/pulls" \ + -d "{ + \"title\": \"chore: update flake.lock $(date +%Y-%m-%d)\", + \"head\": \"$BRANCH\", + \"base\": \"main\", + \"body\": \"Automated weekly flake.lock update.\\n\\nGenerated by Gitea Actions.\", + \"assignees\": [\"greg\"] + }" From 2741be72c7e9c7975c46ad4504818cb4849e5332 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 06:18:14 +0000 Subject: [PATCH 7/9] feat: add update-manifests workflow --- .gitea/workflows/update-manifests.yaml | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .gitea/workflows/update-manifests.yaml diff --git a/.gitea/workflows/update-manifests.yaml b/.gitea/workflows/update-manifests.yaml new file mode 100644 index 0000000..1723dc9 --- /dev/null +++ b/.gitea/workflows/update-manifests.yaml @@ -0,0 +1,58 @@ +name: Update manifest chart versions + +on: + schedule: + - cron: "0 0 * * 1" # Every Monday at midnight UTC + workflow_dispatch: + +jobs: + update-manifests: + runs-on: [self-hosted, nix] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Scan manifests for chart version updates + run: | + echo "TODO: implement manifest update scanning" + echo "" + echo "Planned implementation:" + echo " 1. Parse each manifests/*/chart.yaml for HelmRelease chart versions" + echo " 2. Query artifact hub or helm repo for latest versions" + echo " 3. Emit a diff of available updates" + echo "" + echo "Scanned manifests directories:" + ls manifests/ + + - name: Create PR if changes found + env: + GITEA_TOKEN: ${{ secrets.KLAATU_TOKEN }} + GITEA_URL: https://src.thehellings.com + REPO: greg/nixos + run: | + if git diff --quiet; then + echo "No manifest changes, nothing to do" + exit 0 + fi + + BRANCH="auto/update-manifests-$(date +%Y%m%d)" + git config user.email "klaatu@thehellings.com" + git config user.name "klaatu" + git checkout -b "$BRANCH" + git add manifests/ + git commit -m "chore: update manifest chart versions $(date +%Y-%m-%d)" + + git remote set-url origin "https://klaatu:${GITEA_TOKEN}@${GITEA_URL#https://}/${REPO}.git" + git push origin "$BRANCH" + + curl -s -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + "${GITEA_URL}/api/v1/repos/${REPO}/pulls" \ + -d "{ + \"title\": \"chore: update manifest chart versions $(date +%Y-%m-%d)\", + \"head\": \"$BRANCH\", + \"base\": \"main\", + \"body\": \"Automated weekly manifest chart version update.\\n\\nGenerated by Gitea Actions.\", + \"assignees\": [\"greg\"] + }" From b7fba0e151cdc814f7f96b5d9582864402064576 Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 19:05:06 +0000 Subject: [PATCH 8/9] fix: chart name act_runner -> actions, version 0.2.5 -> 0.0.4 --- manifests/gitea-runner/chart.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/manifests/gitea-runner/chart.yaml b/manifests/gitea-runner/chart.yaml index 7e6ee5d..c0a35f8 100644 --- a/manifests/gitea-runner/chart.yaml +++ b/manifests/gitea-runner/chart.yaml @@ -15,8 +15,8 @@ spec: interval: 10m chart: spec: - chart: act_runner - version: "0.2.5" + chart: actions + version: "0.0.4" sourceRef: kind: HelmRepository name: gitea @@ -26,8 +26,6 @@ spec: create: true serviceAccount: create: true - # FIXME: The gitea-runner Secret (key: token) must be created by Greg via agenix - # before this HelmRelease will deploy successfully. gitea: instanceURL: https://src.thehellings.com runnerToken: From 757b07c22f79ceadde748270814962bc78ef658f Mon Sep 17 00:00:00 2001 From: klaatu Date: Sat, 4 Apr 2026 19:05:17 +0000 Subject: [PATCH 9/9] fix: replace placeholder Secret with ExternalSecret via bitwarden-login --- manifests/gitea-runner/secrets.yaml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/manifests/gitea-runner/secrets.yaml b/manifests/gitea-runner/secrets.yaml index 60c00ed..4fb1503 100644 --- a/manifests/gitea-runner/secrets.yaml +++ b/manifests/gitea-runner/secrets.yaml @@ -1,16 +1,18 @@ -# FIXME: This Secret is a placeholder only! -# Greg must generate a runner registration token from the Gitea web UI -# (Site Administration → Actions → Runners → Create Runner Token), -# then store it in agenix and wire it up to populate this Secret. -# The Secret should have key: token -# -# Until this Secret exists in the cluster, the gitea-runner HelmRelease -# will fail to deploy. -apiVersion: v1 -kind: Secret +apiVersion: external-secrets.io/v1 +kind: ExternalSecret metadata: name: gitea-runner namespace: gitea-runner -stringData: - # FIXME: Replace with actual runner token (managed via agenix / external-secrets) - token: "REPLACE_ME_WITH_ACTUAL_TOKEN" +spec: + refreshInterval: 1h + secretStoreRef: + name: bitwarden-login + kind: ClusterSecretStore + target: + name: gitea-runner + creationPolicy: Owner + data: + - secretKey: token + remoteRef: + key: 11419680-5338-4f19-bdd9-b422007046af + property: password