243 lines
9.2 KiB
Markdown
243 lines
9.2 KiB
Markdown
# Self-Hosted GitHub Actions Runner für rebreak-monorepo
|
|
|
|
**Datum:** 2026-06-18
|
|
**Status:** Genehmigt — bereit für Implementierungsplanung
|
|
**Autor:** Kimi Code (Brainstorming-Session)
|
|
**Ziel:** GitHub-Actions-Buildkosten eliminieren, indem Backend- und Admin-Builds auf den bereits vorhandenen Hetzner-Server `api.trucko.org` (128.140.47.53) verlagert werden.
|
|
|
|
---
|
|
|
|
## 1. Zusammenfassung
|
|
|
|
Derzeit laufen Backend- und Admin-Builds auf kostenpflichtigen GitHub-gehosteten Runnern (`ubuntu-latest`). Bei einem privaten Repository führt das bei hoher Push-Frequenz zu Kosten von über 200 €/Monat.
|
|
|
|
Dieses Design schlägt vor, einen **self-hosted GitHub Actions Runner** auf dem bereits vorhandenen, aktuell ungenutzten Hetzner-Server `api.trucko.org` (128.140.47.53, 8 GB RAM) zu betreiben. Der Code-Hosting-Aspekt bleibt vollständig auf GitHub; nur die Build- und Deploy-Ausführung wird auf die eigene Infrastruktur verlagert.
|
|
|
|
Das Runner-Label `raynis-builder` ist bewusst generisch gewählt, damit später weitere Raynis-Apps (Mutterfirma von ReBreak) denselben Runner nutzen können.
|
|
|
|
---
|
|
|
|
## 2. Kontext & Ausgangslage
|
|
|
|
### Aktueller Flow
|
|
|
|
```
|
|
local dev → push to main
|
|
↓
|
|
GitHub Actions (ubuntu-latest)
|
|
↓
|
|
Build Backend / Admin
|
|
↓
|
|
Upload Artifact
|
|
↓
|
|
Deploy-Job (ubuntu-latest)
|
|
↓
|
|
SCP + SSH zu staging.rebreak.org
|
|
↓
|
|
deploy-from-artifact.sh
|
|
```
|
|
|
|
### Bestehende Komponenten (werden wiederverwendet)
|
|
|
|
- `.github/workflows/deploy-staging.yml`
|
|
- `.github/workflows/deploy-admin-staging.yml`
|
|
- `scripts/deploy-from-artifact.sh`
|
|
- `scripts/deploy-admin-from-artifact.sh`
|
|
- `ecosystem.config.js` auf `staging.rebreak.org`
|
|
|
|
### Probleme mit dem aktuellen Setup
|
|
|
|
- GitHub Actions Minuten kosten bei privatem Repo über 200 €/Monat.
|
|
- Keine Notwendigkeit für die ursprüngliche Entscheidung, Builds auf GitHub laufen zu lassen (Server-OOM auf CX23) — `api.trucko.org` hat 8 GB RAM.
|
|
|
|
---
|
|
|
|
## 3. Ziele
|
|
|
|
1. **Kosten eliminieren:** Keine kostenpflichtigen GitHub Actions Minuten mehr für Backend-/Admin-Builds.
|
|
2. **Minimaler Änderungsaufwand:** Bestehende Workflows und Deploy-Scripts bleiben weitgehend erhalten.
|
|
3. **Sicherheit:** Self-hosted Runner wird nicht für Pull Requests von Forks genutzt.
|
|
4. **Zuverlässigkeit:** Concurrency-Group, Health-Check und atomic deploy bleiben erhalten.
|
|
|
|
## 4. Nicht-Ziele
|
|
|
|
- Kein Wechsel des Code-Hostings (GitHub bleibt).
|
|
- Kein Ersatz für Windows- oder iOS-Builds (diese bleiben bei GitHub Actions oder werden lokal gebaut).
|
|
- Keine Einführung zusätzlicher CI-Tools wie Gitea, GitLab oder Woodpecker.
|
|
- Keine Änderung an der Production-Infrastruktur auf `staging.rebreak.org` über das Nötige hinaus.
|
|
|
|
---
|
|
|
|
## 5. Architektur
|
|
|
|
```
|
|
GitHub Push (main)
|
|
↓
|
|
GitHub Actions Workflow
|
|
↓
|
|
Self-hosted Runner auf api.trucko.org
|
|
↓
|
|
Checkout → pnpm install → pnpm build → tar artifact
|
|
↓
|
|
SCP artifact zu staging.rebreak.org
|
|
↓
|
|
SSH: bash /srv/rebreak/scripts/deploy-from-artifact.sh
|
|
↓
|
|
Atomic swap .output-staging + pm2 restart + health-check
|
|
```
|
|
|
|
### Komponenten
|
|
|
|
| Komponente | Ort | Verantwortung |
|
|
|---|---|---|
|
|
| GitHub Repository | GitHub Cloud | Code-Hosting, Workflow-Definitionen |
|
|
| GitHub Actions Runner | `api.trucko.org` | Workflow-Ausführung, Build, Deploy-Trigger |
|
|
| Build-Umgebung | `api.trucko.org` | `pnpm install`, `pnpm build`, Artifact-Erstellung |
|
|
| Production-Server | `staging.rebreak.org` | Artifact entpacken, Migrationen, PM2-Restart |
|
|
| Deploy-Script | `staging.rebreak.org` | `scripts/deploy-from-artifact.sh` / `deploy-admin-from-artifact.sh` |
|
|
|
|
---
|
|
|
|
## 6. Datenfluss (detailliert)
|
|
|
|
### 6.1 Backend-Deploy
|
|
|
|
1. Push auf `main` triggert `.github/workflows/deploy-staging.yml`.
|
|
2. Workflow-Job `build` läuft auf `runs-on: self-hosted` (Runner auf `api.trucko.org`).
|
|
3. Runner checkt Repo mit `actions/checkout@v4` aus.
|
|
4. `pnpm install --frozen-lockfile` wird ausgeführt.
|
|
5. `cd backend && pnpm build` erzeugt `backend/.output`.
|
|
6. Artifact wird gepackt: `tar czf backend-output.tar.gz -C backend/.output .`.
|
|
7. Artifact wird per SCP auf `staging.rebreak.org:/srv/rebreak/backend/.output-incoming.tar.gz` kopiert.
|
|
8. `imap-idle/` wird per SCP synchronisiert.
|
|
9. Runner führt per SSH `bash /srv/rebreak/scripts/deploy-from-artifact.sh` aus.
|
|
10. Server entpackt Artifact atomisch, führt ggf. Prisma-Migrationen aus und restartet `rebreak-staging`.
|
|
11. Health-Check gegen `https://staging.rebreak.org/api/auth/me` prüft Erreichbarkeit.
|
|
|
|
### 6.2 Admin-Deploy
|
|
|
|
- Analog zu Backend über `.github/workflows/deploy-admin-staging.yml`.
|
|
- Ziel: `staging.rebreak.org:/srv/rebreak/apps/admin/.output-incoming.tar.gz`.
|
|
- Script: `scripts/deploy-admin-from-artifact.sh`.
|
|
- Health-Check: `https://admin.staging.rebreak.org/`.
|
|
|
|
---
|
|
|
|
## 7. Sicherheit
|
|
|
|
### Runner-Isolation
|
|
|
|
- Der Runner wird als **Repository-Level Runner** im `rebreak-monorepo` registriert, damit nur dieses Repo ihn nutzen kann.
|
|
- Der Runner bekommt ein dediziertes Label: `raynis-builder`.
|
|
- Der Workflow fordert das Label explizit an: `runs-on: [self-hosted, raynis-builder]`.
|
|
- Der Runner reagiert **nicht** auf Pull-Request-Events — nur auf `push` zu `main` und `workflow_dispatch`.
|
|
|
|
### SSH-Zugriff
|
|
|
|
- Ein neuer SSH-Deploy-Key wird auf `api.trucko.org` erzeugt.
|
|
- Der Public Key wird auf `staging.rebreak.org` in `/root/.ssh/authorized_keys` eingetragen.
|
|
- Der Private Key wird als GitHub Secret (z. B. `STAGING_DEPLOY_KEY`) im Environment `staging` hinterlegt.
|
|
|
|
### Secrets
|
|
|
|
- Keine Secrets im Runner-Image.
|
|
- Alle sensiblen Daten kommen weiterhin aus GitHub Environments oder Infisical (auf `staging.rebreak.org`).
|
|
|
|
---
|
|
|
|
## 8. Fehlerbehandlung
|
|
|
|
### Build-Fehler
|
|
|
|
- Wenn `pnpm build` fehlschlägt, bricht der Workflow ab.
|
|
- Es wird nichts auf `staging.rebreak.org` kopiert.
|
|
|
|
### Deploy-Fehler
|
|
|
|
- `deploy-from-artifact.sh` bricht bei fehlgeschlagenen Prisma-Migrationen ab.
|
|
- Der alte `.output-staging`-Ordner bleibt durch atomisches `mv` erhalten.
|
|
- Health-Check muss bestehen, sonst schlägt der Workflow fehl.
|
|
|
|
### Parallelität
|
|
|
|
- Concurrency-Group bleibt erhalten:
|
|
```yaml
|
|
concurrency:
|
|
group: deploy-staging
|
|
cancel-in-progress: false
|
|
```
|
|
- Parallele Deploys queueen sich, statt sich gegenseitig abzubrechen.
|
|
|
|
---
|
|
|
|
## 9. Tests in CI
|
|
|
|
Aktuell laufen keine automatisierten Tests in den Deploy-Workflows. Mit dem eigenen Runner entstehen hierfür keine zusätzlichen Kosten.
|
|
|
|
**Empfohlener optionaler nächster Schritt:**
|
|
- Vitest-Unit-Tests vor dem Build-Schritt ausführen.
|
|
- Reihenfolge: `install → lint → test → build → deploy`.
|
|
|
|
Dies ist **nicht Teil dieses Designs** und wird in einem separaten Plan behandelt.
|
|
|
|
---
|
|
|
|
## 10. Migrationsschritte
|
|
|
|
1. **Runner auf `api.trucko.org` installieren**
|
|
- Node.js 24.11.1, pnpm 10.23.0, git einrichten.
|
|
- GitHub Actions Runner herunterladen und konfigurieren.
|
|
- Als Service registrieren (`./svc.sh install && ./svc.sh start`).
|
|
- Label `raynis-builder` zuweisen.
|
|
|
|
2. **SSH-Verbindung einrichten**
|
|
- Auf `api.trucko.org`: `ssh-keygen -t ed25519 -f ~/.ssh/rebreak-deploy`.
|
|
- Public Key auf `staging.rebreak.org` in `/root/.ssh/authorized_keys` eintragen.
|
|
- Private Key als GitHub Secret `STAGING_DEPLOY_KEY` im Environment `staging` hinterlegen.
|
|
|
|
3. **Workflows anpassen**
|
|
- `runs-on: ubuntu-latest` → `runs-on: [self-hosted, raynis-builder]`.
|
|
- SSH-Setup-Step an neues Secret `STAGING_DEPLOY_KEY` anpassen.
|
|
- Node-Setup beibehalten (Version 24.11.1).
|
|
|
|
4. **Test-Deploy durchführen**
|
|
- `workflow_dispatch` auf `main` auslösen.
|
|
- Logs auf `api.trucko.org` und `staging.rebreak.org` prüfen.
|
|
- Health-Check bestätigen.
|
|
|
|
5. **Alte Pfade abschalten**
|
|
- Nach erfolgreichen Test-Deploys können die alten Webhook-basierten Deploys deaktiviert werden.
|
|
- `pm2 stop rebreak-webhook && pm2 save` auf `staging.rebreak.org` (nur auf User-Approval).
|
|
|
|
---
|
|
|
|
## 11. Risiken & Mitigationen
|
|
|
|
| Risiko | Wahrscheinlichkeit | Auswirkung | Mitigation |
|
|
|---|---|---|---|
|
|
| Runner-Prozess stürzt ab | Niedrig | Hoch | Runner als systemd-Service laufen lassen; GitHub zeigt Runner offline an. |
|
|
| Build auf `api.trucko.org` zu langsam | Mittel | Mittel | 8 GB RAM + 8 GB Swap einrichten; SSD statt HDD prüfen. |
|
|
| SSH-Verbindung zwischen Servern failt | Niedrig | Hoch | SSH-Key testen; `ssh-keyscan` im Workflow nutzen. |
|
|
| Runner wird versehentlich für PRs genutzt | Niedrig | Hoch | Trigger auf `push: branches: [main]` beschränken; kein `pull_request`. |
|
|
| Windows-/Native-Builds bleiben kostenpflichtig | Sicher | Niedrig | In separatem Schritt evaluieren (nicht Teil dieses Designs). |
|
|
|
|
---
|
|
|
|
## 12. Offene Punkte
|
|
|
|
1. Exakte Spezifikation von `api.trucko.org` bestätigen (CPU, SSD, OS).
|
|
2. Soll der Runner unter einem dedizierten User laufen oder als `root`?
|
|
3. Sollen bestehende Webhook-Deploys sofort abgeschaltet oder parallel als Fallback laufen?
|
|
4. Sollen Vitest-Tests vor dem Build integriert werden (separater Plan)?
|
|
|
|
---
|
|
|
|
## 13. Erwartetes Ergebnis
|
|
|
|
Nach der Umstellung:
|
|
|
|
- Backend- und Admin-Builds laufen auf `api.trucko.org`.
|
|
- GitHub-Actions-Minutenkosten für diese Workflows fallen nahezu auf null.
|
|
- Die Deploy-Mechanik auf `staging.rebreak.org` bleibt unverändert.
|
|
- Windows-/Native-Builds bleiben bei GitHub Actions oder werden separat betrachtet.
|