GuiderUtveckling och driftCI/CD med Forgejo Runner

Kör CI/CD för Forgejo med Forgejo Runner och Podman utan root

Forgejo Runner på Debian 13, som kör dina jobb i Forgejo Actions i rootless Podman under en egen användare, med tester, cache, artefakter, en containeravbild som pushas till Forgejo och driftsättning över SSH, utan privilegierade containrar.

Testad på Forgejo Runner 13.2.0 och Forgejo 15.0.10 på Debian 13 (trixie) på en server hos Melonslab Uppdaterad 14 oktober 2026

Rekommenderad server för guiden

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy · 2 vCPU · 8 GB Minne · 60 GB Lagring

Månadsvis, ingen bindningstid 7 dagars öppet köp

100 kr/mån

Beställ nu
På den här sidan

Det här sätter du upp

Forgejo Actions kör dina tester, byggen och driftsättningar när du pushar till Forgejo, med arbetsflöden som liknar GitHub Actions. Forgejo delar bara ut arbetet. En runner hämtar varje jobb och kör det, här i en ny rootless-container under en egen användare som heter runner.

Forgejo Runner görs av Forgejo-projektet, en gemenskap som utvecklar Forgejo öppet under Codeberg e.V., en ideell förening i Berlin. Den är fri programvara under GPL, version 3.0 eller senare (kontrollerat 14 oktober 2026).

Forgejo ger ut runnern både som ett enda program och som en containeravbild, code.forgejo.org/forgejo/runner. Med rootless Podman passar programmet bättre: det pratar direkt med runner-användarens Podman, och cachen som det ger jobben lyssnar på serverns egen adress. I en container skulle den behöva Podmans socket monterad och cacheporten publicerad, och jobbens containrar skulle ändå startas av samma Podman. Priset är att podman auto-update inte uppdaterar den; steg 17 visar hur du gör.

Guiden bygger på Forgejo-guiden, som sätter upp runnern i två korta steg. Här går vi längre. Varje steg nedan har körts på en VC-P Alloy (2 vCPU, 8 GB) hos Melonslab med Debian 13:

  • Forgejo Runner 13.2.0 körde jobb åt Forgejo 15.0.10 i rootless-containrar, två åt gången.
  • Ett arbetsflöde hämtade ett litet Node.js-projekt, körde dess tester på Node.js 22 och 24 samtidigt och återställde sin npm-cache vid nästa körning. Varje körning sparade ett paket som artefakt, som gick att ladda ner från körningens sida. Både ett schema och knappen Run workflow startade det.
  • En hemlighet visades som *** i loggen. Ett jobb byggde en containeravbild med Buildah, utan privilegierat läge, och pushade den till Forgejos paketregister. Nästa jobb driftsatte den över SSH med en nyckel som bara kan köra ett kommando, och den nya versionen svarade bakom Caddy.
  • En pull request från en annan användares fork väntade på godkännande. När den godkänts fick jobbet inga av hemligheterna, och dess token kunde inte pusha eller ändra repot.
  • Jobben kunde inte nå Podmans socket eller appar som bara lyssnar på serverns loopback-adress, och kunde inte montera filsystem.
  • Runnern uppdaterades från 13.1.0 till 13.2.0 och återställdes från en säkerhetskopia, och allt startade igen av sig självt efter en omstart av servern.

Runnern använde omkring 35 MB minne mellan jobben. Med två jobb igång använde servern omkring 450 MB mer. Varje jobbavbild tar omkring 1,3 GB disk.

Innan du börjar

Du behöver:

  • Forgejo uppsatt som i Forgejo-guiden, steg 1 till 6, med Caddy igång. Om du också gjorde steg 7 och 8 där har du redan gjort steg 2 till 4 här. Byt runnerns inställningar och tjänst mot dem i steg 5 och 6, behåll ditt eget server:-block och starta om den;
  • ufw påslaget som i säkerhetsguiden. Runnern öppnar portar för jobbens cache, som brandväggen håller stängda mot internet;
  • för driftsättningen i steg 11, en A-post och en AAAA-post för hello.example.com som pekar på din server.

Exemplen använder git.example.com för Forgejo, hello.example.com för appen du driftsätter, anna som ditt användarnamn och 203.0.113.10 som serverns IPv4-adress. Byt ut dem genomgående.

Forgejo finns på svenska: under Settings > Appearance väljer du Svenska som Default language och sedan Change language. Guiden använder de engelska namnen på menyer och knappar.

1. Kontrollera att Actions är påslaget

I Forgejo 15 är Actions påslaget, även för nya repon. I ett repo visar Settings > Units att Actions ("Enable integrated CI/CD pipelines with Forgejo Actions") är ikryssat, och repot har fliken Actions. Om du har stängt av det för ett repo kryssar du i rutan där och väljer Save settings.

2. Installera runnern

Som root installerar du Git, som runnern använder för att hämta actions, och laddar ner runnern. Forgejo signerar varje version, så kontrollera signaturen innan du installerar den:

apt install -y git gpg curl
v=13.2.0
url=https://code.forgejo.org/forgejo/runner/releases/download/v$v/forgejo-runner-$v-linux-amd64
curl -fL -o forgejo-runner $url
curl -fL -o forgejo-runner.asc $url.asc
gpg --keyserver hkps://keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
gpg --verify forgejo-runner.asc forgejo-runner

Det sista kommandot måste skriva ut Good signature from "Forgejo <contact@forgejo.org>". En varning om att nyckeln inte är certifierad är normal. 13.2.0 var den senaste versionen när vi skrev det här; code.forgejo.org/forgejo/runner/releases listar nyare. Installera den:

install -m 755 forgejo-runner /usr/local/bin/forgejo-runner
rm forgejo-runner forgejo-runner.asc

3. Skapa användaren

Jobben kör kod från dina repon, så runnern får en egen användare. Fortfarande som root:

useradd -m -s /bin/bash runner
loginctl enable-linger runner
systemctl --user -M runner@ enable --now podman.socket
machinectl shell runner@

podman.socket är runner-användarens Docker-kompatibla API till Podman. Runnern startar varje jobbs container via det, som den här användaren. Allt fram till steg 7 körs som runner.

Jobb börjar oftast med att hämta din kod från https://git.example.com, som är den här servern. Rootless-containrar delar normalt serverns egen adress och kan därför inte nå den. Ge den här användarens containrar egna adresser:

mkdir -p ~/.config/containers

Skapa ~/.config/containers/containers.conf:

# Give job containers addresses of their own, so they can reach this
# server's public address, and Forgejo on it.
[network]
pasta_options = ["-a", "10.0.2.0", "-n", "24", "-g", "10.0.2.2", "--dns-forward", "10.0.2.3"]

Det är den andra lösningen i steg 8 i Podman-guiden, här utan IPv6. Den gäller bara användaren runner: Forgejo och appen du driftsätter körs som andra användare och behåller sina inställningar.

4. Skapa runnern i Forgejo

Öppna https://git.example.com/admin/actions/runners i Forgejo och välj Create new runner. Ge den ett namn, till exempel server-runner, och välj Create. Forgejo visar en enda gång runnerns UUID och token, och ett block som börjar med server:. Låt sidan vara öppen till nästa steg.

En runner som skapas här tar jobb från alla repon. Under Settings > Actions > Runners i ett repo finns samma knapp, för en runner som bara tar det repots jobb.

Samma sida har också Registration Token (Deprecated), för det äldre kommandot forgejo-runner register. Det fungerar fortfarande, och skriver token till en fil, .runner, som alla användare på servern kan läsa. Sättet ovan håller den i en fil som bara runner kan läsa.

5. Ställ in den

Skapa ~/runner-config.yml, med server:-blocket från Forgejo sist i stället för det nedan:

runner:
  # How many jobs run at the same time
  capacity: 2
  # Stop a job that runs longer than this
  timeout: 1h
  # On stop or reboot, give running jobs this long to finish
  shutdown_timeout: 10m
  labels:
    - docker:docker://data.forgejo.org/oci/node:24-trixie
    - ubuntu-latest:docker://data.forgejo.org/oci/node:24-trixie

cache:
  enabled: true

container:
  # No privileged containers, no Podman socket and no server folders in jobs
  privileged: false
  docker_host: "-"
  valid_volumes: []

server:
  connections:
    forgejo:
      url: https://git.example.com/
      uuid: 00000000-0000-0000-0000-000000000000
      token: 0000000000000000000000000000000000000000

Gör den sedan läsbar bara för runner, eftersom den innehåller token:

chmod 600 ~/runner-config.yml

Vad inställningarna gör:

  • Ett arbetsflöde väljer runner med runs-on:. Båda etiketterna kör jobbet i en container från data.forgejo.org/oci/node:24-trixie, Debian 13 med Node.js, Git och Python, som Forgejo kopierar från Docker Hub. Med ubuntu-latest fungerar arbetsflöden som skrivits för GitHub utan ändringar, i den här avbilden, som har mycket mindre installerat än GitHubs egna maskiner.
  • capacity: 2 passar två vCPU. Höj den på en större server, eller för jobb som mest väntar.
  • cache startar cacheservern som actions/cache använder, på en slumpvis port på servern. ufw håller porten stängd mot internet.
  • Raderna under container är standardvärdena, utskrivna så att du ser dem: jobben körs utan privilegierat läge, kan inte nå runner-användarens Podman och kan inte montera mappar från servern. Steg 7 förklarar vad det ger.

forgejo-runner generate-config skriver ut alla inställningar, med kommentarer.

6. Starta den

Skapa ~/.config/systemd/user/forgejo-runner.service:

mkdir -p ~/.config/systemd/user
[Unit]
Description=Forgejo Runner, which runs Forgejo Actions jobs in rootless Podman
After=podman.socket
Wants=podman.socket

[Service]
ExecStart=/usr/local/bin/forgejo-runner daemon -c %h/runner-config.yml
WorkingDirectory=%h
Restart=always
RestartSec=10
# A little longer than shutdown_timeout in runner-config.yml
TimeoutStopSec=15min

[Install]
WantedBy=default.target

Starta den:

systemctl --user daemon-reload
systemctl --user enable --now forgejo-runner
journalctl --user -u forgejo-runner

Loggen visar declared successfully, med etiketterna, och runnersidan i Forgejo visar den som Idle. När du har ändrat runner-config.yml kör du systemctl --user restart forgejo-runner. Använd inte reload: det stoppade runnern i våra tester.

7. Vad ett jobb kan och inte kan göra

Vi kontrollerade inifrån ett jobb. Varje jobb får en ny container i ett eget Podman-nätverk, och runnern tar bort båda när jobbet är klart. Root i containern är användaren runner utanför den, så ett jobb kan inte läsa Forgejos filer eller någon annan apps filer på servern. Det kan inte nå Podmans socket, och kan alltså inte starta eller stoppa containrar på servern. Att montera ett filsystem nekades. Jobben nådde internet, serverns publika portar, som 22 och 443, precis som vilken besökare som helst, och runnerns cache. Appar som bara lyssnar på 127.0.0.1, som Forgejo självt på port 8089, gick inte att nå.

Det här ger det inte:

  • Jobben delar kärna med servern. En container är inte en virtuell maskin. En sårbarhet i kärnan skulle kunna släppa ut ett jobb, som användaren runner, med runnerns token. Kör inte kod du inte litar på på den här servern, eller ge den en runner på en egen server (steg 14).
  • Den som kan pusha kan läsa hemligheterna. Ett arbetsflöde i repot får repots hemligheter, och ett ändrat arbetsflöde kan skicka dem vart som helst. Forgejo döljer det exakta värdet av en hemlighet i loggen, men inte en kopia av den i en annan form.
  • Pull requests från forkar väntar på dig. Forgejo höll en sådan körning tills vi valde Approve once eller Approve always i pull requesten, eller Deny. Efter godkännandet fick jobbet inga av repots hemligheter, och dess token kunde inte pusha, ändra repot eller lägga till etiketter. Det kör ändå forkens kod på din server, med tillgång till internet, och ser repots variabler. Läs ändringen innan du godkänner den.
  • Privilegierat läge är avstängt. Inget i guiden behöver det, inte ens bygget av avbilder i steg 10.

8. Testa ett projekt

Den här delen görs på din dator, i repot hello från steg 9 i Forgejo-guiden. Lägg till en liten Node.js-app med ett test. Skapa package.json:

{
  "name": "hello",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --test",
    "start": "node server.js"
  }
}

greet.js:

import ms from 'ms';

export function greet(name, uptimeMs) {
  return `Hello, ${name}! Up for ${ms(uptimeMs, { long: true })}.`;
}

greet.test.js:

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { greet } from './greet.js';

test('greets by name', () => {
  assert.equal(greet('Anna', 60000), 'Hello, Anna! Up for 1 minute.');
});

server.js:

import http from 'node:http';
import { greet } from './greet.js';

const started = Date.now();
http.createServer((req, res) => {
  res.end(greet('world', Date.now() - started) + '\n');
}).listen(8080);

Och .gitignore:

node_modules/
*.tgz

Med Node.js installerat kör du npm install ms@2, som lägger till det enda beroendet och skriver package-lock.json. Skapa sedan .forgejo/workflows/ci.yml:

on:
  push:
  pull_request:
  schedule:
    - cron: '30 3 * * 1'
  workflow_dispatch:

jobs:
  test:
    runs-on: docker
    strategy:
      matrix:
        node: [22, 24]
    container:
      image: data.forgejo.org/oci/node:${{ matrix.node }}-trixie
    steps:
      - uses: actions/checkout@v6
      - uses: actions/cache@v5
        with:
          path: ~/.npm
          key: npm-${{ matrix.node }}-${{ hashFiles('package-lock.json') }}
      - run: npm ci
      - run: npm test
      - run: npm pack
      - uses: forgejo/upload-artifact@v5
        with:
          name: hello-node${{ matrix.node }}
          path: '*.tgz'

Spara och pusha allt:

git add .
git commit -m "Add an app, tests and CI"
git push

Repots flik Actions visar körningen, med ett jobb per Node.js-version, och utdata från varje steg. Det här gör arbetsflödet:

  • on: startar det vid varje push och pull request, varje måndag klockan 03.30, och med knappen Run workflow, som syns på fliken Actions när du väljer ci.yml. Forgejo läser schemat i UTC och kör det på standardgrenen.
  • matrix kör jobbet en gång för varje Node.js-version, samtidigt, och container: väljer avbild för var och en. Utan den körs jobbet i avbilden för runnerns etikett.
  • actions/cache sparar ~/.npm när jobbet är klart och återställer den nästa gång, så länge package-lock.json är oförändrad. Loggen för den andra körningen säger Cache restored from key.
  • forgejo/upload-artifact sparar paketet som npm pack gjorde. Körningens sida listar det under Artifacts, och du laddar ner det som en ZIP-fil. Forgejo sparar artefakter i 90 dagar.

9. Hemligheter och variabler

Lösenord och nycklar som jobben behöver lägger du som hemligheter. Öppna Settings > Actions > Secrets i repot och välj Add secret. Inställningar som inte är hemliga, som en adress, lägger du under Variables > Add variable. Ett arbetsflöde läser dem som ${{ secrets.NAME }} och ${{ vars.NAME }}:

      - run: ./upload.sh "$TARGET"
        env:
          TARGET: ${{ vars.UPLOAD_TARGET }}
          API_KEY: ${{ secrets.API_KEY }}

Skicka in dem via env:, som här, i stället för att skriva in dem direkt i kommandot, så att ett värde med citattecken eller mellanslag inte kan ändra kommandot. Forgejo byter ut en hemlighets värde mot *** i loggen. När en hemlighet väl är sparad kan ingen läsa den i Forgejo, bara ersätta den. De två nästa stegen använder båda.

10. Bygg en containeravbild

Ett jobb kan bygga appens avbild och pusha den till Forgejos eget paketregister, så att du kan köra den var som helst med podman pull git.example.com/anna/hello.

Jobbets automatiska token kunde logga in i registret men inte pusha: Forgejo svarade authentication required. Skapa en token som kan det. Öppna menyn under din avatar i Forgejo, Settings > Applications > Generate new token. Döp den till ci-packages, låt Repository and organization access stå på All, sätt package till Read and write under Select permissions och välj Generate token. Kopiera den och lägg in den som hemligheten REGISTRY_TOKEN i repot hello.

På din dator lägger du till en Containerfile i repot:

FROM docker.io/library/node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY *.js ./
USER node
EXPOSE 8080
CMD ["node", "server.js"]

Och .containerignore, som håller de här mapparna utanför avbilden:

.git
node_modules

Lägg till det här jobbet sist i ci.yml, indraget två mellanslag som test::

  image:
    needs: test
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: docker
    steps:
      - uses: actions/checkout@v6
      - name: Install Buildah
        run: apt-get update -qq && apt-get install -y -qq buildah > /dev/null
      - name: Build the image
        run: buildah build --storage-driver vfs --isolation chroot -t hello .
      - name: Push it to Forgejo
        env:
          TOKEN: ${{ secrets.REGISTRY_TOKEN }}
        run: |
          registry=${GITHUB_SERVER_URL#https://}
          echo "$TOKEN" | buildah login -u "$GITHUB_ACTOR" --password-stdin $registry
          buildah push --storage-driver vfs hello $registry/$GITHUB_REPOSITORY:${GITHUB_SHA::7}
          buildah push --storage-driver vfs hello $registry/$GITHUB_REPOSITORY:latest

needs: test bygger bara när testerna går igenom, och raden if: bara vid push till main. Spara och pusha. Avbilden dyker upp i Forgejo under fliken Packages på din profil, som hello, med två taggar: latest och commitens korta id.

Buildah bygger avbilder utan en tjänst i bakgrunden, och här utan några extra rättigheter. Debians paket buildah installeras i varje jobb, vilket tar ungefär en halv minut. --storage-driver vfs lagrar lagren som vanliga mappar: overlay-drivrutinen behöver /dev/fuse, som ett jobb inte har, och misslyckades med fuse: device not found. --isolation chroot kör raderna med RUN utan att starta en container inne i containern. I vårt test tog hela jobbet omkring 75 sekunder.

Avbilden är lika öppen som ditt konto. Är ditt konto eller din organisation privat, är avbilden det också, och den som hämtar den måste logga in, som i steg 11.

11. Driftsätt över SSH

Det sista jobbet loggar in på servern över SSH och startar den nya avbilden. Nyckeln det använder kan köra ett kommando och inget annat: inget skal, inga andra kommandon och ingen portvidarebefordran.

Kör appen. Skapa en användare för den som root:

useradd -m -s /bin/bash hello
loginctl enable-linger hello
machinectl shell hello@

Som hello:

mkdir -p ~/.config/containers/systemd

Skapa ~/.config/containers/systemd/hello.container:

[Unit]
Description=Hello, deployed from Forgejo Actions

[Container]
ContainerName=hello
Image=git.example.com/anna/hello:latest
# Only Caddy, on this server, can reach the app
PublishPort=127.0.0.1:8121:8080
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target

Om avbilden är privat loggar du först in med en token som kan läsa paket, skapad som i steg 10 med package satt till Read. Sparad i ~/.config/containers/auth.json gäller inloggningen även efter en omstart:

podman login --authfile ~/.config/containers/auth.json git.example.com

Starta den:

systemctl --user daemon-reload
systemctl --user start hello
curl http://127.0.0.1:8121/

Den svarar Hello, world! Up for 2 seconds. Gå tillbaka till root med exit, byt till machinectl shell caddy@, lägg till det här blocket sist i ~/Caddyfile och starta om Caddy med systemctl --user restart caddy:

hello.example.com {
    reverse_proxy 127.0.0.1:8121
}

Skapa nyckeln för driftsättning. På din dator:

ssh-keygen -t ed25519 -N '' -C deploy-hello -f hello-deploy

Det ger hello-deploy, den privata nyckeln, och hello-deploy.pub. Som root på servern byter du till machinectl shell hello@ och skapar ~/.ssh/authorized_keys:

install -d -m 700 ~/.ssh
nano ~/.ssh/authorized_keys

Skriv en enda rad: texten nedan, ett mellanslag och hela innehållet i hello-deploy.pub:

restrict,command="podman auto-update && podman image prune -f" ssh-ed25519 AAAA... deploy-hello
chmod 600 ~/.ssh/authorized_keys

Vad en inloggning med den här nyckeln än ber om, kör servern podman auto-update, som hämtar en nyare latest och startar om appen, och tar sedan bort den gamla avbilden. restrict stänger av portvidarebefordran och resten. I vårt test körde en inloggning med nyckeln som bad om rm -rf ~ i stället podman auto-update, och en portvidarebefordran nekades.

Ge Forgejo nyckeln och serverns adress. Lägg in hela hello-deploy, från -----BEGIN till sista raden, som hemligheten DEPLOY_KEY i repot hello. Radera sedan hello-deploy från din dator, eller spara den i din lösenordshanterare. Lägg till två variabler: DEPLOY_HOST, med serverns adress, 203.0.113.10, och DEPLOY_KNOWN_HOSTS, med raden som det här skriver ut som root på servern:

echo "203.0.113.10 $(cut -d' ' -f1,2 /etc/ssh/ssh_host_ed25519_key.pub)"

Det är serverns egen SSH-nyckel, så att jobbet kan kontrollera att det kom till rätt server.

Lägg till jobbet sist i ci.yml:

  deploy:
    needs: image
    runs-on: docker
    steps:
      - name: Deploy over SSH
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
          KNOWN_HOSTS: ${{ vars.DEPLOY_KNOWN_HOSTS }}
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts
          ssh -i ~/.ssh/deploy_key hello@${{ vars.DEPLOY_HOST }}

Byt 'world' i server.js mot ditt namn, spara och pusha. Körningen testar, bygger, pushar och driftsätter, på ungefär två minuter, och loggen för jobbet deploy slutar med en tabell där UPDATED är true. https://hello.example.com visar den nya texten.

Appen kan lika gärna ligga på en annan server: skapa användaren och nyckeln där, och lägg den serverns adress och SSH-nyckel i de två variablerna.

12. Actions från GitHubs marknadsplats

uses: actions/checkout@v6 anger ingen server. Då hämtar Forgejo action från https://data.forgejo.org, som har kopior av omkring 650 populära repon med actions: actions/*, docker/* och liknande, men inte alla. För andra actions skriver du hela adressen:

      - uses: https://github.com/actions/github-script@v7
      - uses: https://code.forgejo.org/actions/checkout@v5

Det här testade vi:

  • actions/checkout v5 och v6, actions/cache v4 och v5, och actions/github-script från GitHub fungerade.
  • actions/upload-artifact v4 och senare stoppade med "not currently supported on GHES". Forgejos egen kopia, forgejo/upload-artifact, fungerade i v4 och v5, och forgejo/download-artifact@v4 hämtade en artefakt i ett senare jobb.
  • Actions som kör kommandot docker, som docker/login-action, misslyckades med "Unable to locate executable file: docker". Jobbavbilden har ingen Docker, och jobben kan inte nå Podman. Bygg avbilder som i steg 10 i stället.

Vill du i stället hämta actions utan angiven server från GitHub lägger du till den här raden i forgejo.container från Forgejo-guiden, som forgejo, och startar om Forgejo:

Environment=FORGEJO__actions__DEFAULT_ACTIONS_URL=https://github.com

Forgejo sparar den i sin egen inställningsfil. För att gå tillbaka ändrar du den till https://data.forgejo.org: det räcker inte att ta bort raden.

13. Kapacitet och städning

capacity i runner-config.yml är hur många jobb som körs samtidigt. Matrisen i steg 8 använde båda platserna, och servern använde omkring 450 MB mer minne medan de kördes. Andra jobb väntar på en ledig plats och visas som väntande på fliken Actions.

Runnern tar bort varje jobbs container och nätverk när jobbet är klart. Det som blir kvar är jobbavbilderna, omkring 1,3 GB styck, och de actions som den har hämtat, i ~/.cache/act. Som runner låter du en timer ta bort de avbilder som inget jobb använder, en gång i veckan. Skapa ~/.config/systemd/user/runner-cleanup.service:

[Unit]
Description=Remove job images and build leftovers no job is using

[Service]
Type=oneshot
ExecStart=/usr/bin/podman system prune --all --force

Och ~/.config/systemd/user/runner-cleanup.timer:

[Unit]
Description=Weekly cleanup of the runner's images

[Timer]
OnCalendar=Sun 04:30
Persistent=true

[Install]
WantedBy=timers.target
systemctl --user daemon-reload
systemctl --user enable --now runner-cleanup.timer

Första jobbet efter en städning laddar ner sin avbild igen, så du får också den senaste varje vecka. podman system df visar hur mycket plats som används. På appens sida tar podman image prune -f i nyckelns kommando bort varje avbild som har ersatts.

14. En andra runner på en annan server

När jobben behöver mer plats, eller kod du inte litar på ska hållas borta från Forgejo, lägger du till en runner på en annan server. Sätt upp den servern som i Podman-guiden, med ufw, och gör steg 2 till 6 där. Den ansluter ut till https://git.example.com, så den behöver ingen öppen port. I steg 4 skapar du en ny runner: var och en har sin egen token. Ge den en egen etikett, till exempel big:docker://data.forgejo.org/oci/node:24-trixie, så körs arbetsflöden med runs-on: big bara där. Varje runner har sin egen cache. Vi har inte testat den här uppsättningen.

15. Vad runnern ansluter till

Mellan jobben frågar runnern bara Forgejo efter arbete, varannan sekund. Vi spelade in serverns uppslag och anslutningar under körningarna i den här guiden:

  • data.forgejo.org, för actions med korta namn och för jobbavbilderna;
  • github.com och code.forgejo.org, för actions med de adresserna;
  • det som jobben själva hämtade: registry.npmjs.org för npm ci, deb.debian.org för Buildah och Docker Hub för raden FROM i Containerfile;
  • Forgejo, på git.example.com, för koden, cachenycklarna, artefakterna och registret.

Runnern laddar ner varje action första gången ett jobb använder den, och sparar den i ~/.cache/act.

16. Säkerhetskopiera

Som runner:

umask 077
mkdir -p ~/backup
tar -czf ~/backup/runner.tar.gz runner-config.yml .config/containers/containers.conf .config/systemd/user

Det är allt runnern behöver: dess inställningar, med token, och dess tjänster. Kopiera ~/backup till en annan maskin och förvara den säkert. Arbetsflöden, loggar, artefakter, hemligheter och variabler finns i Forgejo, och i dess säkerhetskopia.

För att återställa gör du steg 2 och 3 fram till machinectl shell runner@, kopierar säkerhetskopian till ~/backup och kör som runner:

tar -xzf ~/backup/runner.tar.gz
systemctl --user daemon-reload
systemctl --user enable --now forgejo-runner runner-cleanup.timer

Loggen säger declared successfully igen. Har du tappat bort token tar du bort runnern i Forgejo och skapar en ny som i steg 4.

17. Uppdatera

För en ny version av runnern upprepar du steg 2 med dess nummer, och kör sedan som runner:

systemctl --user restart forgejo-runner

Loggen visar den nya versionen. Jobb som körs får upp till tio minuter på sig att bli klara först. Läs versionsinformationen på code.forgejo.org/forgejo/runner/releases före en ny huvudversion, som 14, som kan ändra inställningar. Jobbavbilderna förnyas av den veckovisa städningen i steg 13, Buildah installeras på nytt i varje jobb, och en action som anges som @v6 får alla nya versioner inom version 6. Forgejo uppdaterar du som i Forgejo-guiden.

Felsökning

Ett jobb väntar och startar aldrig. Ingen runner har etiketten på raden runs-on:, eller så är runnern offline. Kontrollera etiketten, och att runnern visas som Idle på /admin/actions/runners. Som runner visar journalctl --user -u forgejo-runner varför den stannade.

Hämtningen av koden misslyckas med Failed to connect to git.example.com port 443. Jobbets container delar serverns adress. Kontrollera ~/.config/containers/containers.conf från steg 3, som runner.

upload-artifact misslyckas med "not currently supported on GHES". Använd forgejo/upload-artifact@v5 i stället för actions/upload-artifact.

Buildah misslyckas med fuse: device not found. --storage-driver vfs saknas i det kommandot.

Pushen misslyckas med authentication required. Token kan inte skriva paket, eller så använde jobbet sin automatiska token. Använd en token som i steg 10, i hemligheten REGISTRY_TOKEN.

Driftsättningen misslyckas med Host key verification failed. DEPLOY_KNOWN_HOSTS stämmer inte med serverns adress i DEPLOY_HOST, eller så har serverns SSH-nyckel ändrats. Skriv ut raden igen som i steg 11.

Runnern stannade efter systemctl --user reload. Starta den med systemctl --user start forgejo-runner, och använd restart när du har ändrat inställningarna.

Kör det på din egen server

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy

100 kr/mån

vCPU
2
Minne
8 GB
Lagring
60 GB
Trafik
10 TB
Performance
SSD · RAID 1
  • Full root-åtkomst
  • Nativt /64 IPv6
  • RAID-skyddad lagring
  • Malmö, Sverige
  • Månadsvis, ingen bindningstid
  • 7 dagars öppet köp
Alla guider