Un espejo de tus repositorios críticos no te protege de depender de un SaaS para ejecutar los tests en cada commit. Este stack monta Gitea como forja de código, con Gitea Actions (compatible en sintaxis con GitHub Actions) ejecutando los workflows en un runner propio, y ntfy avisando al móvil en cuanto un build falla — sin ceder ni el código ni el pipeline de CI a un tercero.
Tu propia forja de código con CI integrado: Gitea + Actions + avisos por ntfy
Objetivo
Alojar tu propio repositorio Git con integración continua propia, para dejar de depender de un SaaS externo tanto para guardar el código como para ejecutar los tests, con un aviso al móvil si un build falla.
Componentes
Base · Host de contenedores
Servidor Docker existente
Servicio principal · Forja de código
CI/CD · Ejecuta los workflows
Notificaciones · Avisa si un build falla
Cómo se conecta

Haz clic para ampliar
Ensamblaje
Desplegar Gitea
Gitea corre bien con SQLite para un uso personal o en pequeño equipo, sin necesidad de levantar un motor de base de datos aparte. Define un volumen persistente para /data y publica el puerto HTTP detrás de tu reverse proxy habitual con HTTPS:
services: gitea: image: gitea/gitea:28.0.0 restart: unless-stopped environment: - GITEA__database__DB_TYPE=sqlite3 - GITEA__server__ROOT_URL=https://git.tu-dominio.es/ volumes: - ./gitea-data:/data ports: - "3000:3000" - "222:22"Habilitar Actions y registrar el runner
Actions viene desactivado por defecto en Gitea. Actívalo en app.ini, genera un token de registro desde el panel de administración de la instancia y levanta el runner apuntando a ese token:
[actions] ENABLED = true
services: act-runner: image: gitea/act_runner:latest restart: unless-stopped environment: - GITEA_INSTANCE_URL=https://git.tu-dominio.es - GITEA_RUNNER_REGISTRATION_TOKEN=<token-generado-en-el-admin> volumes: - ./runner-data:/data - /var/run/docker.sock:/var/run/docker.sockConectar ntfy para los avisos de build
Con ntfy ya corriendo (un contenedor con un volumen para la cache de mensajes basta), añade un paso final al workflow que mande una notificación solo cuando el job anterior falle:
- name: Avisar por ntfy si falla if: failure() run: | curl -H "Title: Build roto" \ -d "${{ github.repository }} — commit ${{ github.sha }} ha fallado" \ https://ntfy.tu-dominio.es/ci-avisos
Conclusión
Para comprobar que todo el circuito funciona, haz push a un repositorio con un workflow mínimo (por ejemplo, uno que solo ejecute un echo y falle a propósito una vez) y confirma tres cosas en orden: que el job aparece en la pestaña Actions de Gitea, que el runner lo recoge y lo ejecuta de verdad (no se queda en cola), y que el fallo llega como notificación a ntfy en segundos. Si el job se queda en cola sin recogerlo nadie, el runner no se ha registrado bien contra la instancia — revisa el token de registro antes de mirar cualquier otra cosa.



