From 008533491ff073bef490417199d546cd1b7852fb Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 25 Jan 2026 17:21:29 -0800 Subject: [PATCH] Add containerized forgejo-runner for Phase 1 ratcheting Part of the runner ratcheting plan to migrate from host-mode to k8s runners. - Debian-based image with forgejo-runner and Docker CLI - Mounts Docker socket for container builds - Auto-registers on first start - Host networking for access to *.ops.eblu.me services Co-Authored-By: Claude Opus 4.5 --- containers/forgejo-runner/Dockerfile | 63 +++++++++++++++++++++++++ containers/forgejo-runner/config.yaml | 25 ++++++++++ containers/forgejo-runner/entrypoint.sh | 36 ++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 containers/forgejo-runner/Dockerfile create mode 100644 containers/forgejo-runner/config.yaml create mode 100644 containers/forgejo-runner/entrypoint.sh diff --git a/containers/forgejo-runner/Dockerfile b/containers/forgejo-runner/Dockerfile new file mode 100644 index 0000000..03b3349 --- /dev/null +++ b/containers/forgejo-runner/Dockerfile @@ -0,0 +1,63 @@ +# Forgejo Actions Runner - Containerized +# +# A containerized runner capable of building containers via Docker socket mount. +# Part of the runner ratcheting plan (Phase 1+). +# +# Build: +# docker build -t registry.ops.eblu.me/blumeops/forgejo-runner:v1.0.0 . +# +# Run (Phase 1 - Docker on indri): +# docker run -d \ +# --name forgejo-runner \ +# -v /var/run/docker.sock:/var/run/docker.sock \ +# -e FORGEJO_URL=https://forge.ops.eblu.me \ +# -e RUNNER_TOKEN= \ +# -e RUNNER_NAME=indri-docker-runner \ +# registry.ops.eblu.me/blumeops/forgejo-runner:v1.0.0 +# +# The runner registers itself on first start and persists state in /data. + +FROM debian:bookworm-slim + +# Forgejo runner version - check https://code.forgejo.org/forgejo/runner/releases +ARG RUNNER_VERSION=6.3.1 +ARG TARGETARCH + +# Install base dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + jq \ + gnupg \ + lsb-release \ + && rm -rf /var/lib/apt/lists/* + +# Install Docker CLI (not daemon - we mount the socket) +RUN install -m 0755 -d /etc/apt/keyrings \ + && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \ + && chmod a+r /etc/apt/keyrings/docker.asc \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends docker-ce-cli \ + && rm -rf /var/lib/apt/lists/* + +# Install forgejo-runner +RUN ARCH=$(case "${TARGETARCH}" in "amd64") echo "amd64";; "arm64") echo "arm64";; *) echo "amd64";; esac) \ + && curl -fsSL "https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-${ARCH}.xz" -o /tmp/runner.xz \ + && xz -d /tmp/runner.xz \ + && mv /tmp/runner /usr/local/bin/forgejo-runner \ + && chmod +x /usr/local/bin/forgejo-runner + +# Create data directory for runner state +RUN mkdir -p /data +WORKDIR /data + +# Copy entrypoint script +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Copy runner config template +COPY config.yaml /etc/forgejo-runner/config.yaml + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/containers/forgejo-runner/config.yaml b/containers/forgejo-runner/config.yaml new file mode 100644 index 0000000..60ad82e --- /dev/null +++ b/containers/forgejo-runner/config.yaml @@ -0,0 +1,25 @@ +# Forgejo Runner configuration +# See: https://forgejo.org/docs/latest/admin/actions/#configuration + +log: + level: info + +runner: + file: /data/.runner + capacity: 2 + timeout: 3h + # Fetch task interval + fetch_timeout: 5s + fetch_interval: 2s + +container: + # Use host network so containers can reach services on the host + # (e.g., registry.ops.eblu.me resolves to host's Tailscale IP) + network: host + # Don't use privileged mode by default + privileged: false + # Mount docker socket for container builds + options: -v /var/run/docker.sock:/var/run/docker.sock + # Valid volumes that can be mounted + valid_volumes: + - /var/run/docker.sock diff --git a/containers/forgejo-runner/entrypoint.sh b/containers/forgejo-runner/entrypoint.sh new file mode 100644 index 0000000..9977ce9 --- /dev/null +++ b/containers/forgejo-runner/entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Forgejo Runner entrypoint script +# +# Registers the runner on first start, then runs the daemon. +# State is persisted in /data so restarts don't re-register. + +set -e + +# Required environment variables +: "${FORGEJO_URL:?FORGEJO_URL is required (e.g., https://forge.ops.eblu.me)}" +: "${RUNNER_TOKEN:?RUNNER_TOKEN is required (from Forgejo admin > Actions > Runners)}" + +# Optional environment variables with defaults +RUNNER_NAME="${RUNNER_NAME:-forgejo-runner}" +RUNNER_LABELS="${RUNNER_LABELS:-docker:docker://debian:bookworm-slim}" + +# Registration file indicates runner is already registered +RUNNER_FILE="/data/.runner" + +# Register if not already registered +if [ ! -f "$RUNNER_FILE" ]; then + echo "Registering runner '${RUNNER_NAME}' with ${FORGEJO_URL}..." + forgejo-runner register \ + --instance "${FORGEJO_URL}" \ + --token "${RUNNER_TOKEN}" \ + --name "${RUNNER_NAME}" \ + --labels "${RUNNER_LABELS}" \ + --no-interactive + echo "Registration complete." +else + echo "Runner already registered, skipping registration." +fi + +# Start the runner daemon +echo "Starting forgejo-runner daemon..." +exec forgejo-runner daemon --config /etc/forgejo-runner/config.yaml