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) MIT
GitLab CE Ruby/Go ~2–4 GB Sí (nativo) MIT
Gogs Go ~50 MB No No MIT
OneDev Java ~500 MB 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 (o 636 para 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
Google 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
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.ini controla cada aspecto: seguridad, mailer, LFS, paquetes y SSH
  • Gitea Actions usa la sintaxis YAML de GitHub Actions; act_runner ejecuta 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

Artículos Relacionados