Gitea
Self-hosted git as the source of truth - every change is a branch and a pull request into a protected main, with the same gate for humans and automation alike.
What it is & why I use it
Gitea is the self-hosted git service at the center of AutomationLab. It is where the truth lives: pipeline definitions, infrastructure code, configuration, and this site all sit in Gitea repositories, and nothing reaches the platform except through a merge into a protected branch. If it is not in git, it is not real.
I self-host it because the source of truth for a self-contained platform should itself be part of the platform - not a dependency on an outside service. Owning the git server means owning the whole change-control story end to end.
How I use it in the lab
- Branch per change, PR to merge. Every change is a feature branch and a pull
request into
main; direct pushes to the protected branch are not the path. - Branch protection with required checks. Merges are gated on the security and lint checks passing, so main stays green and reviewed by construction.
- Automation opens PRs too. The tooling that assists development opens pull requests through the API, held to the same protections as a human contributor.
- The hub the rest of the flow trusts. The GitOps reconciler and CI both take Gitea as their input, so the git server is the single upstream everything else follows.
Architecture
In action
Lessons learned & gotchas
git push perfectly, but the same credential
returns 401 against the REST API used to open a pull request. It is scoped
to git transport operations, not to the API surface, so "my git works, why is the API
rejecting me?" has a real answer. The fix is to stop reusing the git credential for API
calls entirely: automation authenticates to the API with a dedicated personal access
token, fetched from the secrets manager at run time and never written to disk. Push
and API are two different doors with two different keys.
- One canonical way to open a PR. Rather than hand-curling the API and rediscovering the 401 every time, the lab has a single PR-opening path that pulls the right token and does it correctly - so the gotcha is solved once, in one place.
- Keep the token out of the command line. An API token pasted as an argument leaks into shell history and process listings. The helper fetches it and uses it in memory; it never becomes a visible argument or a file.
- Protect the branch, then honour it everywhere. Branch protection only means something if automation is subject to it too - the moment a bot can bypass the gate, the gate is decorative.
Impact
Gitea is the anchor the whole change-control story hangs from: branch, review, gate, merge - for people and machines alike. The auth gotcha is a small, sharp reminder that "it authenticated once" does not mean "it is authorized for what you are about to do" - scope matters, and the clean fix is a purpose-scoped credential, not reusing the one you already had.
Code & further reading
Published tooling is scrubbed of hostnames, addresses, and any token material before it goes public; tokens always come from the secrets manager.