Installing the Forgejo Runner Binary
This guide walks you through downloading, verifying, and installing the Forgejo runner binary on Linux. By the end, you’ll have a runner registered with your Forgejo/Codeberg instance and running as a systemd service that starts automatically on boot.
Prerequisites
- A Linux machine (x86_64 or ARM64)
wgetorcurl,jq,gpg, andsystemd- Docker installed and running (required for running jobs)
- A Forgejo or Codeberg account with permission to create runners
Step 1: Download and Verify the Binary
First, determine your architecture and fetch the latest release:
# Detect architecture (converts x86_64 → amd64, aarch64 → arm64)
export ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
# Get the latest version tag from Forgejo's API
export RUNNER_VERSION=$(curl -s https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | jq -r .name | cut -c 2-)
# Construct the download URL
export FORGEJO_URL="https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-${ARCH}"
# Download the binary and its signature
wget -O forgejo-runner "${FORGEJO_URL}" || curl -o forgejo-runner "${FORGEJO_URL}"
wget -O forgejo-runner.asc "${FORGEJO_URL}.asc" || curl -o forgejo-runner.asc "${FORGEJO_URL}.asc"
Verify the GPG Signature
Forgejo signs releases with their GPG key. Verify the binary before running it:
# Import Forgejo's public key
gpg --keyserver hkps://keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
# Verify the signature
gpg --verify forgejo-runner.asc forgejo-runner && echo "✓ Verified" || echo "✗ Verification failed"
If verification fails, do not run the binary—re-download and try again.
Step 2: Install the Binary
Make the binary executable and move it to a directory in your PATH:
chmod +x forgejo-runner
sudo cp forgejo-runner /usr/local/bin/forgejo-runner
Test the installation:
forgejo-runner -v
# Should output something like: forgejo-runner version 8.0.0 ...
Step 3: Create a Dedicated Runner User
Run the runner as a dedicated non-root user for security:
# Create user with a home directory
sudo useradd --create-home --shell /bin/bash forgejo-runner-user
# Add to docker group so the runner can spawn job containers
sudo usermod -aG docker forgejo-runner-user
Note: Log out and back in (or reboot) for the docker group change to take effect.
Step 4: Generate the Initial Configuration
Switch to the runner user and generate a default config file:
sudo su - forgejo-runner-user
forgejo-runner generate-config > ~/runner-config.yml
This creates ~/runner-config.yml with sensible defaults. We’ll customize it next.
Step 5: Configure the Runner
Edit ~/runner-config.yml (or use sed/cat as shown below) to make three changes:
1. Set Labels
Labels determine which jobs this runner can execute. Replace the empty labels: [] with your desired labels:
labels:
- ubuntu-latest:host
- ubuntu-22.04:host
- docker:host
Tip: Use
label:hostformat for runners that execute jobs directly on the host. See Forgejo docs for more label formats.
2. Add Your Forgejo/Codeberg Connection
Log into your Forgejo or Codeberg instance:
- Go to Settings → Actions → Runners
- Click Create new runner
- Copy the generated configuration (it contains
url,uuid, andtoken)
Paste it under connections: in your config:
connections:
forgejo:
url: https://codeberg.org/ # or your Forgejo instance URL
uuid: your-runner-uuid-here
token: your-runner-token-here
3. Save the file
Your runner-config.yml should now have both labels and connections populated.
Step 6: Test the Runner Manually
Before setting up systemd, verify everything works:
# Still as forgejo-runner-user
forgejo-runner daemon -c ~/runner-config.yml
You should see output indicating the runner connected and is waiting for jobs. Check your Forgejo/Codeberg runner list—it should show as Online. Press Ctrl+C to stop.
Step 7: Create a Systemd Service
Run the runner automatically on boot and restart on failure.
Create the service file
# Exit back to your sudo user (Ctrl+D or 'exit')
sudo nvim /etc/systemd/system/forgejo-runner.service
Paste the following configuration:
[Unit]
Description=Forgejo Runner
Documentation=https://forgejo.org/docs/latest/admin/actions/
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=forgejo-runner-user
WorkingDirectory=/home/forgejo-runner-user
ExecStart=/usr/local/bin/forgejo-runner daemon -c /home/forgejo-runner-user/runner-config.yml
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=10
TimeoutStopSec=infinity
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/forgejo-runner-user
[Install]
WantedBy=multi-user.target
Security notes: The hardening options above restrict the service’s filesystem access. Adjust
ReadWritePathsif your runner needs access to other directories.
Step 8: Enable and Start the Service
sudo systemctl daemon-reload
sudo systemctl enable --now forgejo-runner.service
sudo systemctl status forgejo-runner.service
The runner should now be active (running). Verify in your Forgejo/Codeberg UI that the runner appears Online.
Troubleshooting
| Issue | Solution |
|---|---|
| Runner shows Offline | Check journalctl -u forgejo-runner -f for errors; verify url, uuid, token in config |
docker: permission denied | Ensure forgejo-runner-user is in the docker group and you’ve rebooted/logged out |
| Jobs stuck in Pending | Check labels match job requirements; verify Docker is running |
| Binary won’t run | Re-verify GPG signature; ensure architecture matches (uname -m) |
Updating the Runner
When a new version is released:
# Stop the service
sudo systemctl stop forgejo-runner
# Re-run Step 1 (download & verify new binary)
# ... download commands from Step 1 ...
# Replace binary
sudo cp forgejo-runner /usr/local/bin/forgejo-runner
# Restart
sudo systemctl start forgejo-runner
References:
Author’s note: The technical content and steps in this post are my own. AI was used only for grammar correction and formatting improvements.