layered-soul/skills/forgejo-operations/references/forgejo-migration-plan.md
Sam & Claude 4d8ce07fa7 docs: apply Prettier to current markdown (Sam & Codex)
Normalize markdown formatting after the latest main updates.\n\nChecks: python3 scripts/layered_soul.py validate .; npx --yes prettier@3 --check '**/*.md'; git diff --check.
2026-06-14 01:48:32 +02:00

3.1 KiB

Codeberg → Self-Hosted Forgejo Migration Plan

Target: code.smilepowered.org (Forgejo 10.0.3, port 2222 SSH)

Architecture: Machine-User Model

Each host/agent gets its own Forgejo user + SSH key + scoped token for clean audit trails and per-agent revocation:

User Host Agent Access
clawdie Org owner Admin (bootstrap only)
hermes-debby debby Hermes write:repository
claude-domedog domedog Claude write:repository
codex-osa osa Codex read:repository (initially)

Principle: never copy private SSH keys between hosts. Each machine user gets its own key generated on that host.

Migration Order

  1. Create repos under clawdie user (org creation blocked — user/org name collision; repos under user account have identical URL structure)
    • clawdie/colibri, clawdie/clawdie-ai, clawdie/clawdie-iso
  2. Push Colibri first (smoke test — 300 KB, instant)
  3. Push Clawdie-AI (187 MB, 1636 commits — background push, ~5 min)
  4. Push Clawdie-ISO from cleaned mirror
  5. Verify all three repos with git ls-remote and Forgejo API
  6. Update AGENTS.md in each repo: replace Codeberg remotes with Forgejo
  7. Create per-agent machine users + SSH keys
  8. Add branch protection after initial imports succeed
  9. Add webhooks/CI-style FreeBSD validation
  10. Delete bootstrap admin token

Token Strategy

  • One bootstrap token with write:repository + write:user + write:organization for setup only
  • Revoke bootstrap token after setup complete
  • Each machine user gets its own scoped token
  • Day-to-day git operations use SSH keys, not tokens
  • Tokens are immutable after creation — to change scopes, delete and recreate

SSH Pitfall: Password Popups from Agent Tools

When an agent tool (non-TTY) runs ssh to a host where the key isn't authorized, KDE's ssh-askpass fires a graphical password prompt on the user's desktop. Prevention: test SSH access manually from a real terminal before delegating to agent tools. Ensure IdentitiesOnly yes + PreferredAuthentications publickey in SSH config.

Shallow Clone Fixes

When pushing a shallow clone to Forgejo fails with "shallow update not allowed" and the original remote is unreachable:

  1. Check .git/shallow for boundary commits
  2. Create a graft making the root commit parentless:
    echo "$(cat .git/shallow) " > .git/info/grafts
    git filter-branch -f --msg-filter "cat" -- --all
    rm .git/info/grafts .git/shallow
    
  3. Push — repo is now self-contained

WARNING: rewrites commit hashes. Only for migration when original remote history is preserved elsewhere.

Verification After Push

git ls-remote git@code.smilepowered.org:clawdie/$REPO.git HEAD
curl -s "https://code.smilepowered.org/api/v1/repos/clawdie/$REPO" \
  -H "Authorization: token <token>" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); \
    print(f'HEAD: {d[\"default_branch\"]}  Size: {d[\"size\"]} KB  Empty: {d[\"empty\"]}')"