Files
scoutfs-build/ci/deploy-runner.sh
William Gill 90c8537e00
Some checks failed
ScoutFS CI / build (8, localhost/scoutfs-builder:el8, scoutfs-el8) (push) Has been cancelled
ScoutFS CI / build (9, localhost/scoutfs-builder:el9, scoutfs-el9) (push) Has been cancelled
Add deploy-runner.sh for fresh-VM act runner setup
One-shot script that installs podman + git, creates the cache volume,
builds the scoutfs-builder images, downloads act_runner, registers it
with the scoutfs-el8/el9 labels, and installs a systemd unit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:57:04 -05:00

165 lines
6.2 KiB
Bash

#!/bin/bash
# Deploy a self-hosted Gitea Act Runner for ScoutFS CI on a fresh VM.
#
# Installs podman + git, creates the cache volume, builds the
# scoutfs-builder:el8 / el9 images, registers act_runner with the
# labels the workflow expects, and installs a systemd service.
#
# Tested on: Debian 12, Ubuntu 22.04/24.04, AlmaLinux 9, Rocky 9.
#
# Usage (run as root on the target VM):
#
# GITEA_URL=https://git.anomalous.dev \
# RUNNER_TOKEN=xxxxxxxxxxxxxxxxxxxxxx \
# REPO_URL=https://git.anomalous.dev/alphacentri/scoutfs-build.git \
# ./deploy-runner.sh
#
# Optional env:
# RUNNER_NAME default: scoutfs-$(hostname -s)
# RUNNER_USER default: act_runner
# CACHE_DIR default: /var/cache/scoutfs-ci
# WORK_DIR default: /var/lib/act_runner
# ACT_RUNNER_VER default: 0.2.11
# BRANCH default: dev (scoutfs-build branch to clone)
set -euo pipefail
GITEA_URL="${GITEA_URL:?GITEA_URL is required (e.g. https://git.anomalous.dev)}"
RUNNER_TOKEN="${RUNNER_TOKEN:?RUNNER_TOKEN is required (get from Gitea admin → Actions → Runners)}"
REPO_URL="${REPO_URL:?REPO_URL is required (the scoutfs-build repo clone URL)}"
RUNNER_NAME="${RUNNER_NAME:-scoutfs-$(hostname -s)}"
RUNNER_USER="${RUNNER_USER:-act_runner}"
CACHE_DIR="${CACHE_DIR:-/var/cache/scoutfs-ci}"
WORK_DIR="${WORK_DIR:-/var/lib/act_runner}"
ACT_RUNNER_VER="${ACT_RUNNER_VER:-0.2.11}"
BRANCH="${BRANCH:-main}"
if [[ $EUID -ne 0 ]]; then
echo "ERROR: must run as root" >&2
exit 1
fi
log() { echo -e "\n\033[1;32m>>> $*\033[0m"; }
# --- 1. Install base packages ------------------------------------------------
log "Installing base packages (podman, git, curl)..."
if command -v apt-get >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y --no-install-recommends podman git curl ca-certificates uidmap
elif command -v dnf >/dev/null 2>&1; then
dnf install -y --allowerasing podman git curl ca-certificates shadow-utils
else
echo "ERROR: unsupported distro (no apt-get or dnf)" >&2
exit 1
fi
# --- 2. Create runner user ---------------------------------------------------
if ! id "${RUNNER_USER}" >/dev/null 2>&1; then
log "Creating user ${RUNNER_USER}..."
useradd --system --create-home --home-dir "/home/${RUNNER_USER}" \
--shell /bin/bash "${RUNNER_USER}"
fi
# Enable lingering so the user's podman/systemd units run without login.
loginctl enable-linger "${RUNNER_USER}" 2>/dev/null || true
# --- 3. Cache volume ---------------------------------------------------------
log "Creating cache dir ${CACHE_DIR}..."
mkdir -p "${CACHE_DIR}"
chown -R "${RUNNER_USER}:${RUNNER_USER}" "${CACHE_DIR}"
# --- 4. Clone scoutfs-build and build images --------------------------------
BUILD_CHECKOUT="/home/${RUNNER_USER}/scoutfs-build"
log "Cloning ${REPO_URL} (branch ${BRANCH}) → ${BUILD_CHECKOUT}..."
if [[ -d "${BUILD_CHECKOUT}/.git" ]]; then
sudo -u "${RUNNER_USER}" git -C "${BUILD_CHECKOUT}" fetch --depth 1 origin "${BRANCH}"
sudo -u "${RUNNER_USER}" git -C "${BUILD_CHECKOUT}" checkout "${BRANCH}"
sudo -u "${RUNNER_USER}" git -C "${BUILD_CHECKOUT}" reset --hard "origin/${BRANCH}"
else
sudo -u "${RUNNER_USER}" git clone --depth 1 --branch "${BRANCH}" "${REPO_URL}" "${BUILD_CHECKOUT}"
fi
log "Building scoutfs-builder images (this takes a few minutes)..."
sudo -u "${RUNNER_USER}" bash "${BUILD_CHECKOUT}/ci/images/build.sh"
# --- 5. Download act_runner binary ------------------------------------------
ARCH="$(uname -m)"
case "${ARCH}" in
x86_64) AR_ARCH="amd64" ;;
aarch64) AR_ARCH="arm64" ;;
*) echo "ERROR: unsupported arch ${ARCH}" >&2; exit 1 ;;
esac
AR_URL="https://dl.gitea.com/act_runner/${ACT_RUNNER_VER}/act_runner-${ACT_RUNNER_VER}-linux-${AR_ARCH}"
log "Downloading act_runner ${ACT_RUNNER_VER} (${AR_ARCH})..."
curl -fsSL -o /usr/local/bin/act_runner "${AR_URL}"
chmod +x /usr/local/bin/act_runner
# --- 6. Register runner ------------------------------------------------------
log "Preparing runner work dir ${WORK_DIR}..."
mkdir -p "${WORK_DIR}"
chown -R "${RUNNER_USER}:${RUNNER_USER}" "${WORK_DIR}"
CONFIG_FILE="${WORK_DIR}/config.yaml"
if [[ ! -f "${CONFIG_FILE}" ]]; then
log "Generating runner config..."
sudo -u "${RUNNER_USER}" /usr/local/bin/act_runner generate-config > "${CONFIG_FILE}"
# Point the runner at our cache bind-mount by default for every container job.
# (Workflow also declares the mount, but this is a belt-and-braces.)
chown "${RUNNER_USER}:${RUNNER_USER}" "${CONFIG_FILE}"
fi
if [[ ! -f "${WORK_DIR}/.runner" ]]; then
log "Registering runner with ${GITEA_URL} as '${RUNNER_NAME}'..."
sudo -u "${RUNNER_USER}" /usr/local/bin/act_runner \
--config "${CONFIG_FILE}" \
register \
--no-interactive \
--instance "${GITEA_URL}" \
--token "${RUNNER_TOKEN}" \
--name "${RUNNER_NAME}" \
--labels "scoutfs-el8:docker://localhost/scoutfs-builder:el8,scoutfs-el9:docker://localhost/scoutfs-builder:el9"
# Move the generated .runner file into the work dir if needed.
if [[ -f "/home/${RUNNER_USER}/.runner" ]]; then
mv "/home/${RUNNER_USER}/.runner" "${WORK_DIR}/.runner"
chown "${RUNNER_USER}:${RUNNER_USER}" "${WORK_DIR}/.runner"
fi
else
log "Runner already registered (${WORK_DIR}/.runner exists) — skipping"
fi
# --- 7. systemd service ------------------------------------------------------
log "Installing systemd unit..."
cat > /etc/systemd/system/act_runner.service <<EOF
[Unit]
Description=Gitea Act Runner (ScoutFS CI)
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/act_runner --config ${CONFIG_FILE} daemon
WorkingDirectory=${WORK_DIR}
User=${RUNNER_USER}
Group=${RUNNER_USER}
Restart=always
RestartSec=5
Environment=HOME=/home/${RUNNER_USER}
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now act_runner.service
log "Done."
echo
echo "Runner name: ${RUNNER_NAME}"
echo "Cache dir: ${CACHE_DIR}"
echo "Work dir: ${WORK_DIR}"
echo "Service: systemctl status act_runner"
echo "Logs: journalctl -u act_runner -f"
echo
echo "Verify in Gitea: Site Administration → Actions → Runners"