*A builder's work is not writing code. It is having AI write it, evaluating it, and integrating it* (1-04). But the code that results needs a place to live — the repository.
2-05 stood up the gate. The workshop goes inside it. The more code AI generates, the more control over where it lives matters.
GitHub and Azure DevOps both sit on someone else's servers. Here, that workshop gets stood up on the one machine handed to the AI in 2-02.
Keep control of where the code lives
Code is an asset. The substance of the business itself is written there. The reason to leave it parked on someone else's platform is now thin.
- Cut the dependency — pricing, terms, and availability don't change at another company's convenience
- Couple it tightly with AI — generation, review, and CI run by your own rules
- One with the gate — code goes inside the 2-05 authentication too
Generic Git hosting is already there as OSS. You don't write it, you stand it up.
Stand up Forgejo
The workshop is Forgejo, a single Gitea-family binary carrying repositories, issues, pull requests, review, and CI in one. It is a replacement for GitHub, GitLab, and Azure DevOps. The project ships a single binary, and its documentation carries the systemd unit. So, as 2-02 decided, place the file and register it with systemd.
- The binary at
/usr/local/bin/forgejo, data in/var/lib/forgejo, configuration in/etc/forgejo(as the official guide has it) - It runs as the
gituser. Pushes over ssh go through the machine's own sshd as that user; no new port is opened (2-02) - The data rides on the PostgreSQL from 2-03, with one database and one role made for Forgejo
- It listens on localhost port 3000 only. Caddy takes the outside (below)
# after placing the binary, creating the git user, and registering the official forgejo.service
sudo systemctl enable --now forgejo
git remote add origin [email protected]:team/app.git
git push -u origin main # already on your own server
The PostgreSQL role name and password for Forgejo are the human's to decide and supply.
Run CI/CD with Forgejo Actions
Automating tests, builds, and deploys is Forgejo Actions. Workflows in the same syntax as GitHub Actions run as-is. Just drop one file in the repository.
# .forgejo/workflows/ci.yml
on: [push]
jobs:
test:
runs-on: host # no container; runs directly on this machine
steps:
- uses: actions/checkout@v4
- run: uv run pytest # on your own runner, at no extra charge
The runner (forgejo-runner) is a single binary too, run under systemd. With no
Docker, jobs run directly on the machine (host). The official documentation
warns that there is no isolation and a single job can destroy the host, so three
decisions go with it.
- The runner runs as its own dedicated user (the "separate users" of 2-02)
- CI runs tests, and no further. Steps that deploy to production stay among the actions the AI states before performing
- When isolation becomes necessary, step up to LXC, which Forgejo supports and apt carries
Step off GitHub Actions' minute caps and billing. The runner is on your side too, so you can verify AI-written code any number of times without watching a meter.
The local tools are Zed and the AI called from inside it
If the server is Forgejo, local editing is Zed: a Rust-built, lightweight editor with co-editing, which can host an AI agent inside the editor (ACP). Call the AI subscribed to in 2-02 in place to generate, fix, and explain, while the builder concentrates on evaluation and integration.
git clone [email protected]:team/app.git
zed app/ # call the AI, have it write, evaluate, and push
AI writes; the human decides. With the workshop (Forgejo) and the tool (Zed) in place, that division of labor just runs.
Place it behind the gate, and migrate in stages
Put Forgejo behind the reverse proxy (2-05). Migrating from GitHub, Forgejo's "New Migration" imports a repository together with its issues and PRs.
git.example.com { reverse_proxy localhost:3000 }
There is no need to switch in one stroke. Keep GitHub as a mirror and run in parallel, then move production onto Forgejo once it feels natural (2-12).
Code is the substance of the business itself. Control of where it lives belongs to you, not another company.
How to check you are done
This chapter is done when these five hold.
- You open
git.example.comin a browser and log in as the administrator you created - Code you
git pushfrom your own machine appears in the Forgejo web UI - After the push, the workflow runs on Forgejo's Actions page and the
pytestresult is visible - You open the repository in Zed, call the AI to write code, and push it from there
- A repository imported from GitHub with "New Migration" arrives with its issues and PRs attached
systemctl status forgejo forgejo-runner # both running under systemd
git push -u origin main # then look at the web UI
curl -sI https://git.example.com # does it answer through Caddy
What the human holds
Values the human supplies
- The Forgejo domain name (e.g.
git.example.com) - The PostgreSQL role name and password for Forgejo
- The first administrator's name and email address
- The ssh public key of the human's own PC (used for pushes; registered in Forgejo's web UI)
- The access token used to import from GitHub
Actions the AI states before performing
- Deleting a GitHub repository, or changing its visibility
- Pointing a DNS record at
git.example.com - Enabling or running a workflow that deploys to production
- Deleting or recreating the data under
/var/lib/forgejo
Versions checked, and when
- Forgejo 16.0.5 (2026-09-17, the single binary from Codeberg), forgejo-runner
actions/checkout@v4— the checkout action used in the workflow- Zed, Caddy, PostgreSQL (2-03's Debian 13 package) — no version pinned
- The procedure was written on 2026-07-06 and reviewed on 2026-10-05
- If a version has moved, have the AI confirm the official procedure before proceeding
Summary
The builder's workshop, on your own side.
- Forgejo — repositories, issues, PRs, and review in one (on the 2-03 PostgreSQL); a single binary under systemd
- Forgejo Actions — GitHub Actions-compatible CI/CD; the runner runs as its own user, directly on the machine
- Zed + AI — call the AI from inside a lightweight editor; write, evaluate, push
- Behind the gate — fenced by the reverse proxy, migrate from GitHub gradually
The only code written is configuration. The generic is already there, as OSS. The next chapter keeps the manuscript of every document as text, and turns Word and Claude Docs into doors you pass through.