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>
165 lines
6.2 KiB
Bash
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"
|