teqo/docs/plans/ops71-runner-self-hosted-github-homeserver-impl.md

7.6 KiB

Impl: Runner self-hosted do GitHub no homeserver (deploy do dispatch manual) + CURSOR_API_KEY

Status: aguardando aprovação Atualizado em: 2026-08-19 Issue: #113 Intenção: o body da Issue #113 (OPS71-INFRA) é a spec — sem plano de intenção separado Appetite: horas de operação (não é Issue de código — nada de schema/UI/access)

Leitura da intenção

  • Outcome: o job deploy do .github/workflows/deploy.yml (dispatch manual) roda no runner self-hosted do GitHub instalado no homeserver (labels self-hosted + homeserver), executando scripts/deploy-homeserver.sh <sha> localmente (sem SSH). O hosted (verify) nunca toca o homeserver.
  • O que NÃO negociar: runner só no deploy.yml (nunca no ci-pr.yml); usuário com docker group + leitura de ~/stack/; outbound-only (funciona atrás do Cloudflare tunnel); registro do runner em infra-solla STATE.md.
  • Já validado na sessão (pre-flight):
    • SSH ao homeserver OK (LAN 192.168.15.142, user fsolla).
    • fsolla tem docker no groups + sudo; lê ~/stack/teqo-1313.env e ~/stack/.env (modo 600, dono = fsolla). Arch x86_64 → tarball linux-x64.
    • Runner ainda NÃO existe no homeserver (sem ~/actions-runner, sem unit systemd do runner; o runner-watch.* é outra coisa — WoL/shutdown da workstation).
    • PAT do OPS71 funciona (local, ~/.bashrc): GET /repos/fsolla/teqo 200 e POST …/actions/runners/registration-token 201 → admin no repo OK.
    • Versão estável atual do runner: v2.336.0 linux-x64, 226 MB, sha256 04cf0be1aff4c3ec3554466c39124ca250e3effd8873bb7e8d68535aa9505d5d (digest da API de releases do GitHub).
    • Linger do homeserver já ativo (loginctl show-user fsolla → Linger=yes) → systemd user funciona sem sudo (o runner-watch já é user service persistente lá — prova do padrão).
    • Workspace ~/teqo-deploy existe mas ainda aponta origin → Forgejo (http://localhost:3000/…): o set-url idempotente do deploy-homeserver.sh re-aponta para TEQO_REPO_URL (GitHub) no primeiro deploy — nada a fazer, mas é o que o log do primeiro deploy deve mostrar.

Abordagem recomendada

Sequência operacional no homeserver (nenhum commit no repo teqo — o código do OPS71 já foi mergeado; o único artefato commitado desta Issue é o registro no STATE.md do infra-solla, repo separado):

  1. Download (homeserver, ~/actions-runner): tarball v2.336.0 linux-x64 da release oficial, sha256 conferido contra o digest da API de releases.
  2. Registration token (workstation, PAT local): POST /repos/fsolla/teqo/actions/runners/registration-token (TTL 1 h — gerar e configar na sequência, um único passo encadeado).
  3. config.sh (homeserver, user fsolla): ./config.sh --url https://github.com/fsolla/teqo --token <token> --labels self-hosted,homeserver --name teqo-1313-runner --work _work.
  4. svc.sh como systemd USER (./svc.sh install sem root → unit ~/.config/systemd/user/actions.runner.fsolla-teqo-1313-runner.service) + systemctl --user enable --now … (start). Linger já ativo → persiste sem login; roda como fsolla (docker + ~/stack envs).
  5. Verificação do runner: systemctl --user status … ativo; runner listado em GET /repos/fsolla/teqo/actions/runners como online.
  6. Registro em infra-solla (~/Code/infra-solla/STATE.md): entrada na seção do Teqo + nota na tabela de topologia (runner GitHub no homeserver, labels, dir, systemd user) — e no runbook docs/ops/teqo-1313-deploy.md do teqo (a tabela "Onde roda cada coisa" já o menciona prospectivamente; só confirmar o texto com o estado real). Changelog docs/changelog/2026-08-20-ops71-infra.md + pnpm changelog:build.
  7. Aceite (verificação ao vivo): dispatch manual do deploy.yml (ref main) → verify full verde → job deploy roda no runner do homeserver → log com o set-url do workspace (Forgejo → GitHub) + smoke ok → segundo dispatch do mesmo SHA → guard "already deployed".

Decisões:

  • systemd user + linger (já ativo) vs. svc.sh install via root: user — sem senha sudo interativa, mesmo padrão do runner-watch (persistência provada no próprio homeserver); o unit system-level não adicionaria nada (o unit user roda com User=fsolla de qualquer forma).
  • ~/actions-runner + workdir _work: convenção oficial; ~/teqo-deploy permanece como workspace do deploy (o script seta TEQO_REPO_URL nele).
  • Sem mudanças em código/workflows: runs-on: [self-hosted, homeserver] já está no deploy.yml; o deploy-homeserver.sh já tem o set-url idempotente. O runner vem do GitHub com o token de registro — sem secrets novos no repo (o repo é público; as envs de produção ficam no homeserver).

Rejeitadas:

  • svc.sh install como root — exigiria sudo interativo; nada ganho sobre o unit user (mesmo usuário efetivo, linger já garante auto-start no boot).
  • Rodar o runner em container/docker — complexidade extra; o padrão oficial do GitHub é o binário com svc; o runner-watch local prova o user service.
  • Instalar agora o helper archive-cursor-agent / criar o secret CURSOR_API_KEY no GitHub — item secundário da Issue, dormente (pool morto, OPS65): a key não existe no ambiente; fica registrado como pendência no fechamento (pedir a key ao humano quando quiser reativar o helper), sem ação agora.

Fases verificáveis

  1. Runner baixado + sha256 conferido.
  2. Runner configurado (.runner + .credentials no ~/actions-runner), labels corretas, nome teqo-1313-runner.
  3. Unit systemd user ativo e persistente (systemctl --user is-enabled …), runner online na API do GitHub.
  4. STATE.md (infra-solla) + runbook + changelog registrados.
  5. Dispatch manual de validação (verify → deploy → already-deployed no segundo dispatch) — aceite final, exige o humano (dispara no GitHub UI).

Rabbit holes / Não escopo (engenharia)

  • Não re-engenharia do deploy-homeserver.sh (fluxo compose/migrate intacto).
  • Não mexer no stack/registry/env do homeserver.
  • Não criar secret CURSOR_API_KEY (dormente — só com a key do usuário).
  • Não editar o ci-pr.yml nem a branch protection.

Riscos e mitigação

  • Token de registro expira em 1 h → o config.sh roda na mesma sequência do POST (script encadeado da workstation → homeserver).
  • svc.sh install gerar unit system em vez de user (se detectar root): rodar sem sudo garante o user unit; se algo criar system unit, desfazer com svc.sh uninstall e repetir como user.
  • Runner offline no dispatch → falha conhecida já documentada no runbook ("job deploy nunca roda / runner offline"): checar systemctl --user status, o runner-watch local não cuida deste runner (não é o forgejo-runner).
  • verify full ~50 min hosted antes do deploy → aceite da Issue é um ciclo completo; nada do homeserver é tocado até verify verde.
  • Rollback: ~/actions-runner/./svc.sh uninstall + rm -rf ~/actions-runner (desregistra no GitHub); o deploy volta a ficar indisponível até o runner ser religado — comportamento conhecido, documentado no runbook.

Aceite de engenharia

  • Aceite de produto da intenção coberto (deploy self-hosted no homeserver, verify hosted nunca toca o homeserver)
  • Runner instalado como fsolla (docker + ~/stack), systemd user com linger, outbound-only
  • Registrado em infra-solla STATE.md + runbook + changelog
  • Validação ao vivo: dispatch manual → deploy no runner → "already deployed" no segundo dispatch