
En resumen. Una instalación de Gitea por defecto deja abierto el instalador web, permite el registro libre y crea los repositorios como públicos. Esta checklist cubre los cinco ajustes de app.ini que cierran esos huecos (INSTALL_LOCK, DISABLE_REGISTRATION, REQUIRE_SIGNIN_VIEW, RUN_USER, llaves secretas), además de 2FA obligatoria (Gitea 1.24+), alcance de los tokens de acceso, repositorios privados por defecto, protección de ramas y una configuración blindada de proxy inverso Nginx con los headers que Gitea necesita.
Antes de empezar: la base de seguridad del VPS
El hardening de Gitea se apoya en un host ya asegurado. Antes de recorrer los pasos de abajo, asegúrate de que tu VPS ya tenga:
- Autenticación con llaves SSH y el login por contraseña deshabilitado. La guía de autenticación con llaves SSH te muestra cómo configurarlo.
- El firewall de Contabo activado. Cada VPS y VDS de Contabo incluye un firewall gratuito a nivel de red que administras desde el Customer Control Panel, sin instalar nada. El artículo de autoayuda te guía paso a paso.
- Fail2Ban instalado y configurado. La guía de Fail2Ban te muestra cómo bloquear intentos de login repetidos a nivel de red.
- Un usuario sudo sin privilegios de root ejecutando el servicio. La guía del usuario sudo explica la forma correcta de provisionar una cuenta de sistema
git. - Parcheo regular del host. La guía de parcheo del VPS te muestra un enfoque automatizado para mantener los paquetes de tu sistema operativo al día.
Cada punto es una entrada de una sola línea; los tutoriales enlazados cubren el procedimiento completo. No te saltes esta base: el hardening específico de Gitea no sirve de nada contra un atacante que ya tiene acceso SSH por una configuración débil del host.
Hardening específico de Gitea (la parte que nada más cubre)
Estos puntos son exclusivos de Gitea. No aparecen en ninguna guía de sistema operativo, y una instalación de Gitea por defecto no aplica la mayoría. Recorre cada sección; todos los cambios van en app.ini, que en la mayoría de las instalaciones por paquete de Linux vive en /etc/gitea/app.ini, o en custom/conf/app.ini en una instalación por binario.
Blindar la configuración de app.ini
Cinco ajustes de app.ini son exclusivos de Gitea y no los cubre ninguna guía de hardening del sistema operativo. Configúralos todos antes de exponer tu instancia a la red:
INSTALL_LOCK = truecierra el endpoint web /install. El instalador web lo activa solo al terminar, pero verifica que esté presente en app.ini antes de salir a producción — si falta o quedó en false por cualquier razón, cualquiera que llegue al endpoint puede reconfigurar tu instancia desde cero.REQUIRE_SIGNIN_VIEW = trueobliga a iniciar sesión antes de ver cualquier repositorio, issue o perfil de usuario. Esencial para instancias privadas de equipo.RUN_USER = gitle indica a Gitea que corra bajo una cuenta de sistema dedicada sin privilegios de root, no como root. Revisa tu unit de systemd y corrige esto primero si está mal.SECRET_KEYeINTERNAL_TOKENlos genera automáticamente el instalador. Verifica que cada uno sea una cadena larga y aleatoria, no un valor en blanco o un placeholder. Rótalos si no estás seguro de su origen.
Después de cualquier cambio en app.ini, reinicia y verifica:
sudo systemctl restart gitea && sudo systemctl status giteaDeshabilitar el registro abierto y controlar el alta
Configura DISABLE_REGISTRATION = true en la sección [service] de app.ini. Esto impide que cualquiera cree su propia cuenta; los usuarios nuevos los tiene que provisionar un administrador desde Site Administration > Users o con el comando de CLI gitea admin user create. Si necesitas inicio de sesión externo con OAuth o LDAP, puedes configurar esas fuentes para cuentas ya existentes: crea primero el usuario en Gitea y luego vincula la identidad de OAuth desde su perfil.
Forzar 2FA y autenticación fuerte
Gitea soporta 2FA basada en TOTP de forma nativa. Los usuarios la activan desde Settings > Security > Two-Factor Authentication con cualquier app compatible con RFC 6238 (Google Authenticator, Authy, 1Password y similares).
Para forzar la 2FA en todos los usuarios, agrega lo siguiente a la sección [service] de app.ini (requiere Gitea 1.24 o posterior):
[service]
TWO_FACTOR_AUTH = enforcedTras reiniciar, cualquier usuario que no haya activado 2FA será redirigido a la página de activación en su siguiente inicio de sesión y quedará bloqueado de los repositorios hasta completarla. Gitea Enterprise tiene su propio flag para esto (ENFORCE_TWO_FACTOR_AUTH en [security]), pero en Gitea community 1.24+, TWO_FACTOR_AUTH = enforced cubre el mismo terreno.
Higiene de tokens de acceso y llaves de despliegue
Dale a cada token de acceso personal solo los permisos mínimos que necesita. Gitea soporta alcances de token detallados (por ejemplo, read:repository o write:package) en Settings > Applications. Ponle fecha de expiración a cada token; los que nunca expiran se acumulan en silencio. Para acceso de solo lectura desde CI/CD, crea un token dedicado con alcance únicamente a read:repository en lugar de usar un token personal con acceso total. Rota cualquier token de inmediato si sospechas que quedó expuesto.
Control de acceso a repositorios y organizaciones
Para que todos los repositorios nuevos sean privados por defecto, configura lo siguiente en la sección [repository] de app.ini:
[repository]
DEFAULT_PRIVATE = trueEsto deja la casilla «Private» ya marcada cada vez que un usuario crea un repositorio nuevo. Si quieres ir más allá e impedir que los repositorios se hagan públicos alguna vez, configura FORCE_PRIVATE = true en su lugar: los administradores todavía pueden cambiar la visibilidad, pero los usuarios normales no. Para el control de acceso, usa organizaciones y equipos en lugar de permisos directos por usuario, y asigna el rol mínimo necesario: Reader, Writer u Owner. Activa la protección de ramas en los repositorios que reciben despliegues a producción: ve a Repository Settings > Branches, agrega una regla para tu rama por defecto, exige al menos una aprobación de revisión y deshabilita el force-push.
Hardening del proxy inverso y TLS para Gitea
Gitea puede manejar TLS directamente, pero el enfoque recomendado es poner un proxy inverso por delante y terminar TLS ahí. Esta sección cubre Nginx. En este esquema Gitea no necesita saber nada de TLS; solo necesita conocer su URL pública.
app.ini – ajustes requeridos para cualquier esquema con proxy inverso
Configura estos en las secciones [server] y [session] antes de levantar el proxy:
[server]
ROOT_URL = https://git.example.com/
[session]
COOKIE_SECURE = trueROOT_URL tiene que coincidir exactamente con la URL pública HTTPS. Una discrepancia rompe las URLs de clonado, los redirects de OAuth y los payloads de webhooks. COOKIE_SECURE = true marca las cookies de sesión como Secure para que los navegadores solo las envíen por HTTPS; sin esto, las cookies emitidas a través de un proxy HTTPS se pueden reenviar por HTTP.
Bloque server de Nginx
Los headers de proxy de abajo los requiere Gitea, no son opcionales. Sin X-Forwarded-Proto ni X-Real-IP, Gitea no puede ver la IP real del cliente ni determinar el esquema de la petición, lo que rompe el rate limiting por IP, los logs de auditoría y los flujos de OAuth.
server {
listen 443 ssl;
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;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy strict-origin-when-cross-origin;
# Hide Gitea version
proxy_hide_header X-Gitea-Version;
# Rate-limit the login and sign-up routes
limit_req zone=gitea_auth burst=5 nodelay;
location / {
client_max_body_size 512M;
proxy_pass http://127.0.0.1:3000;
# Required headers — do not remove
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;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
}
}
server {
listen 80;
server_name git.example.com;
return 301 https://$host$request_uri;
}Define la zona de rate limiting en el bloque http de nginx.conf (fuera del bloque server):
limit_req_zone $binary_remote_addr zone=gitea_auth:10m rate=10r/m;client_max_body_size 512M coincide con el valor de la documentación de Gitea. Sin él, los pushes de repositorio y las subidas de archivos que superan el límite por defecto de Nginx (1 MB) devuelven un error 413.
Emite los certificados TLS con Let’s Encrypt y Certbot; consulta la guía ¿Cómo instalo un certificado SSL en mi servidor Linux con Let’s Encrypt? para el procedimiento completo.
Después de cualquier cambio en Nginx, haz reload en lugar de restart para no cortar las conexiones activas:
sudo nginx -t && sudo systemctl reload nginxRespaldos y disciplina de actualización
Respaldar Gitea
Gitea trae un subcomando dump que archiva repositorios, base de datos, configuración y adjuntos en un solo archivo zip:
sudo systemctl stop gitea
sudo -u git gitea dump -c /etc/gitea/app.ini --file /backups/gitea-$(date +%Y%m%d).zip
sudo systemctl start giteaEl dump incluye la base de datos SQLite o una exportación SQL plana. Para PostgreSQL o MySQL, toma un dump de base de datos por separado antes de correr gitea dump:
# PostgreSQL
pg_dump -U gitea gitea > /backups/gitea-db-$(date +%Y%m%d).sql
# MySQL / MariaDB
mysqldump -u gitea -p gitea > /backups/gitea-db-$(date +%Y%m%d).sqlGuarda los respaldos fuera del servidor. Contabo ofrece dos opciones que se complementan:
- Auto Backup, el complemento – un complemento de pago para Cloud VPS que crea respaldos automáticos diarios de todo el disco de tu VPS, guardados fuera del servidor en un sistema de almacenamiento aparte de Contabo hasta por 10 días. Esto te da un punto de restauración completo del sistema, útil para revertir una actualización fallida de Gitea o recuperarte de un host comprometido.
- Descarga manual con rclone – el archivo de
gitea dumpes una exportación portátil, específica de Gitea y bajo tu control. Sincronízalo con Object Storage de Contabo usando rclone para retención de largo plazo más allá de los 10 días. La guía de respaldo con rclone cubre el procedimiento completo.
Para una instancia de Gitea en producción, vale la pena correr ambos: Auto Backup para recuperación rápida de todo el sistema, gitea dump más Object Storage para archivado de largo plazo y portabilidad.
Mantenerte al día
Gitea publica versiones de parche con frecuencia, y las correcciones de seguridad viajan en las releases de parche. Suscríbete al feed de releases de Gitea en https://github.com/go-gitea/gitea/releases.atom para recibir avisos. Antes de cualquier actualización, toma un gitea dump completo y un snapshot de la base de datos; las migraciones de base de datos de Gitea corren automáticamente al arrancar y no son reversibles sin un respaldo. Si tienes un despliegue de equipo, prueba primero las actualizaciones en una instancia de staging. Estar una sola versión de parche atrás es aceptable; estar varias versiones menores atrás no.
Detectar un compromiso
Gitea genera logs de acceso, logs de push y logs de auditoría de administración. Es el primer lugar donde revisar si sospechas de un acceso no autorizado. La guía de indicadores de que tu instancia fue comprometida trae la lista completa de señales que vigilar y los pasos de respuesta. Como base, vigila cuentas de usuario nuevas inesperadas, llaves SSH agregadas a cuentas existentes y repositorios que eran privados y ahora son públicos.
Por qué correr un Gitea blindado en Contabo
Alojar Gitea en un VPS de Contabo te da recursos de sobra. Tus CI runners, tus procesos de Git y tu base de datos reciben el CPU y la RAM que pagaste, sin competir con otros inquilinos.
Para equipos sujetos al GDPR o a políticas internas de soberanía de datos, la residencia de datos en la UE importa. Elegir un centro de datos en la UE mantiene el código fuente y el historial de commits bajo jurisdicción de la UE, en una infraestructura 100 % conforme al GDPR.
Los snapshots merecen una mención especial en el contexto de las actualizaciones de Gitea. Antes de correr una actualización mayor, toma un snapshot de todo el VPS desde el Customer Control Panel. Si la migración falla o introduce una regresión, reviertes en minutos en lugar de restaurar desde un respaldo de base de datos.
Los planes de VPS de entrada arrancan en menos de 7 dólares al mes y te dan margen suficiente para correr Gitea junto a una base de datos PostgreSQL y un proxy Nginx sin presión de recursos.
FAQ: seguridad de Gitea
Agrega DISABLE_REGISTRATION = true bajo [service] en app.ini y reinicia Gitea. Las cuentas nuevas tendrá que crearlas un administrador desde Site Administration > Users o con gitea admin user create. Ten en cuenta que esto también bloquea la creación de cuentas vía OAuth: crea primero los usuarios manualmente y vincula las identidades de OAuth desde su perfil.
Sí. Los usuarios la activan desde Settings > Security > Two-Factor Authentication con cualquier app TOTP. Para forzarla en todo el sitio, agrega TWO_FACTOR_AUTH = enforced bajo [service] en app.ini y reinicia (requiere Gitea 1.24+). Gitea Enterprise tiene un flag aparte para esto. El acceso a la API vía tokens personales no queda protegido por 2FA sin importar la edición.
Configura ROOT_URL = https://git.example.com/ en [server] y COOKIE_SECURE = true en [session] en app.ini. Apunta Nginx a http://127.0.0.1:3000 y pasa los headers requeridos (Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto). Emite un certificado con Certbot: consulta la guía ¿Cómo instalo un certificado SSL en mi servidor Linux con Let’s Encrypt? para el procedimiento completo.
Corre gitea dump -c /etc/gitea/app.ini para producir un archivo zip con repositorios, configuración, base de datos y adjuntos. Para PostgreSQL o MySQL, toma antes un pg_dump o mysqldump por separado. Guarda los archivos fuera del servidor: Contabo Auto Backup cubre snapshots diarios de todo el disco, o sincroniza el dump con Object Storage usando rclone para retención de largo plazo.