TL;DR — Resumen Rápido
Despliega Gitea como forge Git autoalojado. Cubre Docker Compose, systemd, Gitea Actions, LDAP, OAuth2, registros de paquetes, mirroring y proxy inverso Caddy.
Gitea es un forge Git ligero y autoalojado escrito en Go que se distribuye como un binario único y funciona cómodamente en hardware tan modesto como una Raspberry Pi. Si alguna vez has querido control total sobre tu código fuente, pipelines de CI/CD, seguimiento de incidencias y registros de paquetes sin pagar precios de GitHub o GitLab en la nube — y sin el peso operativo de una instancia de GitLab CE — Gitea es la respuesta. Esta guía cubre desde un despliegue de producción con Docker Compose hasta Gitea Actions CI, SSO con OAuth2, registros de paquetes y mirroring de repositorios.
Requisitos Previos
- Docker y Docker Compose v2 instalados en el host
- Un nombre de dominio apuntando al servidor (para TLS con Caddy)
- Al menos 512 MB de RAM y 2 GB de disco (Gitea necesita ~150 MB; el resto para PostgreSQL y repositorios)
- Familiaridad básica con volúmenes Docker y sintaxis YAML
- Puerto 3000 (o 80/443 mediante proxy inverso) accesible desde tu red
Arquitectura de Gitea
Gitea es una aplicación Go compilada en un único binario sin dependencias en tiempo de ejecución. Incluye un servidor web, hooks de Git, un daemon SSH y trabajadores en segundo plano. Opciones de almacenamiento:
| Backend | Ideal para | Notas |
|---|---|---|
| SQLite | Usuario único / equipos pequeños | Sin configuración; no apto para alta concurrencia |
| PostgreSQL | Equipos y producción | Recomendado; mejor rendimiento |
| MySQL / MariaDB | Infraestructura MySQL existente | Soportado; se prefiere PostgreSQL |
Los datos de repositorios se almacenan como repos Git bare en disco bajo $GITEA_WORK_DIR/repositories. Los objetos LFS van a $GITEA_WORK_DIR/lfs. Los adjuntos, avatares y paquetes usan $GITEA_WORK_DIR/data.
Gitea vs Forgejo vs Alternativas
| Forge | Lenguaje | RAM (reposo) | Actions CI | Registro de paquetes | Licencia |
|---|---|---|---|---|---|
| Gitea | Go | ~120 MB | Sí (act_runner) | Sí (11 tipos) | MIT |
| Forgejo | Go | ~120 MB | Sí (act_runner) | Sí | MIT |
| GitLab CE | Ruby/Go | ~2–4 GB | Sí (nativo) | Sí | MIT |
| Gogs | Go | ~50 MB | No | No | MIT |
| OneDev | Java | ~500 MB | Sí | Limitado | MIT |
| Sourcehut | Python/Go | ~100 MB | Sí (builds.sr.ht) | No | AGPL |
Forgejo es compatible en API con Gitea y los runners son intercambiables. La migración entre ambos es sencilla. GitLab CE es mucho más completo en funcionalidades, pero requiere entre 10 y 20 veces más recursos.
Paso 1: Desplegar con Docker Compose y PostgreSQL
Crea un directorio de proyecto y un docker-compose.yml:
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=changeme
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
db:
image: postgres:16-alpine
container_name: gitea-db
restart: unless-stopped
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=changeme
- POSTGRES_DB=gitea
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
gitea-data:
postgres-data:
docker compose up -d
Abre http://tu-servidor:3000 en un navegador. El instalador web rellena previamente la configuración de la base de datos desde las variables de entorno. Solo configura la URL base, el nombre de usuario administrador, el correo del administrador y la contraseña de administrador, luego haz clic en Instalar. Gitea inicializa el esquema de la base de datos y te redirige al panel en segundos.
Paso 2: Configurar app.ini
Tras la ejecución del instalador, app.ini se encuentra en el volumen Docker bajo gitea/conf/app.ini. Edítalo para reforzar la configuración:
[server]
DOMAIN = git.ejemplo.com
ROOT_URL = https://git.ejemplo.com/
HTTP_PORT = 3000
SSH_DOMAIN = git.ejemplo.com
SSH_PORT = 22
SSH_LISTEN_PORT = 22
DISABLE_SSH = false
LFS_START_SERVER = true
[repository]
DEFAULT_BRANCH = main
ENABLE_PUSH_CREATE_USER = false
DEFAULT_PRIVATE = private
[security]
INSTALL_LOCK = true
SECRET_KEY = <genera-con-openssl-rand-hex-32>
INTERNAL_TOKEN = <genera-con-gitea-generate-secret>
MIN_PASSWORD_LENGTH = 12
PASSWORD_COMPLEXITY = lower,upper,digit,spec
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
REGISTER_EMAIL_CONFIRM = true
ENABLE_NOTIFY_MAIL = true
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
[mailer]
ENABLED = true
SMTP_ADDR = smtp.ejemplo.com
SMTP_PORT = 587
FROM = "Gitea <gitea@ejemplo.com>"
USER = gitea@ejemplo.com
PASSWD = `tu-contraseña-smtp`
Reinicia para aplicar los cambios:
docker compose restart gitea
Paso 3: Gestión de Repositorios
Git LFS
LFS se habilita con LFS_START_SERVER = true en [server]. Los usuarios configuran su cliente local una vez:
git lfs install
git lfs track "*.psd" "*.zip" "*.tar.gz"
Gitea almacena los objetos LFS en $GITEA_WORK_DIR/data/lfs. Haz una copia de seguridad de este directorio por separado de la base de datos.
Mirroring de Repositorios
Los mirrors pull permiten a Gitea clonar y sincronizar periódicamente desde GitHub, GitLab o cualquier remoto Git. En la interfaz web: Nuevo Repositorio → Migrar. Selecciona la fuente y marca Este repositorio será un mirror con el intervalo de sincronización deseado.
Los mirrors push envían cada commit a un remoto automáticamente. Configúralos en Configuración del repositorio → Configuración de mirrors → Push Mirrors.
Ramas Protegidas y Estrategias de Fusión
En Configuración del repositorio → Ramas → Añadir regla de protección de rama:
- Requerir revisiones de pull request — establece aprobaciones mínimas
- Requerir comprobaciones de estado — bloquea la fusión si falla el flujo de trabajo de Actions
- Restringir push — lista blanca de equipos o usuarios
- Estrategias de fusión — habilita/deshabilita commit de fusión, squash y rebase por repositorio
Paso 4: Gitea Actions CI
Gitea Actions es el sistema de CI integrado que usa la misma sintaxis YAML que GitHub Actions.
Registrar un act_runner
Descarga el último binario act_runner desde https://gitea.com/gitea/act_runner/releases. En el panel de administración ve a Administración del sitio → Actions → Runners → Crear nuevo token de runner.
# Registrar el runner
act_runner register \
--instance https://git.ejemplo.com \
--token <token-runner> \
--name mi-runner \
--labels ubuntu-latest:docker://node:20-bullseye
# Iniciar como servicio
act_runner daemon
Ejemplo de Flujo de Trabajo
# .gitea/workflows/build.yml
name: Compilar y Probar
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm test
docker:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Construir imagen Docker
run: docker build -t miapp:${{ gitea.sha }} .
- name: Publicar en registro de Gitea
run: |
docker login git.ejemplo.com -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_TOKEN }}
docker push git.ejemplo.com/miorg/miapp:${{ gitea.sha }}
La mayoría de las acciones del marketplace de GitHub funcionan en Gitea Actions porque act_runner usa el mismo protocolo de runner. Las acciones que referencian variables de contexto github.com necesitan ajustes mínimos (github.* → gitea.*).
Paso 5: Gestión de Usuarios y Autenticación
Cuentas Locales y 2FA
Los usuarios se autoregistran (o los administradores crean cuentas). 2FA mediante TOTP disponible en Configuración de usuario → Seguridad → Autenticación de dos factores. Los administradores del sitio pueden obligar al 2FA en toda la organización desde el panel de administración.
LDAP / Active Directory
Administración del sitio → Identidad y acceso → Fuentes de autenticación → LDAP (via BindDN):
- Host:
ldap.ejemplo.com - Puerto:
389(o636para LDAPS) - Bind DN:
cn=gitea,ou=cuentas-servicio,dc=ejemplo,dc=com - Base de búsqueda de usuarios:
ou=usuarios,dc=ejemplo,dc=com - Filtro de usuario:
(&(objectClass=person)(sAMAccountName=%s)) - Atributo de correo:
mail
Proveedores OAuth2
Añade inicio de sesión con GitHub, GitLab o Google en Fuentes de autenticación → OAuth2:
| Proveedor | Origen del Client ID | Alcance |
|---|---|---|
| GitHub | github.com/settings/developers | read:user,user:email |
| GitLab | gitlab.com/-/profile/applications | read_user |
| console.cloud.google.com | openid email profile |
Los usuarios pueden vincular cuentas OAuth2 externas a cuentas locales existentes desde Configuración de usuario → Seguridad → Cuentas vinculadas.
Paso 6: Proxy Inverso Caddy con TLS
Añade esto a tu Caddyfile:
git.ejemplo.com {
reverse_proxy gitea:3000
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
}
Caddy obtiene certificados de Let’s Encrypt automáticamente en la primera solicitud al dominio.
Organizaciones, Equipos y Permisos
El modelo de permisos de Gitea es similar al de GitHub:
| Rol | Repositorios | Panel de admin | Crear repos |
|---|---|---|---|
| Propietario | Todos en la org | Sí | Sí |
| Admin (equipo) | Repos del equipo | No | Alcance del equipo |
| Escritura (equipo) | Repos del equipo | No | No |
| Lectura (equipo) | Repos del equipo | No | No |
Registro de Paquetes de Gitea
Habilita el registro de paquetes en app.ini:
[packages]
ENABLED = true
Tipos de paquetes soportados: npm, PyPI, Maven, NuGet, Docker/OCI, Composer, Cargo, Conan, Helm, RubyGems y APT Alpine/Debian.
Ejemplo npm
npm config set registry https://git.ejemplo.com/api/packages/miorg/npm/
npm config set //git.ejemplo.com/api/packages/miorg/npm/:_authToken <token>
npm publish
Webhooks y API REST
La API REST v1 de Gitea está documentada en https://git.ejemplo.com/api/swagger. Cada recurso tiene endpoints CRUD completos compatibles con la forma de la API de GitHub/Gitea.
Copia de Seguridad y Restauración
# Dentro del contenedor
docker exec -u git gitea gitea dump -c /data/gitea/conf/app.ini \
-t /tmp --type tar.gz
# Copiar el archivo al exterior
docker cp gitea:/tmp/gitea-dump-*.tar.gz ./copias-seguridad/
Migración desde GitHub, GitLab o Gogs
Administración del sitio → Migraciones soporta importación completa preservando:
- Incidencias y comentarios
- Pull requests
- Etiquetas e hitos
- Lanzamientos y activos de lanzamientos
- Páginas wiki
La migración de Gogs a Gitea es transparente: Gitea lee directamente la base de datos de Gogs y migra el esquema automáticamente.
Errores Comunes y Casos Especiales
Conflicto de puerto SSH — Si el puerto 22 ya lo usa el daemon SSH del host, mapea el SSH de Gitea a un puerto diferente (p. ej., 222:22) y actualiza SSH_PORT en app.ini.
Docker-in-Docker con act_runner — Para flujos de trabajo que construyen imágenes Docker, el runner necesita acceso al socket de Docker. Monta /var/run/docker.sock en el contenedor del runner.
Crecimiento del almacenamiento LFS — Los objetos LFS no se recogen automáticamente. Programa gitea admin repo-lfs-prune periódicamente.
Solución de Problemas
| Problema | Solución |
|---|---|
| La interfaz web devuelve 502 | Comprueba docker logs gitea; verifica las variables de entorno de conexión a la BD |
| El clon por SSH falla | Confirma que SSH_PORT coincide con el mapeo de puertos del host |
| Flujo de Actions en cola para siempre | Verifica que act_runner esté en ejecución y registrado; comprueba que las etiquetas del runner coincidan |
| Push de paquete con error 401 | Genera un token con alcance package; úsalo como contraseña del registro |
| El mirror no sincroniza | Verifica que la URL del mirror sea accesible desde el contenedor |
Resumen
- Gitea funciona con ~120 MB de RAM como binario Go único — mucho más ligero que GitLab CE
- Docker Compose con PostgreSQL es el despliegue de producción recomendado
app.inicontrola cada aspecto: seguridad, mailer, LFS, paquetes y SSH- Gitea Actions usa la sintaxis YAML de GitHub Actions;
act_runnerejecuta trabajos en contenedores Docker - LDAP, OAuth2 (GitHub/GitLab/Google) y TOTP 2FA están integrados
- Los registros de paquetes soportan npm, PyPI, Maven, NuGet, Docker/OCI y más
- El mirroring de repositorios (push y pull) mantiene los repos externos sincronizados automáticamente