Auto-alojar Gitea en un VPS con Docker Compose
Despliega una instancia Gitea lista para producción con PostgreSQL, passthrough SSH en el puerto 22, CI/CD con Gitea Actions, Git LFS, mirroring de GitHub y copias de seguridad automatizadas. Todo en un solo VPS con Docker Compose.
Gitea es un servicio Git auto-alojado, ligero y escrito en Go. Ofrece pull requests, seguimiento de issues, CI/CD, registros de paquetes y Git LFS en un solo binario que consume unos 150 MB de RAM en reposo. Compara eso con los 4 GB mínimos de GitLab y verás por qué Gitea encaja a la perfección en un VPS.
Esta guía despliega Gitea con Docker Compose y PostgreSQL en un VPS. Configurarás el passthrough SSH para que git clone git@tu-servidor:user/repo.git funcione en el puerto 22, configurarás Gitea Actions con un runner en contenedor, activarás Git LFS, harás mirroring de repositorios de GitHub, configurarás webhooks y automatizarás las copias de seguridad.
¿Qué necesitas antes de instalar Gitea?
Necesitas un VPS con Debian 12 o Ubuntu 24.04 que tenga Docker y Docker Compose v2 instalados, un nombre de dominio apuntando a tu servidor, y un reverse proxy (Nginx o Caddy) con TLS configurado. Esta guía asume que ya has realizado el hardening inicial del servidor: usuario no-root con sudo, autenticación por clave SSH, firewall activado.
| Requisito | Mínimo |
|---|---|
| SO | Debian 12 / Ubuntu 24.04 |
| RAM | 1 GB (2 GB recomendado con runner CI) |
| Docker | 27.x+ con Compose v2 |
| Dominio | Registro A apuntando a la IP del VPS |
| Reverse proxy | Nginx o Caddy con TLS |
¿Cómo desplegar Gitea con Docker Compose y PostgreSQL?
Crea un directorio de proyecto, genera los secretos en un archivo .env y define los servicios Gitea y PostgreSQL en docker-compose.yml. El archivo .env mantiene las credenciales fuera del control de versiones y los archivos compose.
Crear el directorio del proyecto
sudo mkdir -p /opt/gitea
sudo chown $USER:$USER /opt/gitea
cd /opt/gitea
Generar los secretos
openssl rand -base64 32 > /dev/null # test that openssl works
cat > .env << 'ENVFILE'
POSTGRES_USER=gitea
POSTGRES_PASSWORD=REPLACE_ME
POSTGRES_DB=gitea
GITEA_SECRET_KEY=REPLACE_ME
GITEA_INTERNAL_TOKEN=REPLACE_ME
GITEA_LFS_JWT_SECRET=REPLACE_ME
ENVFILE
Ahora reemplaza cada REPLACE_ME por un secreto real:
sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_SECRET_KEY=.*/GITEA_SECRET_KEY=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_INTERNAL_TOKEN=.*/GITEA_INTERNAL_TOKEN=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_LFS_JWT_SECRET=.*/GITEA_LFS_JWT_SECRET=$(openssl rand -base64 32)/" .env
chmod 600 .env
Archivo Docker Compose
# /opt/gitea/docker-compose.yml
services:
gitea:
image: docker.gitea.com/gitea:1.25.5
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=${POSTGRES_DB}
- GITEA__database__USER=${POSTGRES_USER}
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
- GITEA__server__DOMAIN=git.example.com
- GITEA__server__ROOT_URL=https://git.example.com/
- GITEA__server__SSH_DOMAIN=git.example.com
- GITEA__server__SSH_PORT=22
- GITEA__server__LFS_START_SERVER=true
- GITEA__server__LFS_JWT_SECRET=${GITEA_LFS_JWT_SECRET}
- GITEA__service__DISABLE_REGISTRATION=true
- GITEA__service__REQUIRE_SIGNIN_VIEW=false
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
- GITEA__security__INTERNAL_TOKEN=${GITEA_INTERNAL_TOKEN}
- GITEA__actions__ENABLED=true
restart: always
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
depends_on:
db:
condition: service_healthy
networks:
- gitea
db:
image: docker.io/library/postgres:17
container_name: gitea-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
restart: always
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- gitea
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
networks:
gitea:
external: false
volumes:
gitea-data:
postgres-data:
Reemplaza git.example.com por tu dominio real. Decisiones clave:
- PostgreSQL 17 en lugar del 14 obsoleto que la mayoría de guías aún recomiendan
- Volúmenes nombrados (
gitea-data,postgres-data) en lugar de bind mounts para una gestión más limpia - Health check en PostgreSQL para que Gitea espere a que la base de datos esté lista
DISABLE_REGISTRATION=trueporque el registro abierto en una instancia pública invita al abusoACTIONS__ENABLED=truepara activar Gitea Actions desde el principio- Puerto 3000 vinculado a localhost (
127.0.0.1:3000:3000) para que solo sea accesible a través del reverse proxy, no directamente desde internet - Sin mapeo de puerto SSH en el contenedor. El SSH se gestionará a través del passthrough del host (siguiente sección)
Iniciar el stack
docker compose up -d
[+] Running 3/3
✔ Network gitea_gitea Created
✔ Container gitea-db Healthy
✔ Container gitea Started
docker compose ps
NAME IMAGE STATUS PORTS
gitea docker.gitea.com/gitea:1.25.5 Up 2 minutes 127.0.0.1:3000->3000/tcp
gitea-db postgres:17 Up 2 minutes (healthy) 5432/tcp
Configuración del reverse proxy
Añade Gitea a tu configuración Nginx existente:
server {
listen 443 ssl http2;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;
server_tokens off;
client_max_body_size 512M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
client_max_body_size 512M permite pushes grandes, especialmente útil con Git LFS activo. server_tokens off oculta la versión de Nginx en las cabeceras de respuesta, ya que la divulgación de versión ayuda a los atacantes a explotar vulnerabilidades conocidas.
sudo nginx -t && sudo systemctl reload nginx
Crear el usuario administrador
docker exec -it gitea gitea admin user create \
--username admin \
--password "$(openssl rand -base64 16)" \
--email admin@example.com \
--admin \
--must-change-password
New user 'admin' has been successfully created!
Guarda la contraseña generada en un lugar seguro (un gestor de contraseñas, no un post-it). El flag --must-change-password fuerza el cambio de contraseña en el primer inicio de sesión. Una vez dentro, activa la autenticación de dos factores en Settings > Security > Two-Factor Authentication.
¿Cómo configurar el passthrough SSH para Gitea en Docker?
Crea un usuario git en el host con el mismo UID que dentro del contenedor. Añade un bloque AuthorizedKeysCommand en /etc/ssh/sshd_config que llame a docker exec gitea /usr/local/bin/gitea keys. Esto enruta las operaciones SSH de git desde el puerto 22 del host directamente al contenedor, sin exponer un segundo puerto SSH.
Crear el usuario git en el host
El usuario necesita UID 1000 para coincidir con el usuario interno del contenedor:
sudo adduser --system --shell /bin/bash --group --disabled-password --home /home/git --uid 1000 git
Si el UID 1000 ya está en uso por tu usuario habitual, cambia USER_UID/USER_GID en el archivo compose para usar un UID disponible, o ajusta el flag --uid aquí.
Crear el wrapper de shell
El shell del usuario git necesita reenviar los comandos al contenedor:
sudo tee /usr/local/bin/gitea-shell > /dev/null << 'WRAPPER'
#!/bin/sh
/usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
WRAPPER
sudo chmod 755 /usr/local/bin/gitea-shell
sudo usermod -s /usr/local/bin/gitea-shell git
ls -la /usr/local/bin/gitea-shell
-rwxr-xr-x 1 root root 99 Mar 20 10:00 /usr/local/bin/gitea-shell
Añadir el usuario git al grupo docker
sudo usermod -aG docker git
Esto da al usuario git permiso para ejecutar docker exec. En un servidor dedicado a Gitea, es aceptable. En un host compartido, considera usar reglas sudo limitadas al comando docker exec específico.
Configurar sshd
Añade este bloque al final de /etc/ssh/sshd_config:
# Gitea SSH passthrough
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /etc/gitea/app.ini -e git -u %u -t %t -k %k
El AuthorizedKeysCommand pregunta al contenedor Gitea si la clave pública presentada por el cliente SSH pertenece a un usuario Gitea registrado. Si coincide, SSH concede el acceso. El bloque Match User git restringe esto al usuario git únicamente, dejando tu acceso SSH normal intacto.
sudo sshd -t
Sin salida significa que la configuración es válida. Si ves errores, revisa el bloque Match en busca de erratas.
sudo systemctl restart sshd
Probar el acceso SSH
Añade tu clave pública SSH a tu cuenta Gitea a través de la interfaz web (Settings > SSH/GPG Keys). Luego desde tu máquina local:
ssh -T git@git.example.com
Hi there, admin! You've successfully authenticated with the key named "my-laptop", but Gitea does not provide shell access.
Ya puedes clonar, hacer push y pull por SSH en el puerto 22:
git clone git@git.example.com:admin/my-repo.git
¿Cómo activar y configurar Gitea Actions para CI/CD?
Gitea Actions es un sistema CI/CD integrado cuya sintaxis es compatible con GitHub Actions. Se activa con una variable de entorno (ya definida en nuestro archivo compose), se despliega un runner como servicio de Docker Compose y se escriben archivos YAML de workflow en los repositorios.
¿Cómo registrar un act_runner con Docker Compose?
Primero, genera un token de registro del runner desde el panel de administración de Gitea:
docker exec -it gitea gitea actions generate-runner-token
NxxxxxxxxxxxxxxxxxxxxxxxN
Copia este token. Añádelo a tu archivo .env:
echo "GITEA_RUNNER_TOKEN=YOUR_TOKEN_HERE" >> /opt/gitea/.env
chmod 600 /opt/gitea/.env
Ahora añade el servicio runner a tu docker-compose.yml:
runner:
image: docker.io/gitea/act_runner:0.3.0
container_name: gitea-runner
environment:
- GITEA_INSTANCE_URL=http://gitea:3000
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN}
- GITEA_RUNNER_NAME=vps-runner
volumes:
- runner-data:/data
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- gitea
restart: always
networks:
- gitea
Añade runner-data: a la sección volumes: al final del archivo. Luego inicia el runner:
docker compose up -d runner
docker compose logs runner --tail 20
level=info msg="Starting runner daemon"
level=info msg="Runner registered successfully"
El runner monta el socket Docker (/var/run/docker.sock) para poder crear contenedores en cada job. Es una práctica estándar en runners CI, pero significa que los jobs pueden acceder al demonio Docker del host. Para entornos aislados, considera ejecutar el runner con Docker-in-Docker (DinD).
| Variable de entorno | Propósito |
|---|---|
GITEA_INSTANCE_URL |
URL interna donde el runner contacta a Gitea (usa el nombre del servicio, no el dominio público) |
GITEA_RUNNER_REGISTRATION_TOKEN |
Token de un solo uso de gitea actions generate-runner-token |
GITEA_RUNNER_NAME |
Nombre visible en el panel de administración de Gitea |
¿Cómo es un workflow de Gitea Actions?
Gitea Actions usa la misma sintaxis YAML que GitHub Actions, con algunas diferencias. Crea .gitea/workflows/build.yml en tu repositorio:
name: Build and Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh -o StrictHostKeyChecking=accept-new user@production "cd /app && git pull && systemctl restart myapp"
Almacena el secreto DEPLOY_KEY en los ajustes de tu repositorio en Settings > Actions > Secrets.
| Característica | Gitea Actions | GitHub Actions |
|---|---|---|
| Directorio de workflows | .gitea/workflows/ |
.github/workflows/ |
uses: actions/* |
Funciona (se obtiene de GitHub por defecto) | Nativo |
| Servicios en contenedor | Soportado | Soportado |
| Builds matriciales | Soportado | Soportado |
| Workflows reutilizables | Soportado desde Gitea 1.24 | Soportado |
| Actions del Marketplace | La mayoría funcionan, algunas necesitan adaptación | Nativo |
¿Cómo activar Git LFS en Gitea?
Git Large File Storage permite rastrear archivos binarios (imágenes, modelos, datasets) sin inflar tu repositorio. Gitea tiene soporte LFS integrado. Ya lo activamos con LFS_START_SERVER=true en el archivo compose. Los datos LFS se almacenan en el volumen gitea-data por defecto.
Para configurar la ruta de almacenamiento explícitamente o aumentar los límites, edita la configuración de Gitea:
docker exec -i gitea sh -c 'cat >> /data/gitea/conf/app.ini' << 'EOF'
[lfs]
PATH = /data/git/lfs
EOF
Reinicia Gitea para aplicar los cambios:
docker compose restart gitea
En el lado del cliente, instala git-lfs y rastrea los tipos de archivo:
git lfs install
git lfs track "*.bin" "*.h5" "*.onnx"
git add .gitattributes
git commit -m "Track model files with LFS"
git push
Los archivos LFS se almacenan en el servidor en la ruta PATH configurada dentro del contenedor. Para despliegues grandes, puedes configurar almacenamiento compatible con S3 en app.ini bajo la sección [lfs].
¿Cómo hacer mirroring de repositorios de GitHub a Gitea?
El pull mirroring crea una copia de solo lectura de un repositorio de GitHub en tu instancia Gitea. Se sincroniza automáticamente según un calendario configurable. Útil para copias de seguridad, para tener una caché local detrás de tu runner CI o para reducir la dependencia de GitHub.
En la interfaz web de Gitea:
- Haz clic en + > New Migration
- Selecciona GitHub como origen
- Introduce la URL del repositorio (ej.:
https://github.com/owner/repo.git) - Para repos privados, introduce tu nombre de usuario de GitHub y un personal access token como contraseña
- Marca This repository will be a mirror
- Define el intervalo de mirroring (por defecto: 8 horas)
- Haz clic en Migrate Repository
El mirror sincroniza ramas, tags y releases. Las issues, pull requests y wikis también se pueden migrar durante la importación inicial, pero no se sincronizan de forma continua.
Para hacer mirroring a través de la API:
curl -X POST "https://git.example.com/api/v1/repos/migrate" \
-H "Authorization: token YOUR_GITEA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"clone_addr": "https://github.com/owner/repo.git",
"mirror": true,
"mirror_interval": "8h",
"repo_name": "repo-mirror",
"repo_owner": "admin",
"service": "github"
}'
¿Cómo configurar webhooks para el despliegue?
Los webhooks envían peticiones HTTP POST a una URL cuando ocurren eventos en un repositorio. Son una forma sencilla de activar despliegues, notificaciones o sistemas CI externos.
En tu repositorio, ve a Settings > Webhooks > Add Webhook > Gitea:
- Target URL:
https://deploy.example.com/hooks/gitea - HTTP Method: POST
- Content Type: application/json
- Secret: genera con
openssl rand -hex 32 - Trigger events: Push events (o personaliza)
En el extremo receptor, tu script de despliegue debe verificar la firma del webhook:
# The webhook sends a X-Gitea-Signature header
# Verify it with the shared secret before acting on the payload
EXPECTED=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')
if [ "$SIGNATURE" != "$EXPECTED" ]; then
echo "Invalid signature"
exit 1
fi
Un receptor de webhook mínimo usando una herramienta ligera como webhook:
[
{
"id": "deploy",
"execute-command": "/opt/deploy.sh",
"command-working-directory": "/opt/app",
"trigger-rule": {
"match": {
"type": "payload-hmac-sha256",
"secret": "your-webhook-secret",
"parameter": {
"source": "header",
"name": "X-Gitea-Signature"
}
}
}
}
]
¿Cómo hacer copias de seguridad de una instancia Gitea?
Gitea incluye un comando gitea dump que empaqueta los repositorios, la base de datos, la configuración y los objetos LFS en un único archivo zip. Para PostgreSQL, también conviene hacer un pg_dump separado para recuperación a un punto en el tiempo.
Copia de seguridad manual
docker exec -it gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini --file /data/gitea-backup.zip
docker cp gitea:/data/gitea-backup.zip /opt/gitea/backups/
El dump incluye:
| Contenido | Incluido en el dump |
|---|---|
| Repositorios Git | Sí |
| Base de datos (SQLite o dump) | Sí |
| Configuración (app.ini) | Sí |
| Objetos LFS | Sí |
| Adjuntos, avatares | Sí |
| Paquetes | No (respaldar por separado) |
Para PostgreSQL, ejecuta también:
docker exec gitea-db pg_dump -U gitea gitea | gzip > /opt/gitea/backups/gitea-db-$(date +%Y%m%d).sql.gz
Copia de seguridad automatizada con cron
sudo mkdir -p /opt/gitea/backups
sudo chown root:root /opt/gitea/backups
sudo chmod 700 /opt/gitea/backups
Crea el script de copia de seguridad:
sudo tee /opt/gitea/backup.sh > /dev/null << 'BACKUP'
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/gitea/backups"
DATE=$(date +%Y%m%d-%H%M)
# Gitea dump
docker exec gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini --file /data/gitea-backup.zip --quiet
docker cp gitea:/data/gitea-backup.zip "$BACKUP_DIR/gitea-dump-$DATE.zip"
docker exec gitea rm /data/gitea-backup.zip
# PostgreSQL dump
docker exec gitea-db pg_dump -U gitea gitea | gzip > "$BACKUP_DIR/gitea-db-$DATE.sql.gz"
# Keep last 7 daily backups
find "$BACKUP_DIR" -name "gitea-*" -mtime +7 -delete
echo "Backup completed: $DATE"
BACKUP
sudo chmod 700 /opt/gitea/backup.sh
ls -la /opt/gitea/backup.sh
-rwx------ 1 root root 523 Mar 20 10:00 /opt/gitea/backup.sh
Prográmalo a diario a las 3 de la mañana:
echo "0 3 * * * root /opt/gitea/backup.sh >> /var/log/gitea-backup.log 2>&1" | sudo tee /etc/cron.d/gitea-backup
sudo chmod 644 /etc/cron.d/gitea-backup
Ejecuta el script una vez manualmente:
sudo /opt/gitea/backup.sh
Backup completed: 20260320-1030
ls -lh /opt/gitea/backups/
-rw-r--r-- 1 root root 2.3M Mar 20 10:30 gitea-dump-20260320-1030.zip
-rw-r--r-- 1 root root 48K Mar 20 10:30 gitea-db-20260320-1030.sql.gz
Copia las copias de seguridad fuera del servidor. Una copia de seguridad local que muere con el disco no es una copia de seguridad.
¿Cómo actualizar Gitea de forma segura?
Descarga la nueva imagen, recrea el contenedor y deja que Gitea gestione las migraciones de base de datos automáticamente. Fija las versiones de imagen para que las actualizaciones sean intencionadas, no accidentales.
cd /opt/gitea
# Back up first
sudo /opt/gitea/backup.sh
# Update the image tag in docker-compose.yml, then:
docker compose pull gitea
docker compose up -d gitea
docker compose logs gitea --tail 30
Observa los mensajes de migración:
2026/03/20 10:35:00 ...les/migration.go:67:Migrate() [I] Migration completed
Después de confirmar que Gitea arranca correctamente, actualiza el runner si hay una nueva versión disponible:
docker compose pull runner
docker compose up -d runner
¿Cuál es la diferencia entre Gitea y Forgejo?
Forgejo se bifurcó de Gitea a finales de 2022, después de que una empresa con ánimo de lucro (Gitea Ltd.) tomara el control del proyecto Gitea. Forgejo está gobernado por Codeberg e.V., una asociación sin ánimo de lucro alemana. A principios de 2026, Forgejo es un hard fork con bases de código divergentes. Ambos funcionan con una configuración Docker similar, pero la migración entre ellos ya no es transparente.
| Gitea | Forgejo | |
|---|---|---|
| Gobernanza | Gitea Ltd. (con ánimo de lucro) | Codeberg e.V. (sin ánimo de lucro) |
| Licencia | MIT | GPL-3.0+ (desde Forgejo v9.0) |
| Imagen Docker | docker.gitea.com/gitea |
codeberg.org/forgejo/forgejo |
| Soporte Actions | Sí (act_runner) | Sí (runner compatible) |
| Compatibilidad API | Compatible con GitHub | Compatible con GitHub |
| Funciones únicas | Gitea Enterprise, servidor MCP | Federación (ForgeFed), herramientas de moderación |
Si quieres un proyecto gobernado por la comunidad con licencia copyleft, elige Forgejo. Si quieres el proyecto original con respaldo comercial, elige Gitea. La configuración Docker Compose de esta guía funciona para ambos con cambios mínimos (intercambia la imagen, ajusta las rutas).
Si empiezas con Gitea y quieres cambiar después: exporta tus datos con gitea dump, instala Forgejo e importa. Prueba a fondo. Las bases de código han divergido lo suficiente como para que algunos esquemas de base de datos difieran.
¿Cuánta RAM y CPU necesita Gitea?
Una instancia Gitea con PostgreSQL usa unos 150-250 MB de RAM en reposo. Con uso activo de 5 a 10 usuarios y runners CI, espera 300-500 MB en total. Eso es unas 10 veces más ligero que una instancia GitLab, que necesita 4 GB como mínimo.
Estas cifras provienen de una instancia Gitea en producción en un VPS de Virtua Cloud (4 vCPU, 8 GB de RAM):
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
NAME CPU % MEM USAGE / LIMIT
gitea 0.15% 148.2MiB / 7.77GiB
gitea-db 0.08% 45.3MiB / 7.77GiB
gitea-runner 0.02% 32.1MiB / 7.77GiB
| Escenario | RAM (stack completo) | CPU |
|---|---|---|
| Reposo, pocos repos | ~230 MB | < 1 % |
| Activo, 5-10 usuarios | ~400 MB | 2-5 % |
| Build CI en curso | ~600 MB (picos durante los builds) | 20-50 % por job |
| Equivalente GitLab | 4.000+ MB | 10 %+ en reposo |
Gitea funciona cómodamente en un VPS de 2 GB. Con runners CI, 4 GB te dan margen para builds simultáneos.
Solución de problemas
Conexión SSH rechazada:
Comprueba que el usuario git existe, que sshd_config tiene el bloque Match y que sshd se ha reiniciado. Revisa los logs:
journalctl -u sshd -f
El runner no recoge los jobs: Confirma que el runner está registrado en el panel de administración (Site Administration > Actions > Runners). Revisa los logs del runner:
docker compose logs runner --tail 50
Errores de conexión a la base de datos al arrancar: El health check debería evitar esto, pero si Gitea arranca antes de que PostgreSQL esté listo:
docker compose restart gitea
El push LFS falla con error 413:
Aumenta client_max_body_size en tu configuración Nginx. 512M suele ser suficiente, pero ajústalo según tus archivos más grandes.
Logs de Gitea:
docker compose logs gitea --tail 100
O sigue en directo:
docker compose logs gitea -f
Copyright 2026 Virtua.Cloud. Todos los derechos reservados. Este contenido es una obra original del equipo de Virtua.Cloud. La reproducción, republicación o redistribución sin permiso escrito está prohibida.
¿Listo para probarlo?
Despliega tu propio servidor en segundos. Linux, Windows o FreeBSD.
Ver planes VPS