- CLAUDE.md for AI agents to understand the codebase - GITEA-GUIDE.md centralizes all Gitea operations (API, Registry, Auth) - DEVELOPMENT-WORKFLOW.md explains complete dev process - ROADMAP.md, NEXT-SESSION.md for planning - QUICK-REFERENCE.md, TROUBLESHOOTING.md for daily use - 40+ detailed docs in /docs folder - Backend as submodule from Gitea Everything documented for autonomous operation. Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
10 KiB
10 KiB
Gitea Deployment en Kubernetes
Gitea StatefulSet
# k8s/gitea/gitea-statefulset.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-data
namespace: gitea
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: gitea
namespace: gitea
spec:
serviceName: gitea
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea
image: gitea/gitea:1.22
ports:
- name: http
containerPort: 3000
- name: ssh
containerPort: 22
env:
- name: USER_UID
value: "1000"
- name: USER_GID
value: "1000"
- name: GITEA__database__DB_TYPE
value: "mysql"
- name: GITEA__database__HOST
value: "mysql.control-plane.svc.cluster.local:3306"
- name: GITEA__database__NAME
value: "gitea"
- name: GITEA__database__USER
value: "root"
- name: GITEA__database__PASSWD
valueFrom:
secretKeyRef:
name: aiworker-secrets
key: db-password
- name: GITEA__server__DOMAIN
value: "git.aiworker.dev"
- name: GITEA__server__SSH_DOMAIN
value: "git.aiworker.dev"
- name: GITEA__server__ROOT_URL
value: "https://git.aiworker.dev"
- name: GITEA__server__HTTP_PORT
value: "3000"
- name: GITEA__server__SSH_PORT
value: "2222"
- name: GITEA__security__INSTALL_LOCK
value: "true"
- name: GITEA__webhook__ALLOWED_HOST_LIST
value: "*.svc.cluster.local"
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "4Gi"
livenessProbe:
httpGet:
path: /api/healthz
port: 3000
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/healthz
port: 3000
initialDelaySeconds: 30
periodSeconds: 5
volumes:
- name: data
persistentVolumeClaim:
claimName: gitea-data
---
apiVersion: v1
kind: Service
metadata:
name: gitea
namespace: gitea
spec:
selector:
app: gitea
ports:
- name: http
port: 3000
targetPort: 3000
- name: ssh
port: 2222
targetPort: 22
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: gitea-ssh
namespace: gitea
annotations:
service.beta.kubernetes.io/external-traffic: OnlyLocal
spec:
selector:
app: gitea
ports:
- name: ssh
port: 2222
targetPort: 22
protocol: TCP
type: LoadBalancer
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea
namespace: gitea
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-body-size: "512m"
spec:
ingressClassName: nginx
tls:
- hosts:
- git.aiworker.dev
secretName: gitea-tls
rules:
- host: git.aiworker.dev
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea
port:
number: 3000
Gitea Configuration
# k8s/gitea/gitea-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-config
namespace: gitea
data:
app.ini: |
[server]
PROTOCOL = http
DOMAIN = git.aiworker.dev
ROOT_URL = https://git.aiworker.dev
HTTP_PORT = 3000
SSH_PORT = 2222
DISABLE_SSH = false
START_SSH_SERVER = true
SSH_LISTEN_HOST = 0.0.0.0
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
OFFLINE_MODE = false
[database]
DB_TYPE = mysql
HOST = mysql.control-plane.svc.cluster.local:3306
NAME = gitea
USER = root
SSL_MODE = disable
[security]
INSTALL_LOCK = true
SECRET_KEY = your-secret-key-here
INTERNAL_TOKEN = your-internal-token-here
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
ENABLE_NOTIFY_MAIL = false
[webhook]
ALLOWED_HOST_LIST = *.svc.cluster.local,*.aiworker.dev
[api]
ENABLE_SWAGGER = true
[actions]
ENABLED = true
[repository]
DEFAULT_BRANCH = main
FORCE_PRIVATE = false
[ui]
DEFAULT_THEME = arc-green
Inicialización de Gitea
#!/bin/bash
# scripts/init-gitea.sh
set -e
echo "🚀 Initializing Gitea..."
# Wait for Gitea to be ready
echo "⏳ Waiting for Gitea pod..."
kubectl wait --for=condition=ready pod -l app=gitea -n gitea --timeout=300s
# Port-forward temporalmente
echo "🔌 Port-forwarding Gitea..."
kubectl port-forward -n gitea svc/gitea 3001:3000 &
PF_PID=$!
sleep 5
# Create admin user
echo "👤 Creating admin user..."
kubectl exec -n gitea gitea-0 -- gitea admin user create \
--username aiworker \
--password admin123 \
--email admin@aiworker.dev \
--admin \
--must-change-password=false
# Create organization
echo "🏢 Creating organization..."
kubectl exec -n gitea gitea-0 -- gitea admin user create \
--username aiworker-bot \
--password bot123 \
--email bot@aiworker.dev
# Generate access token
echo "🔑 Generating access token..."
TOKEN=$(kubectl exec -n gitea gitea-0 -- gitea admin user generate-access-token \
--username aiworker-bot \
--scopes write:repository,write:issue,write:user \
--raw)
echo "✅ Gitea initialized!"
echo "📍 URL: https://git.aiworker.dev"
echo "👤 User: aiworker / admin123"
echo "🔑 Bot Token: $TOKEN"
echo ""
echo "⚠️ Save this token and update the secret:"
echo "kubectl create secret generic aiworker-secrets -n control-plane \\"
echo " --from-literal=gitea-token='$TOKEN' --dry-run=client -o yaml | kubectl apply -f -"
# Stop port-forward
kill $PF_PID
Gitea Webhook Configuration
// services/gitea/setup.ts
import { giteaClient } from './client'
import { logger } from '../../utils/logger'
export async function setupGiteaWebhooks(owner: string, repo: string) {
const backendUrl = process.env.BACKEND_URL || 'https://api.aiworker.dev'
try {
// Create webhook for push events
await giteaClient.createWebhook(owner, repo, {
url: `${backendUrl}/api/webhooks/gitea`,
contentType: 'json',
secret: process.env.GITEA_WEBHOOK_SECRET || '',
events: ['push', 'pull_request', 'pull_request_closed'],
})
logger.info(`Webhooks configured for ${owner}/${repo}`)
} catch (error) {
logger.error('Failed to setup webhooks:', error)
throw error
}
}
export async function initializeGiteaForProject(projectName: string) {
const owner = process.env.GITEA_OWNER || 'aiworker'
// Create repository
const repo = await giteaClient.createRepo(projectName, {
description: `AiWorker project: ${projectName}`,
private: true,
autoInit: true,
defaultBranch: 'main',
})
// Setup webhooks
await setupGiteaWebhooks(owner, projectName)
// Create initial branches
await giteaClient.createBranch(owner, projectName, 'develop', 'main')
await giteaClient.createBranch(owner, projectName, 'staging', 'main')
logger.info(`Gitea initialized for project: ${projectName}`)
return {
repoUrl: repo.html_url,
cloneUrl: repo.clone_url,
sshUrl: repo.ssh_url,
}
}
Backup de Gitea
# k8s/gitea/gitea-backup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: gitea-backup
namespace: gitea
spec:
schedule: "0 2 * * *" # Daily at 2 AM
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: gitea/gitea:1.22
command:
- /bin/sh
- -c
- |
echo "Starting backup..."
gitea dump -c /data/gitea/conf/app.ini -f /backups/gitea-backup-$(date +%Y%m%d).zip
echo "Backup complete!"
# Upload to S3 or other storage
volumeMounts:
- name: data
mountPath: /data
- name: backups
mountPath: /backups
volumes:
- name: data
persistentVolumeClaim:
claimName: gitea-data
- name: backups
persistentVolumeClaim:
claimName: gitea-backups
restartPolicy: OnFailure
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-backups
namespace: gitea
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
Monitoreo de Gitea
# k8s/gitea/gitea-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: gitea
namespace: gitea
spec:
selector:
matchLabels:
app: gitea
endpoints:
- port: http
path: /metrics
interval: 30s
Troubleshooting
# Ver logs
kubectl logs -n gitea gitea-0 --tail=100 -f
# Entrar al pod
kubectl exec -it -n gitea gitea-0 -- /bin/sh
# Verificar config
kubectl exec -n gitea gitea-0 -- cat /data/gitea/conf/app.ini
# Regenerar admin user
kubectl exec -n gitea gitea-0 -- gitea admin user change-password \
--username aiworker --password newpassword
# Limpiar cache
kubectl exec -n gitea gitea-0 -- rm -rf /data/gitea/queues/*
SSH Keys Setup
# Generar SSH key para agentes
ssh-keygen -t ed25519 -C "aiworker-agent" -f agent-key -N ""
# Crear secret
kubectl create secret generic git-ssh-keys -n agents \
--from-file=private-key=agent-key \
--from-file=public-key=agent-key.pub
# Añadir public key a Gitea
# (via API o manualmente en UI)
Git Config para Agentes
# k8s/agents/git-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: git-config
namespace: agents
data:
.gitconfig: |
[user]
name = AiWorker Agent
email = agent@aiworker.dev
[core]
sshCommand = ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=no
[credential]
helper = store