diff --git a/Makefile b/Makefile index f847034..a3e0f9d 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,9 @@ runner-docs: ## Print Gitea Actions runner substrate docs and evidence runner-status: ## Read-only Actions runner, host, and inter-hub registry probes bash tools/gitea-runner-status.sh +forgejo-runner-status: ## Read-only Forgejo Actions runner and endpoint probes + bash tools/forgejo-runner-status.sh + check-runner-tools: ## Check local tools used by runner inspection targets @missing=0; \ for tool in curl ssh docker; do \ @@ -109,4 +112,4 @@ help: ## Show this help /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \ /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST) -.PHONY: check-tools check-sops registry-docs evidence-docs runner-docs runner-status check-runner-tools gitea-deploy gitea-ingress-deploy gitea-status help +.PHONY: check-tools check-sops registry-docs evidence-docs runner-docs runner-status forgejo-runner-status check-runner-tools gitea-deploy gitea-ingress-deploy gitea-status help diff --git a/docs/forgejo-actions-runner-substrate.md b/docs/forgejo-actions-runner-substrate.md new file mode 100644 index 0000000..0e381b8 --- /dev/null +++ b/docs/forgejo-actions-runner-substrate.md @@ -0,0 +1,76 @@ +# Forgejo Actions Runner Substrate + +Last reviewed: 2026-07-03 + +Status: first supported runner on coulombcore (interim). Forgejo instance runs on +railiance01; runner host is intentionally separate per Forgejo security guidance. + +## Purpose + +Provide a forge-owned Actions runner for `https://forgejo.coulomb.social` so +repos in the `coulomb` organization can build and publish without workstation +involvement. Mirrors the Gitea runner contract in +`docs/gitea-actions-runner-substrate.md`. + +## First Supported Runner + +| Field | Value | +| --- | --- | +| Runner name | `railiance-coulombcore-build-01` | +| Runner scope | `coulomb` organization | +| Host | coulombcore (`92.205.130.254`) | +| Instance | `https://forgejo.coulomb.social/` | +| Binary | `forgejo-runner` v6.3.1 | +| Runtime | Host mode (Docker not installed on host yet) | +| Cluster deploy authority | Not included | + +### Labels + +```text +self-hosted:host,linux:host,linux_amd64:host,container-build:host,registry-publish:host,railiance01:host +``` + +`self-hosted` preserves compatibility with existing Gitea workflow `runs-on` +values during migration. Container image builds require Docker on the runner +host — install before cutover of image-publishing workflows. + +## Service Layout + +| Path | Purpose | +| --- | --- | +| `/usr/local/bin/forgejo-runner` | Runner binary | +| `/var/lib/forgejo-runner/config.yaml` | Generated config | +| `/var/lib/forgejo-runner/.runner` | Registration state (secret) | +| `/etc/systemd/system/forgejo-runner.service` | systemd unit | + +## Probe Evidence (2026-07-03) + +- Org `coulomb` created on Forgejo. +- Runner registered and `systemctl is-active forgejo-runner` → `active`. +- Repo `coulomb/forgejo-actions-probe` workflow `probe.yaml` (`runs-on: self-hosted`) + completed with `status: success` (API: `/api/v1/repos/coulomb/forgejo-actions-probe/actions/tasks`). + +## Operator Commands + +```bash +# Runner health (from railiance-forge) +RUNNER_HOST=coulombcore make forgejo-runner-status + +# Forgejo app smoke (from railiance-apps) +make -C ~/railiance-apps forgejo-smoke + +# Generate a new org registration token (in cluster, no token in logs) +KUBECONFIG=~/.kube/config-hosteurope kubectl exec -n forgejo deploy/forgejo-gitea -- \ + forgejo actions generate-runner-token --scope coulomb +``` + +## Secret Boundaries + +Same as Gitea runner substrate: registration tokens and `.runner` files stay +off Git. Use approved secret paths on the runner host only. + +## Follow-On + +1. Install Docker on the approved runner host for `container-build` jobs. +2. Move runner to a non-legacy host before coulombcore decommission (T03 drain). +3. Add repo-scoped registry credentials in Forgejo org secrets for image push. \ No newline at end of file diff --git a/tools/forgejo-runner-status.sh b/tools/forgejo-runner-status.sh new file mode 100755 index 0000000..97e2094 --- /dev/null +++ b/tools/forgejo-runner-status.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -u + +FORGEJO_URL="${FORGEJO_URL:-https://forgejo.coulomb.social}" +RUNNER_HOST="${RUNNER_HOST:-coulombcore}" +RUNNER_SSH_USER="${RUNNER_SSH_USER:-}" +RUNNER_SSH_KEY="${RUNNER_SSH_KEY:-}" +SSH_CONNECT_TIMEOUT="${SSH_CONNECT_TIMEOUT:-5}" + +section() { printf '\n## %s\n' "$1"; } +have() { command -v "$1" >/dev/null 2>&1; } +http_code() { curl -sS -m 8 -o /dev/null -w '%{http_code}' "$1" 2>/dev/null || printf 'error'; } + +section "Tool availability" +for tool in curl ssh; do + if have "$tool"; then printf 'ok: %s\n' "$tool"; else printf 'missing: %s\n' "$tool"; fi +done + +section "Forgejo endpoint checks" +if have curl; then + printf 'forgejo root: %s\n' "$(http_code "${FORGEJO_URL}/")" + printf 'forgejo api version: %s\n' "$(http_code "${FORGEJO_URL}/api/v1/version")" + printf 'forgejo registry /v2 (GET): %s\n' "$(curl -sS -m 8 -o /dev/null -w '%{http_code}' -X GET "${FORGEJO_URL}/v2/")" +else + echo "curl missing; skipping endpoint checks" +fi + +section "Runner host probe" +if have ssh; then + ssh_target="${RUNNER_HOST}" + if [ -n "${RUNNER_SSH_USER}" ]; then ssh_target="${RUNNER_SSH_USER}@${RUNNER_HOST}"; fi + ssh_args=(-o BatchMode=yes -o ConnectTimeout="${SSH_CONNECT_TIMEOUT}") + if [ -n "${RUNNER_SSH_KEY}" ]; then ssh_args+=(-i "${RUNNER_SSH_KEY}"); fi + ssh "${ssh_args[@]}" "${ssh_target}" ' + set -u + echo "host=$(hostname)" + if command -v forgejo-runner >/dev/null 2>&1; then forgejo-runner -v || true; else echo "missing: forgejo-runner"; fi + if command -v docker >/dev/null 2>&1; then docker --version || true; else echo "missing: docker"; fi + if command -v systemctl >/dev/null 2>&1; then + systemctl is-active forgejo-runner 2>/dev/null || true + fi + if [ -f /var/lib/forgejo-runner/.runner ]; then echo "ok: /var/lib/forgejo-runner/.runner present"; fi + ' +else + echo "ssh missing; skipping runner host probe" +fi \ No newline at end of file