rebreak-monorepo/docs/superpowers/plans/2026-06-18-self-hosted-github-runner.md

438 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Self-Hosted GitHub Actions Runner Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Betreiben eines self-hosted GitHub Actions Runners auf `api.trucko.org` (128.140.47.53) mit dem Label `raynis-builder`, um Backend- und Admin-Builds für das rebreak-monorepo kostenlos auszuführen und weiterhin auf `staging.rebreak.org` zu deployen.
**Architecture:** Code-Hosting bleibt auf GitHub. GitHub Actions Workflows werden auf `runs-on: [self-hosted, raynis-builder]` umgestellt. Der Runner auf `api.trucko.org` checkt aus, baut das Artifact und kopiert es per SCP auf `staging.rebreak.org`. Dort übernimmt das bestehende `deploy-from-artifact.sh` das Entpacken, Migrations-Check und PM2-Restart.
**Tech Stack:** GitHub Actions, self-hosted Runner, Hetzner VPS, pnpm, Node.js 24.11.1, SSH/SCP, PM2.
---
## File Structure
| File / Pfad | Verantwortung | Aktion |
|---|---|---|
| `api.trucko.org` (Server) | Self-hosted Runner + Build-Umgebung | Einrichten |
| `staging.rebreak.org` (Server) | Production/Staging + Deploy-Script | SSH-Key hinzufügen |
| `.github/workflows/deploy-staging.yml` | Backend-Deploy-Workflow | Ändern: `runs-on` + SSH-Secret |
| `.github/workflows/deploy-admin-staging.yml` | Admin-Deploy-Workflow | Ändern: `runs-on` + SSH-Secret |
| GitHub Repo → Settings → Environments → staging | Secrets/Variables | `STAGING_DEPLOY_KEY` hinzufügen |
---
### Task 1: Server `api.trucko.org` vorbereiten
**Files:**
- Ausführen auf: `api.trucko.org` (per SSH)
- [ ] **Step 1: SSH auf Server verbinden**
```bash
ssh root@128.140.47.53
```
- [ ] **Step 2: System aktualisieren und Basis-Tools installieren**
```bash
apt-get update && apt-get install -y curl git build-essential
```
- [ ] **Step 3: Node.js 24.11.1 installieren (via nvm)**
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 24.11.1
nvm use 24.11.1
node -v
```
Expected output: `v24.11.1`
- [ ] **Step 4: pnpm 10.23.0 installieren**
```bash
corepack enable
corepack prepare pnpm@10.23.0 --activate
pnpm -v
```
Expected output: `10.23.0`
- [ ] **Step 5: Git-Config für den Runner setzen**
```bash
git config --global user.name "Raynis Builder"
git config --global user.email "builder@raynis.dev"
```
- [ ] **Step 6: Workspace-Verzeichnis anlegen**
```bash
mkdir -p /srv/raynis-builder
chown root:root /srv/raynis-builder
```
---
### Task 2: GitHub Actions Runner installieren und registrieren
**Files:**
- Ausführen auf: `api.trucko.org`
- Zu prüfen in GitHub: Settings → Actions → Runners
- [ ] **Step 1: Runner-Version ermitteln (aktuellste)**
```bash
RUNNER_VERSION=$(curl -sL https://api.github.com/repos/actions/runner/releases/latest | jq -r '.tag_name' | sed 's/^v//')
echo "$RUNNER_VERSION"
```
- [ ] **Step 2: Runner herunterladen und entpacken**
```bash
cd /srv/raynis-builder
curl -o actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
tar xzf actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
rm actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
```
- [ ] **Step 3: Runner konfigurieren (Token aus GitHub holen)**
In GitHub: Repository `rebreak-monorepo` → Settings → Actions → Runners → New self-hosted runner → Linux → x64.
Dort angezeigte `config.sh`-Befehle auf dem Server ausführen, z. B.:
```bash
cd /srv/raynis-builder
./config.sh --url https://github.com/RaynisDev/rebreak --token <TOKEN_AUS_GITHUB> --name raynis-builder-01 --labels raynis-builder --work _work
```
- [ ] **Step 4: Runner als systemd-Service registrieren**
```bash
cd /srv/raynis-builder
./svc.sh install
./svc.sh start
./svc.sh status
```
Expected: `active (running)`
- [ ] **Step 5: Runner in GitHub UI als Online verifizieren**
In GitHub: Settings → Actions → Runners → Status muss `Idle` oder `Online` zeigen.
---
### Task 3: SSH-Deploy-Key zwischen Servern einrichten
**Files:**
- Ausführen auf: `api.trucko.org` und `staging.rebreak.org`
- [ ] **Step 1: SSH-Key auf `api.trucko.org` erzeugen**
```bash
ssh-keygen -t ed25519 -f /root/.ssh/rebreak-deploy -C "raynis-builder@api.trucko.org" -N ""
cat /root/.ssh/rebreak-deploy.pub
```
- [ ] **Step 2: Public Key auf `staging.rebreak.org` autorisieren**
```bash
ssh root@staging.rebreak.org
mkdir -p /root/.ssh
cat >> /root/.ssh/authorized_keys << 'EOF'
<PUBLIC_KEY_VON_OBEN>
EOF
chmod 600 /root/.ssh/authorized_keys
```
- [ ] **Step 3: Verbindung vom Builder zum Staging testen**
```bash
ssh -i /root/.ssh/rebreak-deploy root@staging.rebreak.org "whoami"
```
Expected output: `root`
- [ ] **Step 4: SSH-Konfiguration für einfacheren Zugriff anlegen**
Auf `api.trucko.org`:
```bash
cat >> /root/.ssh/config << 'EOF'
Host rebreak-staging
HostName staging.rebreak.org
User root
IdentityFile ~/.ssh/rebreak-deploy
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
chmod 600 /root/.ssh/config
```
- [ ] **Step 5: Verbindung mit Alias testen**
```bash
ssh rebreak-staging "whoami"
```
Expected output: `root`
---
### Task 4: GitHub Secrets aktualisieren
**Files:**
- GitHub Repository: Settings → Environments → staging
- [ ] **Step 1: Neuen Private Key als Secret hinzufügen**
Auf `api.trucko.org`:
```bash
cat /root/.ssh/rebreak-deploy
```
Inhalt kopieren und in GitHub einfügen:
- Environment: `staging`
- Secret-Name: `STAGING_DEPLOY_KEY`
- Wert: Inhalt von `/root/.ssh/rebreak-deploy`
- [ ] **Step 2: Bestehende Secrets überprüfen**
In GitHub prüfen, dass folgende Secrets/Vars im Environment `staging` vorhanden sind:
- `HETZNER_SSH_KEY` → kann später entfernt werden, wenn neuer Key funktioniert
- `HETZNER_HOST``staging.rebreak.org`
- `HETZNER_USER``root`
- [ ] **Step 3: Altes Secret nicht löschen (Fallback)**
`HETZNER_SSH_KEY` erst nach erfolgreichem Test-Deploy entfernen.
---
### Task 5: Workflows auf self-hosted Runner umstellen
**Files:**
- Modify: `.github/workflows/deploy-staging.yml`
- Modify: `.github/workflows/deploy-admin-staging.yml`
- [ ] **Step 1: `deploy-staging.yml` anpassen**
Ändere in beiden Jobs `runs-on: ubuntu-latest` zu:
```yaml
runs-on: [self-hosted, raynis-builder]
```
Ändere den SSH-Setup-Step, sodass er `STAGING_DEPLOY_KEY` verwendet:
```yaml
- name: Setup SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
SSH_HOST: ${{ vars.HETZNER_HOST }}
run: |
if [ -z "$SSH_PRIVATE_KEY" ] || [ -z "$SSH_HOST" ]; then
echo "FATAL: STAGING_DEPLOY_KEY oder HETZNER_HOST nicht gesetzt"
exit 1
fi
mkdir -p ~/.ssh
printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H "$SSH_HOST" >> ~/.ssh/known_hosts
```
- [ ] **Step 2: `deploy-admin-staging.yml` analog anpassen**
Gleiche Änderungen wie bei `deploy-staging.yml`:
```yaml
runs-on: [self-hosted, raynis-builder]
```
und SSH-Setup-Step auf `STAGING_DEPLOY_KEY` umstellen.
- [ ] **Step 3: Node-Setup überprüfen**
Da der Runner Node.js 24.11.1 und pnpm 10.23.0 bereits hat, kann der Schritt `actions/setup-node` theoretisch entfallen. Für Robustheit aber beibehalten:
```yaml
- uses: actions/setup-node@v4
with:
node-version: 24.11.1
cache: pnpm
```
**Hinweis:** `cache: pnpm` funktioniert auf self-hosted Runnern nur, wenn der Runner persistent ist. Da der Server nicht bei jedem Job neu aufgesetzt wird, ist das gegeben.
- [ ] **Step 4: Beide Dateien lokal validieren**
```bash
cd /Users/chahinebrini/mono/rebreak-monorepo
git diff .github/workflows/deploy-staging.yml .github/workflows/deploy-admin-staging.yml
```
- [ ] **Step 5: Änderungen commiten**
```bash
git add .github/workflows/deploy-staging.yml .github/workflows/deploy-admin-staging.yml
git commit -m "ci: use self-hosted runner raynis-builder on api.trucko.org"
```
---
### Task 6: Test-Deploy durchführen
**Files:**
- GitHub Actions UI
- Server-Logs auf `api.trucko.org` und `staging.rebreak.org`
- [ ] **Step 1: Workflow manuell triggern**
In GitHub: Actions → Deploy Staging → Run workflow → Branch: main → Run.
- [ ] **Step 2: Build-Logs auf Runner verfolgen**
Auf `api.trucko.org`:
```bash
tail -f /srv/raynis-builder/_diag/Worker_*.log
tail -f /srv/raynis-builder/_diag/SelfUpdate-*.log
```
- [ ] **Step 3: Deploy-Logs auf Staging verfolgen**
Auf `staging.rebreak.org`:
```bash
pm2 logs rebreak-staging --lines 50
```
- [ ] **Step 4: Health-Check manuell ausführen**
Lokal oder auf `api.trucko.org`:
```bash
for i in $(seq 1 12); do
STATUS=$(curl -sS -o /dev/null -w '%{http_code}' https://staging.rebreak.org/api/auth/me 2>/dev/null || echo "000")
echo "Attempt $i: $STATUS"
[ "$STATUS" = "401" ] || [ "$STATUS" = "200" ] && echo "PASSED" && break
sleep 5
done
```
Expected: `PASSED`
- [ ] **Step 5: Admin-Deploy testen**
In GitHub: Actions → Deploy Admin Staging → Run workflow.
Health-Check:
```bash
curl -sS -o /dev/null -w '%{http_code}' https://admin.staging.rebreak.org/
```
Expected: Nicht `000`, `502` oder `503`.
---
### Task 7: Alten Webhook-Deploy abschalten (optional, nach stabilem Betrieb)
**Files:**
- Ausführen auf: `staging.rebreak.org`
- GitHub Repo: Settings → Webhooks
- [ ] **Step 1: Mindestens 35 erfolgreiche Deploys über neuen Runner abwarten**
- [ ] **Step 2: GitHub-Webhook deaktivieren**
In GitHub: Settings → Webhooks → `https://staging.rebreak.org/webhook` → Active: aus.
- [ ] **Step 3: Webhook-Service auf Server stoppen**
```bash
ssh root@staging.rebreak.org
pm2 stop rebreak-webhook
pm2 save
```
- [ ] **Step 4: Legacy-Dateien archivieren (nicht löschen)**
```bash
cd /srv/rebreak
mkdir -p scripts/legacy
mv scripts/deploy.sh scripts/legacy/deploy.sh
mv scripts/deploy-webhook scripts/legacy/deploy-webhook
```
- [ ] **Step 5: `ecosystem.config.js` bereinigen**
Entferne den Block für `rebreak-webhook` aus `ecosystem.config.js` und deploye die Änderung.
---
### Task 8: Cleanup und Monitoring
- [ ] **Step 1: Altes `HETZNER_SSH_KEY` Secret aus GitHub entfernen**
Nur nachdem `STAGING_DEPLOY_KEY` erfolgreich getestet wurde.
- [ ] **Step 2: Runner-Verfügbarkeit überwachen**
In GitHub: Settings → Actions → Runners → Status regelmäßig prüfen.
- [ ] **Step 3: Log-Rotation auf Runner einrichten**
```bash
logrotate --version || apt-get install -y logrotate
cat > /etc/logrotate.d/github-runner << 'EOF'
/srv/raynis-builder/_diag/*.log {
daily
rotate 7
compress
missingok
notifempty
}
EOF
```
- [ ] **Step 4: pnpm-Store auf Runner bereinigen (monatlich)**
```bash
pnpm store prune
```
---
## Self-Review
### Spec coverage
- Self-hosted Runner auf `api.trucko.org`: Task 1 + 2
- Label `raynis-builder`: Task 2
- Code-Hosting bleibt auf GitHub: implizit durch GitHub Actions
- Workflows auf `runs-on: [self-hosted, raynis-builder]`: Task 5
- Deploy zu `staging.rebreak.org`: Task 3 + 4 + 6
- Sicherheit (kein PR-Trigger): Task 5 (Workflow-Trigger bleibt `push: branches: [main]`)
- Webhook abschalten: Task 7
### Placeholder scan
Keine TBD/TODO. Alle Befehle sind konkret.
### Konsistenz
- Label durchgehend `raynis-builder`
- Secret-Name durchgehend `STAGING_DEPLOY_KEY`
- Node-Version durchgehend `24.11.1`
- pnpm-Version durchgehend `10.23.0`
- Server-IP durchgehend `128.140.47.53`