Scaffold Matrix + GitOps + Claude automation stack
build-agent / build-and-push (push) Failing after 18s
build-agent / build-and-push (push) Failing after 18s
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# gitops-automation
|
||||
|
||||
Claude Code automation wired into Gitea + Portainer + Matrix on this VPS. See
|
||||
`~/.claude/plans/cozy-honking-lantern.md` on the host for the full design rationale.
|
||||
|
||||
Three things this gives you:
|
||||
- **PR review**: opening/updating a PR in a watched Gitea repo gets a Claude-authored
|
||||
review comment.
|
||||
- **GitOps redeploy**: pushing to `main` on this repo rebuilds the `claude-agent` image
|
||||
(Gitea Actions) and redeploys the stack (Portainer webhook).
|
||||
- **Chat-driven coding agent**: `!claude owner/repo <instruction>` in the Matrix control
|
||||
room clones the repo, runs Claude Code, and opens a PR with the result.
|
||||
|
||||
Nothing here auto-merges. Every path stops at a comment or an open PR — a human clicks merge.
|
||||
|
||||
## Prerequisites (one-time, on the VPS)
|
||||
|
||||
```bash
|
||||
sudo usermod -aG docker william # then start a new shell/session
|
||||
docker network create web
|
||||
```
|
||||
|
||||
## Bring-up order
|
||||
|
||||
1. **DNS** — confirm these resolve to `217.160.66.143`:
|
||||
`gitea.apps.williamturner.eu`, `portainer.apps.williamturner.eu`,
|
||||
`matrix.apps.williamturner.eu`, `agent.apps.williamturner.eu`.
|
||||
|
||||
2. **Front Gitea with Traefik**: edit `~/gitea/docker-compose.yml` — add it to the `web`
|
||||
network and Traefik labels (mirror the `matrix-homeserver` block in this repo's
|
||||
`docker-compose.yml`, using port `3000` as the service port and rule
|
||||
`` Host(`gitea.apps.williamturner.eu`) ``). Update `~/gitea/data/gitea/conf/app.ini`:
|
||||
`DOMAIN` and `ROOT_URL` → `https://gitea.apps.williamturner.eu/`. Recreate the container,
|
||||
confirm the HTTPS URL works, *then* remove `3000:3000` from the port mapping.
|
||||
|
||||
3. **Front Portainer with Traefik**: same pattern on `~/portainer-compose.yaml`, service
|
||||
port `9443` (Portainer serves TLS itself on that port — either terminate TLS at Traefik
|
||||
with `traefik.http.services.portainer.loadbalancer.server.scheme=https` and
|
||||
`serversTransport` with insecure skip-verify, or simplest: also expose Portainer's plain
|
||||
HTTP port internally and point Traefik at that instead). Confirm
|
||||
`https://portainer.apps.williamturner.eu` works before removing `9443:9443`.
|
||||
|
||||
4. **Create the `gitops-automation` repo in Gitea** (via `http://217.160.66.143:3000` if
|
||||
step 2 isn't done yet, otherwise the HTTPS URL), push this directory to it.
|
||||
|
||||
5. **Gitea API token**: user Settings → Applications → generate a token with repo +
|
||||
webhook scopes. Put it in `.env` as `GITEA_TOKEN`.
|
||||
|
||||
6. **Gitea Actions runner**: admin Settings → Actions → Runners → create registration
|
||||
token → `.env` as `ACT_RUNNER_REGISTRATION_TOKEN`. Also set repo-level Actions
|
||||
variables `GITEA_HOST` (e.g. `gitea.apps.williamturner.eu`) and secret `GITEA_TOKEN`
|
||||
(Settings → Actions → Variables/Secrets on the repo) — the workflow in
|
||||
`.gitea/workflows/build.yml` reads those.
|
||||
|
||||
7. **First image build** (registry is empty until Actions runs once):
|
||||
```bash
|
||||
cp .env.example .env # fill in values as you go
|
||||
docker build -t "$(grep GITEA_REGISTRY_IMAGE .env | cut -d= -f2)" ./agent
|
||||
docker login <gitea-host> -u <your-username>
|
||||
docker push "$(grep GITEA_REGISTRY_IMAGE .env | cut -d= -f2)"
|
||||
```
|
||||
|
||||
8. **Bring up the stack**, ideally as a Portainer "Repository" stack pointed at this repo
|
||||
(so it's also the GitOps redeploy target) — or directly:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
9. **First boot: Matrix bot account** — with `MATRIX_ALLOW_REGISTRATION=true` in `.env`,
|
||||
redeploy `matrix-homeserver`, then register the bot:
|
||||
```bash
|
||||
curl -s https://matrix.apps.williamturner.eu/_matrix/client/v3/register \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"claude-bot","password":"<pick one>","auth":{"type":"m.login.dummy"}}'
|
||||
```
|
||||
This returns an `access_token` — put it in `.env` as `MATRIX_BOT_TOKEN`. Then set
|
||||
`MATRIX_ALLOW_REGISTRATION=false` and redeploy `matrix-homeserver` again.
|
||||
|
||||
10. **Control room**: from any Matrix client logged in as yourself on this homeserver,
|
||||
create a room, invite `@claude-bot:matrix.apps.williamturner.eu`, copy the room ID
|
||||
into `.env` as `MATRIX_CONTROL_ROOM_ID`. Redeploy `claude-agent`.
|
||||
|
||||
11. **Portainer stack webhook**: in the stack's settings, enable the webhook, copy the URL
|
||||
into `.env`/repo secrets as `PORTAINER_STACK_WEBHOOK_URL`.
|
||||
|
||||
12. **Gitea webhooks** on each repo you want automation for:
|
||||
- push → `main` → `PORTAINER_STACK_WEBHOOK_URL` (only needed on *this* repo, for
|
||||
GitOps redeploy of the automation stack itself)
|
||||
- pull request (opened, synchronized) → `https://agent.apps.williamturner.eu/webhooks/gitea`,
|
||||
secret = `GITEA_WEBHOOK_SECRET`, on every repo you want auto-reviewed.
|
||||
|
||||
13. **Firewall**: `sudo ufw allow 80/tcp 443/tcp`; once the HTTPS routes above are all
|
||||
confirmed working, `sudo ufw delete allow 3000/tcp` and `sudo ufw delete allow 9443/tcp`.
|
||||
|
||||
## Smoke test
|
||||
|
||||
- Open a throwaway PR on a repo with the PR webhook set → expect a Claude review comment.
|
||||
- In the Matrix control room: `!claude owner/repo add a comment to the README` → expect a
|
||||
"working on it" reply, then a PR link.
|
||||
- `git push` to `main` on this repo → expect a Gitea Actions run, then a Portainer redeploy.
|
||||
|
||||
## Notes
|
||||
|
||||
- `agent/src/runner.js` is the only thing that ever runs `git commit`/`git push`/`git
|
||||
checkout` — Claude Code itself is explicitly denied those tools (`--disallowedTools`),
|
||||
so even a misbehaving prompt can't push directly or touch `main`.
|
||||
- The Matrix bot only reacts inside `MATRIX_CONTROL_ROOM_ID`; keep that room invite-only.
|
||||
- `.gitea/workflows/build.yml` assumes the act_runner label `docker` — check
|
||||
`GITEA_RUNNER_LABELS` in `docker-compose.yml` matches what you actually registered.
|
||||
Reference in New Issue
Block a user