#!/bin/bash # ============================================================================= # FORGEJO RUNNER - FULL SYSTEM DEPLOYMENT WITH SYSTEMD # Supports both DIRECT and DOCKER modes # ============================================================================= # --- CONFIGURATION VARIABLES --- FORGEJO_URL="http://192.168.2.76:3006" # CHANGE THIS REGISTRATION_TOKEN="your-registration-token" # CHANGE THIS RUNNER_NAME="selfhosted-runner-01" RUNNER_VERSION="latest" # "latest" or specific version RUNNER_MODE="direct" # "direct" or "docker" # ============================================================================= set -e echo "============================================================" echo "FORGEJO RUNNER DEPLOYMENT" echo "============================================================" echo "Mode: $RUNNER_MODE" echo "Instance: $FORGEJO_URL" echo "" # --- STEP 1: Detect architecture --- echo "Detecting architecture..." export ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/armv7/') echo "Architecture: $ARCH" # --- STEP 2: Get latest version --- if [ "$RUNNER_VERSION" = "latest" ]; then echo "Fetching latest version..." export RUNNER_VERSION=$(curl -s https://code.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | grep -o '"tag_name":"v[0-9]\+\.[0-9]\+\.[0-9]\+"' | head -1 | sed 's/"tag_name":"//' | sed 's/"//' | sed 's/^v//') echo "Version: $RUNNER_VERSION" else RUNNER_VERSION=${RUNNER_VERSION#v} echo "Version: $RUNNER_VERSION" fi echo "" # ============================================================================= # DIRECT MODE # ============================================================================= if [ "$RUNNER_MODE" = "direct" ]; then echo "=== DIRECT MODE INSTALLATION ===" echo "Installing runner directly on the system" echo "" # --- Download binary --- echo "Downloading runner binary..." wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-${ARCH} # --- Make executable --- echo "Making executable..." chmod +x forgejo-runner # --- Move to /usr/local/bin --- echo "Moving to /usr/local/bin..." sudo mv forgejo-runner /usr/local/bin/ # --- Register runner --- echo "Registering runner with Forgejo..." forgejo-runner register \ --token "$REGISTRATION_TOKEN" \ --name "$RUNNER_NAME" \ --instance "$FORGEJO_URL" \ --labels "$RUNNER_NAME:host" \ --no-interactive # --- Create config.yaml --- echo "Creating configuration..." cat > config.yaml << EOF instance: $FORGEJO_URL token: "$REGISTRATION_TOKEN" log: level: info runner: file: .runner capacity: 1 timeout: 30m shutdown_timeout: 30m insecure: true fetch_timeout: 30s fetch_interval: 60s report_interval: 10s labels: - "$RUNNER_NAME:host" cache: enabled: true dir: "" host: workdir_parent: "" EOF # --- Create systemd service --- echo "Creating systemd service..." sudo tee /etc/systemd/system/forgejo-runner.service > /dev/null << EOF [Unit] Description=Forgejo Actions Runner After=network.target [Service] Type=simple User=$USER Group=$USER WorkingDirectory=$PWD ExecStart=/usr/local/bin/forgejo-runner daemon --config $PWD/config.yaml Restart=always RestartSec=10 StartLimitBurst=3 StartLimitInterval=60s LimitNOFILE=65536 LimitNPROC=65536 [Install] WantedBy=multi-user.target EOF # --- Enable and start service --- echo "Starting service..." sudo systemctl daemon-reload sudo systemctl enable forgejo-runner.service sudo systemctl start forgejo-runner.service echo "" echo "=== DIRECT MODE DEPLOYMENT COMPLETE ===" echo "" echo "Service status:" sudo systemctl status forgejo-runner.service --no-pager echo "" echo "To view logs:" echo " sudo journalctl -u forgejo-runner -f" echo "" echo "Runner location: /usr/local/bin/forgejo-runner" echo "Config location: $PWD/config.yaml" # ============================================================================= # DOCKER MODE # ============================================================================= elif [ "$RUNNER_MODE" = "docker" ]; then echo "=== DOCKER MODE INSTALLATION ===" echo "Installing runner with Docker Compose" echo "" # --- Check Docker --- echo "Checking Docker..." if ! command -v docker &> /dev/null; then echo "Docker not found. Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER sudo systemctl enable docker --now rm get-docker.sh echo "Docker installed successfully" else echo "Docker is already installed" fi if ! systemctl is-active --quiet docker; then echo "Starting Docker service..." sudo systemctl start docker fi echo "Docker is running" # --- Check Docker Compose --- echo "Checking Docker Compose..." if ! command -v docker compose &> /dev/null; then echo "Docker Compose not found. Installing..." if command -v apt-get &> /dev/null; then sudo apt-get update && sudo apt-get install -y docker-compose-plugin elif command -v yum &> /dev/null; then sudo yum install -y docker-compose-plugin else echo "ERROR: Could not install docker-compose-plugin" echo "Please install Docker Compose manually" exit 1 fi else echo "Docker Compose is already installed" fi echo "" # --- Create working directory --- echo "Creating working directory..." mkdir -p ~/forgejo-runner/{data,cache} cd ~/forgejo-runner # --- Register runner using Docker --- echo "Registering runner with Forgejo..." docker run -it --rm \ -v $(pwd)/data:/data \ -w /data \ --user root \ data.forgejo.org/forgejo/runner:${RUNNER_VERSION} \ forgejo-runner register \ --no-interactive \ --token "$REGISTRATION_TOKEN" \ --name "$RUNNER_NAME" \ --instance "$FORGEJO_URL" \ --labels "$RUNNER_NAME:host" # --- Generate config.yaml --- echo "Creating configuration..." cat > data/config.yaml << EOF instance: $FORGEJO_URL token: "$REGISTRATION_TOKEN" log: level: info runner: file: .runner capacity: 1 timeout: 30m shutdown_timeout: 30m insecure: true fetch_timeout: 30s fetch_interval: 60s report_interval: 10s labels: - "$RUNNER_NAME:host" cache: enabled: true dir: "" container: privileged: false valid_volumes: - '**' docker_host: "" force_pull: false host: workdir_parent: "" EOF # --- Create docker-compose.yml --- echo "Creating docker-compose.yml..." cat > docker-compose.yml << EOF version: '3.8' services: docker-in-docker: image: docker:dind container_name: ${RUNNER_NAME}_dind privileged: true command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false'] restart: unless-stopped volumes: - dind-storage:/var/lib/docker runner: image: data.forgejo.org/forgejo/runner:${RUNNER_VERSION} container_name: ${RUNNER_NAME} depends_on: docker-in-docker: condition: service_started environment: DOCKER_HOST: tcp://docker-in-docker:2375 user: 0:0 volumes: - ./data:/data - ./cache:/cache restart: unless-stopped command: /bin/sh -c " apk update && apk add --no-cache nodejs npm && sleep 5 && forgejo-runner daemon --config /data/config.yaml " volumes: dind-storage: EOF # --- Create systemd service --- echo "Creating systemd service..." sudo tee /etc/systemd/system/forgejo-runner-docker.service > /dev/null << EOF [Unit] Description=Forgejo Runner (Docker Compose) After=docker.service Requires=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=$HOME/forgejo-runner ExecStart=/usr/bin/docker compose up -d ExecStop=/usr/bin/docker compose down ExecReload=/usr/bin/docker compose restart StandardOutput=journal User=$USER Group=$USER [Install] WantedBy=multi-user.target EOF # --- Enable and start service --- echo "Starting service..." sudo systemctl daemon-reload sudo systemctl enable forgejo-runner-docker.service sudo systemctl start forgejo-runner-docker.service echo "" echo "=== DOCKER MODE DEPLOYMENT COMPLETE ===" echo "" echo "Service status:" sudo systemctl status forgejo-runner-docker.service --no-pager echo "" echo "To view logs:" echo " docker compose -f $HOME/forgejo-runner/docker-compose.yml logs -f runner" echo "" echo "To manage:" echo " cd ~/forgejo-runner" echo " docker compose up -d # start" echo " docker compose down # stop" echo " docker compose restart # restart" echo "" echo "Runner location: ~/forgejo-runner" # ============================================================================= # INVALID MODE # ============================================================================= else echo "ERROR: Invalid RUNNER_MODE. Use 'direct' or 'docker'" exit 1 fi echo "" echo "============================================================" echo "DEPLOYMENT COMPLETE" echo "============================================================" echo "" echo "Runner should now appear online in Forgejo Admin -> Actions -> Runners" echo "URL: $FORGEJO_URL/admin/actions/runners" echo "" if [ "$RUNNER_MODE" = "direct" ]; then echo "To check runner logs: sudo journalctl -u forgejo-runner -f" else echo "To check runner logs: docker compose -f $HOME/forgejo-runner/docker-compose.yml logs -f runner" fi echo "============================================================"