From b65491afc8a1c6a6a41eb880c63a6decc24628ac Mon Sep 17 00:00:00 2001 From: Erol Haagenrud Date: Mon, 10 Aug 2026 22:41:48 +0200 Subject: [PATCH] Selvhostet Forgejo Actions-runner for backend-testene MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empirisk push viste at repoet ikke hadde noen aktiv runner (jobb ble stående som "Waiting"). Satt opp act_runner lokalt på serveren (Docker-utenfor-Docker, docker.sock automount) siden run_backend_tests.sh er avhengig av teeoff_db/teeoff_default som kun finnes her. Kjører nå som egen tjeneste i docker-compose.yml. Se ADR-059 og CHANGELOG punkt 68. Co-Authored-By: Claude Sonnet 5 --- .gitignore | 1 + ARCHITECTURE_DECISIONS.md | 84 +++++++++++++++++++++++++++++++++++---- CHANGELOG.md | 52 +++++++++++++++++++++--- docker-compose.yml | 26 ++++++++++++ 4 files changed, 150 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 6fe5ff1..f0af2ce 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__/ Temp-uploads/ .venv/ .pytest_cache/ +.forgejo-runner/ diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md index 9766cfe..6879420 100644 --- a/ARCHITECTURE_DECISIONS.md +++ b/ARCHITECTURE_DECISIONS.md @@ -5616,13 +5616,83 @@ grønne. Ekte `teecup_db` sitt rolleoppsett (`teecup_app`: uendret etter kjøring. Ingen deploy denne runden — dette er ren testinfrastruktur, ingen produksjonskode endret. -**Bevisst utenfor omfang, egne fremtidige runder:** CI-workflow-fil -(venter på bekreftet runner), frontend-tester, og dekning av flere -router-funksjoner enn de tre høyest-risiko-områdene over (f.eks. -øvrige `rounds.py`-endepunkter, `individual_tournaments.py`, -org-turnering-match-scoring sin `scoring.py` — sistnevnte spesielt -interessant siden ADR-057 dokumenterte AT den mangler samtidighetsvern, -men det er foreløpig udekket av en test som beviser det empirisk). +**Bevisst utenfor omfang, egne fremtidige runder:** frontend-tester, og +dekning av flere router-funksjoner enn de tre høyest-risiko-områdene +over (f.eks. øvrige `rounds.py`-endepunkter, +`individual_tournaments.py`, org-turnering-match-scoring sin +`scoring.py` — sistnevnte spesielt interessant siden ADR-057 +dokumenterte AT den mangler samtidighetsvern, men det er foreløpig +udekket av en test som beviser det empirisk). CI-workflow-filen ble +løst SAMME dag — se ADR-059. + +--- + +## ADR-059: Selvhostet Forgejo Actions-runner — 2026-08-10 + +Direkte oppfølging av ADR-058: `.forgejo/workflows/backend-tests.yml` +ble lagt til og pushet som en EMPIRISK test av om +forgejo.jegvil.no faktisk hadde en aktiv runner for dette repoet +(instansen svarte `has_actions: true` på et anonymt API-kall, men det +beviste ikke at noe faktisk plukker opp jobber). Resultat: jobben la +seg i kø som "Waiting" og ble stående uendret i over et minutt — ingen +runner fantes. Bruker ba om at det rettes. + +**Beslutning A — selvhostet `act_runner` PÅ DENNE serveren, ikke en +ekstern/skyhostet runner.** `run_backend_tests.sh` er avhengig av +`docker exec teeoff_db` og `teeoff_default`-nettverket, som kun +eksisterer på denne verten. En runner et annet sted ville uansett +ikke kunnet kjøre testene slik de er skrevet i dag. + +**Beslutning B — Docker-utenfor-Docker (DooD) via +`docker_host: automount` i runner-konfigen, ikke Docker-i-Docker.** +Jobb-containeren får HOST-ens `docker.sock` bind-montert inn (samme +mønster som runneren selv bruker for å starte jobb-containere i +utgangspunktet), slik at `scripts/run_backend_tests.sh` sine egne +`docker build`/`docker run`/`docker exec`-kall oppretter ekte +søsken-containere på host-nivå — ikke en nøstet, isolert +docker-daemon som ikke ville sett `teeoff_db` i det hele tatt. +Jobb-image: `catthehacker/ubuntu:act-latest` (de facto standardimage +for act/act_runner — har docker-CLI, git, bash forhåndsinstallert, +unngår `apt-get install` i hvert eneste kjør). + +**Beslutning C — registrerings-tokenet ble ALDRI limt inn i chatten.** +Bruker hentet det selv fra Forgejo sitt UI (repo → Settings → Actions +→ Runners) og la det i en midlertidig fil med `chmod 600` på serveren; +Claude leste filen direkte via shell, registrerte runneren +(`forgejo-runner register --no-interactive`), og makulerte +tokenfilen umiddelbart etterpå (`shred -u`). Selve +runner-legitimasjonen som oppsto (`.forgejo-runner/.runner` — en ekte, +langlevd hemmelighet, ikke det korte engangs-registreringstokenet) er +gitignored, `chmod 600`, aldri committet — samme disiplin som +`.env`. + +**Beslutning D — kjøres via `docker-compose.yml`, ikke en løs +`docker run`.** Startet først manuelt for å bevise at det fungerte +(ekte push → "Waiting" → runner registrert → jobb plukket opp → +"Success", verifisert i Forgejo sitt UI), deretter flyttet inn som en +egen `teecup-forgejo-runner`-tjeneste i `docker-compose.yml` for +samme drift-disiplin som resten av stacken (`restart: unless-stopped`, +dokumentert, ikke en engangs-kommando ingen husker senere). +`group_add: "112"` (docker-gruppens GID på DENNE verten) er +nødvendig fordi runner-imagets prosess kjører som ikke-root — uten +den kan den ikke lese den mountede sokkelen selv om den er tilgjengelig. +Vertsspesifikk verdi, sjekk på nytt om dette noensinne flyttes. + +**Sikkerhetsnotat, bevisst akseptert:** tilgang til `docker.sock` +tilsvarer root-ekvivalent kontroll over VERTEN (enhver som kan +opprette en container kan mounte hva som helst fra filsystemet). +Dette er en reell heving av angrepsflaten sammenlignet med resten av +stacken, som ingen andre containere her har. Akseptert fordi (a) det +er en direkte konsekvens av arkitekturen `run_backend_tests.sh` allerede +hadde (samme prinsipp, bare automatisert fremfor kjørt manuelt fra en +already-priviligert shell), og (b) runneren kjører KUN denne ene +repoens CI, på en enkeltpersons egen server — ikke en delt/flerbruker- +instans. + +**Verifisert:** ekte push → `.forgejo/workflows/backend-tests.yml` +kjørte, viste "Success" i Forgejo sitt UI (grønn hake, samme run som +sto "Waiting" rett før runneren startet). `teecup_db`s rolleoppsett og +fravær av gjenglemte scratch-databaser bekreftet uendret etter kjøring. Disse må avklares før eller under de relevante fasene: diff --git a/CHANGELOG.md b/CHANGELOG.md index ca72e65..2868e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10278,9 +10278,49 @@ Neste steg: grønne. Ingen produksjonskode endret denne runden — ren testinfrastruktur, ingen deploy. - **Bevisst utenfor omfang:** CI-workflow-fil (Forgejo Actions har - `has_actions: true` for repoet, men ingen bekreftet aktiv runner — - egen runde), frontend-tester, og dekning av org-turneringenes - match-scoring (`scoring.py`) — som ADR-057 allerede har dokumentert - mangler samtidighetsvern, men som fortsatt ikke har en test som - beviser det empirisk. + **Bevisst utenfor omfang:** frontend-tester, og dekning av + org-turneringenes match-scoring (`scoring.py`) — som ADR-057 + allerede har dokumentert mangler samtidighetsvern, men som + fortsatt ikke har en test som beviser det empirisk. + CI-workflow-filen ble løst SAMME dag, se punkt 68. + +68. **Selvhostet Forgejo Actions-runner — 2026-08-10, se ADR-059.** + Direkte oppfølging av punkt 67: en `.forgejo/workflows/ + backend-tests.yml` ble lagt til og pushet som en empirisk test — + Forgejo-instansen svarte `has_actions: true`, men det beviste ikke + at noe faktisk plukket opp jobber. Jobben la seg som "Waiting" og + sto uendret i over et minutt. Ingen runner fantes. Bruker ba om + at det rettes ("start med ci"). + + Satt opp en selvhostet `act_runner` PÅ DENNE serveren (må være her + — `run_backend_tests.sh` er avhengig av `docker exec teeoff_db` og + `teeoff_default`-nettverket, som kun finnes lokalt). Docker- + utenfor-Docker (`docker_host: automount`): jobb-containeren får + host-ens `docker.sock` bind-montert inn, slik at testskriptets + egne `docker build`/`run`/`exec`-kall lager ekte søsken-containere + på host-nivå. Jobb-image `catthehacker/ubuntu:act-latest` (docker- + CLI/git/bash forhåndsinstallert). + + Registrerings-tokenet ble ALDRI limt inn i chatten — bruker hentet + det selv fra Forgejo sitt UI, la det i en `chmod 600`-fil på + serveren, Claude leste filen direkte og makulerte den (`shred -u`) + rett etter registrering. Den ekte, langlevde runner-legitimasjonen + som oppsto (`.forgejo-runner/.runner`) er gitignored og `chmod 600` + — samme disiplin som `.env`. + + Startet først manuelt for å bevise at det virket, deretter flyttet + inn som en egen `teecup-forgejo-runner`-tjeneste i + `docker-compose.yml` (`restart: unless-stopped`) for samme + driftsdisiplin som resten av stacken. + + **Sikkerhetsnotat, bevisst akseptert:** `docker.sock`-tilgang er + root-ekvivalent kontroll over verten — en reell heving av + angrepsflaten. Akseptert fordi det er samme prinsipp + `run_backend_tests.sh` allerede krevde (nå automatisert fremfor + kjørt fra en allerede-priviligert shell), og runneren betjener kun + denne ene repoens CI på en enkeltpersons egen server. + + **Verifisert:** ekte push → workflowen kjørte → "Success" i + Forgejo sitt UI (grønn hake, samme kø-oppføring som nettopp sto + "Waiting"). `teecup_db`s rolleoppsett og fravær av gjenglemte + scratch-databaser bekreftet uendret etter kjøring. diff --git a/docker-compose.yml b/docker-compose.yml index da78d47..4bf6e00 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,6 +57,32 @@ services: depends_on: - teecup_api + # Selvhostet Forgejo Actions-runner (ADR-059, 2026-08-10) -- kjører + # backend-testsuiten (.forgejo/workflows/backend-tests.yml) automatisk + # ved push. Docker-utenfor-Docker (docker_host: automount i + # .forgejo-runner/config.yaml): jobb-containeren får docker.sock + # bind-mountet inn, slik at scripts/run_backend_tests.sh kan opprette + # SINE EGNE scratch-db-/testcontainere via HOST-ens docker-daemon -- + # ikke en nøstet docker-daemon inni runneren. `.runner`-fila i + # .forgejo-runner/ er en ekte, langlevd registreringshemmelighet + # (gitignored, ALDRI committet). + # + # group_add: 112 er docker-gruppens GID på DENNE verten (`stat -c %g + # /var/run/docker.sock`) -- uten den kan ikke runner-prosessen (som + # kjører som en ikke-root-bruker i imaget) lese sokkelen, selv når den + # er mountet inn. Sjekk/juster GID-en om dette flyttes til en annen vert. + teecup-forgejo-runner: + image: code.forgejo.org/forgejo/runner:6 + container_name: teecup-forgejo-runner + command: forgejo-runner daemon --config config.yaml + working_dir: /data + group_add: + - "112" + volumes: + - ./.forgejo-runner:/data + - /var/run/docker.sock:/var/run/docker.sock + restart: unless-stopped + volumes: teecup_minio_data: