#!/usr/bin/env bash # ============================================================================ # Install a Gitea Actions runner (act_runner) on THIS host for tlam89/sciagent. # Target: the Gitea + app box 103.149.170.102 (run this ON that box, as root). # # Registers ONE runner with two labels so the CI/CD pipeline can use both: # ci -> docker mode (clean ephemeral containers; backend + frontend jobs) # deploy -> host mode (runs on the host so it can drive `docker compose`) # # Prereqs installed/verified here: Docker + compose plugin, Node.js (needed by # host-mode actions/checkout). Re-runnable: skips steps already done. # # Usage (token already minted for this repo; rotate via Gitea if it expires): # sudo bash setup-gitea-runner.sh # Override: # GITEA_URL=http://localhost:3000 RUNNER_TOKEN=xxx bash setup-gitea-runner.sh # ============================================================================ set -euo pipefail GITEA_URL="${GITEA_URL:-http://localhost:3000}" RUNNER_TOKEN="${RUNNER_TOKEN:-aCd3rpPnJTAPVHqsTIme9SaJm3pUbnbyOQqMrt9O}" RUNNER_NAME="${RUNNER_NAME:-sciagent-box-runner}" RUNNER_LABELS="${RUNNER_LABELS:-ci:docker://catthehacker/ubuntu:act-22.04,deploy:host}" ACT_VERSION="${ACT_VERSION:-0.2.11}" RUNNER_DIR="${RUNNER_DIR:-/opt/act_runner}" log(){ printf '\n\033[36m==> %s\033[0m\n' "$*"; } [[ "$(id -u)" -eq 0 ]] || { echo "Run as root (sudo)."; exit 1; } # --- 1. Docker + compose plugin -------------------------------------------- if ! command -v docker >/dev/null 2>&1; then log "Installing Docker (get.docker.com convenience script)" curl -fsSL https://get.docker.com | sh fi if ! docker compose version >/dev/null 2>&1; then log "docker compose plugin missing — installing docker-compose-plugin" (apt-get update && apt-get install -y docker-compose-plugin) || \ echo "WARN: install the compose plugin manually for your distro." fi systemctl enable --now docker >/dev/null 2>&1 || true docker version --format '{{.Server.Version}}' >/dev/null 2>&1 || { echo "Docker daemon not running"; exit 1; } # --- 2. Node.js (host-mode jobs run actions/checkout, which needs node) ----- if ! command -v node >/dev/null 2>&1; then log "Installing Node.js 20" curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs || \ echo "WARN: install Node.js 20 manually if your distro is non-Debian." fi # --- 3. Download act_runner ------------------------------------------------- mkdir -p "$RUNNER_DIR" cd "$RUNNER_DIR" if [[ ! -x "$RUNNER_DIR/act_runner" ]]; then log "Downloading act_runner ${ACT_VERSION}" arch="$(uname -m)"; case "$arch" in x86_64) arch=amd64;; aarch64) arch=arm64;; esac curl -fsSL -o act_runner \ "https://dl.gitea.com/act_runner/${ACT_VERSION}/act_runner-${ACT_VERSION}-linux-${arch}" chmod +x act_runner fi # --- 4. Register ------------------------------------------------------------ if [[ ! -f "$RUNNER_DIR/.runner" ]]; then log "Registering with Gitea ($GITEA_URL) labels: $RUNNER_LABELS" ./act_runner register --no-interactive \ --instance "$GITEA_URL" \ --token "$RUNNER_TOKEN" \ --name "$RUNNER_NAME" \ --labels "$RUNNER_LABELS" else log ".runner already exists — skipping register" fi [[ -f "$RUNNER_DIR/config.yaml" ]] || ./act_runner generate-config > config.yaml # generate-config injects DEFAULT labels (ubuntu-latest/22.04/20.04) into config.yaml # which OVERRIDE the --labels passed at registration. Force our labels into config.yaml # so the daemon advertises ci (docker) + deploy (host), not the defaults. python3 - "$RUNNER_DIR/config.yaml" "$RUNNER_LABELS" <<'PY' import sys,re path,labels=sys.argv[1],sys.argv[2].split(",") s=open(path).read().splitlines(keepends=True) o=[];i=0;n=len(s);done=False while i", ", ".join(labels)) PY # --- 5. systemd service ----------------------------------------------------- log "Installing systemd service act_runner" cat > /etc/systemd/system/act_runner.service <