mirror of
https://github.com/terraphim/gitea-infrastructure.git
synced 2026-07-16 01:00:33 +02:00
- Document service account read-only limitation - Add session 4 log (1Password token update, task tracking) - Track expired token fix in cto-executive-system#8 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
410 lines
15 KiB
Markdown
410 lines
15 KiB
Markdown
# Gitea Infrastructure Handover Document
|
|
|
|
## Overview
|
|
|
|
Self-hosted Gitea instance running on bigbox server with S3 storage, PostgreSQL, and Prometheus monitoring.
|
|
|
|
**URL:** https://git.terraphim.cloud
|
|
**GitHub Mirror:** https://github.com/terraphim/gitea-infrastructure
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Internet │
|
|
└─────────────────────────┬───────────────────────────────────┘
|
|
│ HTTPS (port 443)
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Caddy Reverse Proxy │
|
|
│ (terraphim.cloud, existing) │
|
|
└─────────────────────────┬───────────────────────────────────┘
|
|
│ git.terraphim.cloud -> localhost:3000
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Docker Network (gitea) │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Gitea (port 3000) │ PostgreSQL │ SeaweedFS (S3) │
|
|
│ - Attachments │ (port 5432) │ - S3 (port 8333) │
|
|
│ - Avatars │ │ - Filer (port 8888) │
|
|
│ - LFS │ │ - Volume (port 8080) │
|
|
│ │ │ - Master (port 9333) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│ │ │
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Tailscale Network │
|
|
│ Prometheus (100.106.66.7:9000) - internal │
|
|
│ S3 (100.106.66.7:8333) - internal only │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Services
|
|
|
|
| Service | Port | Access | Description |
|
|
|---------|------|--------|-------------|
|
|
| Gitea | 3000 | localhost (via Caddy) | Git web UI |
|
|
| Gitea SSH | 22/222 | Public | Git over SSH |
|
|
| PostgreSQL | 5432 | Docker internal | Database |
|
|
| SeaweedFS S3 | 8333 | Tailscale only | S3-compatible storage |
|
|
| SeaweedFS Filer | 8888 | Docker internal | File interface |
|
|
| Prometheus | 9000 | Tailscale only | Metrics |
|
|
|
|
## Server Access
|
|
|
|
**Server:** bigbox (100.106.66.7)
|
|
|
|
```bash
|
|
# SSH to bigbox
|
|
ssh bigbox
|
|
|
|
# Navigate to stack directory
|
|
cd ~/gitea-stack
|
|
|
|
# View container status
|
|
docker compose ps
|
|
|
|
# View logs
|
|
docker compose logs -f gitea
|
|
|
|
# Restart Gitea
|
|
docker compose restart server
|
|
|
|
# Stop entire stack
|
|
docker compose down
|
|
|
|
# Start stack
|
|
docker compose up -d
|
|
```
|
|
|
|
## 1Password Secrets
|
|
|
|
Vault: `TerraphimPlatform`
|
|
|
|
| Item | Purpose |
|
|
|------|---------|
|
|
| gitea-postgres | PostgreSQL password |
|
|
| gitea-s3 | S3 access key and secret key |
|
|
|
|
### Re-deploying with 1Password
|
|
|
|
1. Source the 1Password authentication:
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
```
|
|
|
|
2. Inject secrets and deploy:
|
|
```bash
|
|
cd ~/gitea-stack
|
|
op inject --in-file ../gitea_config/docker-compose.yml.template --out-file docker-compose.yml
|
|
docker compose up -d
|
|
```
|
|
|
|
## Storage Configuration
|
|
|
|
### S3 Buckets
|
|
|
|
- **gitea** - Attachments, avatars, repository files
|
|
- **gitea-lfs** - Git LFS objects
|
|
|
|
### Gitea Storage Settings
|
|
|
|
The following storage types are configured to use S3 (Minio):
|
|
|
|
- `[attachment]` - File attachments
|
|
- `[picture]` - Avatars and images
|
|
- `[lfs]` - Git LFS objects
|
|
- `[storage]` - Default storage configuration
|
|
|
|
Local storage is used for:
|
|
- Git repositories (`/data/git/repositories`)
|
|
- Database (PostgreSQL)
|
|
|
|
## Caddy Configuration
|
|
|
|
Caddy is already running on bigbox. The git route is appended to `/etc/caddy/Caddyfile`:
|
|
|
|
```
|
|
git.terraphim.cloud {
|
|
reverse_proxy localhost:3000
|
|
}
|
|
```
|
|
|
|
To update Caddy config:
|
|
```bash
|
|
ssh bigbox
|
|
sudo vim /etc/caddy/Caddyfile
|
|
sudo caddy reload
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
**Prometheus:** http://100.106.66.7:9000 (Tailscale only)
|
|
|
|
Scrape targets configured in `prometheus/prometheus.yml`.
|
|
|
|
## Troubleshooting
|
|
|
|
### Check Gitea status
|
|
```bash
|
|
ssh bigbox
|
|
docker compose ps
|
|
docker logs gitea
|
|
```
|
|
|
|
### Check S3 connectivity
|
|
```bash
|
|
ssh bigbox
|
|
docker exec gitea curl -s http://s3storage:8333/
|
|
```
|
|
|
|
### Reset PostgreSQL password
|
|
```bash
|
|
ssh bigbox
|
|
docker compose exec db psql -U gitea -c "ALTER USER gitea WITH PASSWORD 'newpassword';"
|
|
```
|
|
|
|
### View S3 buckets
|
|
```bash
|
|
ssh bigbox
|
|
curl -s http://localhost:8888/bucket/
|
|
```
|
|
|
|
## Backup
|
|
|
|
To back up the Gitea data:
|
|
|
|
```bash
|
|
# On bigbox
|
|
cd ~/gitea-stack
|
|
docker compose stop
|
|
tar -czf gitea-backup-$(date +%Y%m%d).tar.gz gitea/ postgres/ seaweedfs/
|
|
docker compose start
|
|
```
|
|
|
|
## Updates
|
|
|
|
To update Gitea to a new version:
|
|
|
|
1. Edit `docker-compose.yml.template`:
|
|
```yaml
|
|
image: gitea/gitea:NEW_VERSION
|
|
```
|
|
|
|
2. Re-inject secrets and deploy:
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
op inject --in-file ../gitea_config/docker-compose.yml.template --out-file docker-compose.yml
|
|
docker compose up -d --build
|
|
```
|
|
|
|
## GitHub -> Gitea Mirroring
|
|
|
|
Gitea is configured as a **pull mirror** from GitHub. No GitHub Actions or manual push needed.
|
|
|
|
**How it works:** Gitea polls GitHub every hour and pulls new commits automatically.
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Source | https://github.com/terraphim/gitea-infrastructure (private) |
|
|
| Mirror | https://git.terraphim.cloud/terraphim/gitea-infrastructure |
|
|
| Interval | 1 hour |
|
|
| Auth | GitHub token stored in Gitea migration config |
|
|
|
|
### Manual Sync
|
|
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
export GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
|
|
curl -s -X POST "https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure/mirror-sync" \
|
|
-H "Authorization: token $GITEA_TOKEN"
|
|
```
|
|
|
|
### Recreating the Mirror
|
|
|
|
If the mirror breaks (e.g., GitHub token expires), delete and recreate:
|
|
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
|
|
GH_TOKEN=$(gh auth token)
|
|
|
|
# Delete existing
|
|
curl -s -X DELETE "https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure" \
|
|
-H "Authorization: token $GITEA_TOKEN"
|
|
|
|
sleep 10
|
|
|
|
# Recreate as pull mirror
|
|
curl -s -X POST "https://git.terraphim.cloud/api/v1/repos/migrate" \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"clone_addr\": \"https://github.com/terraphim/gitea-infrastructure\",
|
|
\"repo_name\": \"gitea-infrastructure\",
|
|
\"repo_owner\": \"terraphim\",
|
|
\"service\": \"github\",
|
|
\"auth_token\": \"$GH_TOKEN\",
|
|
\"mirror\": true,
|
|
\"mirror_interval\": \"1h\"
|
|
}"
|
|
```
|
|
|
|
### Key Constraints
|
|
|
|
- The Gitea repo is **read-only** (mirror). All pushes go to GitHub only.
|
|
- An existing repo cannot be converted to a mirror -- must delete and recreate via `POST /repos/migrate`.
|
|
- `service: "github"` requires a valid GitHub token for private repos. `service: "git"` fails with "terminal prompts disabled".
|
|
- The 1Password item `github.personal.token` is expired. Use `gh auth token` instead.
|
|
|
|
## AI Agent Skill (Gitea Task Management)
|
|
|
|
Added 2026-02-18. Provides AI agents with project and task management via Gitea API.
|
|
|
|
### Architecture
|
|
|
|
Dual-mode: gitea-mcp (75+ tools for standard CRUD) + curl/jq shell helpers (milestones, workflow labels, dependencies -- areas where gitea-mcp has gaps).
|
|
|
|
### Key Constraint
|
|
|
|
Gitea 1.22.6 has NO project board REST API. Milestones serve as project containers with built-in progress tracking.
|
|
|
|
### Files
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `.agents/skills/gitea/SKILL.md` | Agent skill document with all helpers |
|
|
| `.agents/skills/gitea/setup-labels.sh` | Idempotent repo + 12 label creation |
|
|
| `.agents/skills/gitea/test-gitea-skill.sh` | 10 integration tests (26 assertions) |
|
|
| `.docs/RESEARCH-gitea-agent-skill.md` | Phase 1 research (verified against live) |
|
|
| `.docs/DESIGN-gitea-agent-skill.md` | Phase 2 design document |
|
|
|
|
### Default Task Repository
|
|
|
|
`terraphim/agent-tasks` -- overridable via `GITEA_OWNER` and `GITEA_REPO` env vars.
|
|
|
|
### Authentication
|
|
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
export GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
|
|
```
|
|
|
|
### Workflow Labels
|
|
|
|
12 scoped labels across 3 scopes (workflow, priority, type). Workflow state machine: `ready -> in-progress -> blocked -> done`.
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
source ~/op_zesticai_non_prod.sh
|
|
export GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
|
|
.agents/skills/gitea/test-gitea-skill.sh
|
|
```
|
|
|
|
All 26 assertions pass against live Gitea 1.22.6 as of 2026-02-18.
|
|
|
|
### Critical API Gotchas
|
|
|
|
1. **Label exclusivity is UI-only** -- API POST `/labels` just appends. Must use PUT with label swap pattern (get current, filter `workflow:*`, add new, PUT all).
|
|
2. **Assignees** -- Use `PATCH /issues/{index}` with `{"assignees": [...]}`. The `POST /issues/{index}/assignees` endpoint does not exist in 1.22.6.
|
|
3. **Issue dependencies** -- Body uses `IssueMeta` format: `{"owner": "...", "repo": "...", "index": N}` (NOT `{"depends_on_id": N}`).
|
|
|
|
## Pre-commit Hooks
|
|
|
|
Added `.pre-commit-config.yaml` with:
|
|
- Trailing whitespace, end-of-file fixer, YAML/JSON check
|
|
- Merge conflict and private key detection
|
|
- Secret detection via `detect-secrets` (baseline at `.secrets.baseline`)
|
|
|
|
## Key Files
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `docker-compose.yml.template` | Template with 1Password references |
|
|
| `Caddyfile` | Caddy reverse proxy config |
|
|
| `deploy-to-bigbox.sh` | Deployment script |
|
|
| `s3_config.json.template` | SeaweedFS S3 config template |
|
|
| `prometheus/prometheus.yml` | Prometheus scrape config |
|
|
| `MIRRORING-GUIDE.md` | Gitea pull mirror setup (replaced GitHub Actions) |
|
|
| `.agents/skills/gitea/SKILL.md` | AI agent Gitea skill |
|
|
| `.agents/skills/gitea/setup-labels.sh` | Label setup script |
|
|
| `.agents/skills/gitea/test-gitea-skill.sh` | Integration tests |
|
|
| `.pre-commit-config.yaml` | Pre-commit hook config |
|
|
| `ARTICLE-agent-task-management.md` | CTO voice article (~2800 words) |
|
|
| `ARTICLE-agent-task-consolidation.md` | Technical reference article (~6000 words) |
|
|
| `lessons-learned.md` | Session discoveries and pitfalls |
|
|
|
|
## Articles
|
|
|
|
Two comparison articles documenting the migration from beads/br/agent-mail to Gitea:
|
|
|
|
| File | Style | Words |
|
|
|------|-------|-------|
|
|
| `ARTICLE-agent-task-management.md` | CTO voice (bold, narrative) | ~2800 |
|
|
| `ARTICLE-agent-task-consolidation.md` | Technical reference (comprehensive) | ~6000 |
|
|
|
|
Both cover: 1Password integration, Gitea + SeaweedFS infrastructure, all three API gotchas with fix patterns, and honest tradeoff analysis. All commands verified working against live instance.
|
|
|
|
## Gitea Mirror
|
|
|
|
Gitea pulls from GitHub automatically (1-hour interval). No GitHub Actions needed.
|
|
|
|
| Role | URL |
|
|
|------|-----|
|
|
| Primary (push here) | https://github.com/terraphim/gitea-infrastructure |
|
|
| Mirror (auto-synced) | https://git.terraphim.cloud/terraphim/gitea-infrastructure |
|
|
|
|
GitHub Actions workflows (`sync-to-gitea.yml`, `mirror-check.yml`) were removed -- Gitea's native pull mirror replaces them.
|
|
|
|
## Session Log (2026-02-18)
|
|
|
|
### Session 1: Gitea Agent Skill Implementation
|
|
- Rewrote Gitea agent skill with verified API patterns (milestones, workflow labels, dependencies)
|
|
- Created setup-labels.sh for idempotent repo + label creation
|
|
- Created test-gitea-skill.sh with 10 tests (26 assertions), all passing
|
|
- Found and fixed 3 API behavior bugs (label exclusivity, assignee endpoint, dependency format)
|
|
- Added pre-commit hooks and fixed trailing whitespace across 15 files
|
|
- Conducted disciplined research and design phases with live API verification
|
|
|
|
### Session 2: Articles and Publishing
|
|
- Wrote two comparison articles (CTO voice + technical reference) comparing beads/br/agent-mail with Gitea replacement
|
|
- All code snippets, commands, and configurations verified against live Gitea instance
|
|
- Pushed all commits to GitHub origin/main
|
|
|
|
### Session 3: Replace GitHub Actions with Gitea Pull Mirror
|
|
- Removed `sync-to-gitea.yml` and `mirror-check.yml` GitHub Actions workflows
|
|
- Deleted manually-pushed Gitea repo, recreated as native pull mirror via `POST /repos/migrate`
|
|
- Discovered `github.personal.token` in 1Password is expired (401); used `gh auth token` instead
|
|
- Discovered Gitea creates empty mirror repos on failed async clones (silent failure)
|
|
- Discovered `service: "git"` fails for private repos; `service: "github"` with valid token works
|
|
- Mirror interval set to 1 hour, manual sync available via API
|
|
- Rewrote MIRRORING-GUIDE.md with pull mirror approach and all gotchas
|
|
- Updated HANDOVER.md and lessons-learned.md
|
|
|
|
### Session 4: 1Password Token Update and Task Tracking
|
|
- Attempted to update `github.personal.token` via `op item edit` -- blocked by service account read-only permissions
|
|
- Confirmed `op_zesticai_non_prod.sh` sources a SERVICE_ACCOUNT with no write access to TerraphimPlatform vault
|
|
- Created GitHub issue to track the fix: https://github.com/AlexMikhalev/cto-executive-system/issues/8
|
|
|
|
### All Commits (pushed to GitHub, auto-synced to Gitea)
|
|
- `57eabbb` refactor: Replace GitHub Actions mirroring with Gitea native pull mirror
|
|
- `0e69456` docs: Update handover with articles, publishing, and new lessons learned
|
|
- `62e2275` docs: Add articles comparing beads/br/agent-mail with Gitea replacement
|
|
- `4ff1821` docs: Update handover and add lessons learned
|
|
- `b67284e` chore: Fix trailing whitespace across project files
|
|
- `66b305d` feat(gitea-skill): Add integration tests and fix workflow label swap
|
|
- `1fd202d` feat(gitea-skill): Rewrite Gitea agent skill with verified API patterns
|
|
|
|
### Next Steps
|
|
1. Update `github.personal.token` in 1Password manually (service account is read-only) -- tracked in https://github.com/AlexMikhalev/cto-executive-system/issues/8
|
|
2. Grant write access to `op_zesticai_non_prod` service account on TerraphimPlatform vault
|
|
3. Consider adding gitea-mcp or forgejo-mcp as MCP server for Claude Code (see SKILL.md MCP Integration section)
|
|
4. Create first real milestone and tasks in `terraphim/agent-tasks` for a project
|
|
|
|
## Contacts
|
|
|
|
- Infrastructure owner: Alex
|
|
- 1Password vault: TerraphimPlatform
|