# Gitea Deployment en Kubernetes ## Gitea StatefulSet ```yaml # 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 ```yaml # 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 ```bash #!/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 ```typescript // 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 ```yaml # 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 ```yaml # 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 ```bash # 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 ```bash # 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 ```yaml # 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 ```