Git no necesita ningún servicio especial para funcionar como servidor: basta con un repositorio "bare" en una máquina accesible por SSH. En este tutorial montarás un servidor Git privado en Ubuntu 24.04 con un usuario git dedicado, restringido a git-shell para que solo pueda ejecutar operaciones de Git, acceso mediante claves SSH y una copia de seguridad diaria de los repositorios. Es la opción más ligera y segura para un equipo pequeño; al final verás cuándo conviene pasar a una plataforma web como Gitea o Forgejo.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Sirve cualquier tamaño: Git sobre SSH apenas consume recursos.
- Un usuario no root con privilegios
sudoy acceso SSH al servidor. - En tu equipo local, Git instalado y un par de claves SSH. Si no tienes una, créala con
ssh-keygen -t ed25519. - El puerto 22 (SSH) accesible desde los equipos que usarán el servidor.
A lo largo de la guía, sustituye your_server_ip por la IP o el nombre DNS de tu servidor.
Paso 1: Instalar Git en el servidor
Conéctate al servidor, actualiza el índice de paquetes e instala Git:
sudo apt update
sudo apt install git
Comprueba la versión instalada:
git --version
git version 2.43.0
Si usas UFW, asegúrate de que SSH está permitido antes de activar el cortafuegos, o te quedarás sin acceso:
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Paso 2: Crear el usuario git con git-shell
Todos los desarrolladores se conectarán como el mismo usuario git, cada uno con su propia clave. Para que ese usuario no pueda abrir una shell normal, se le asigna git-shell, una shell restringida que solo acepta los comandos que usa Git (git-receive-pack, git-upload-pack y git-upload-archive).
Comprueba dónde está git-shell:
which git-shell
/usr/bin/git-shell
Crea el usuario con esa shell y su directorio personal:
sudo useradd --create-home --shell /usr/bin/git-shell git
El usuario no tiene contraseña, así que solo podrá entrar con clave SSH. Compruébalo:
getent passwd git
git:x:1001:1001::/home/git:/usr/bin/git-shell
Paso 3: Autorizar las claves SSH de los desarrolladores
Crea el directorio .ssh del usuario git con los permisos que exige OpenSSH:
sudo install -d -m 700 -o git -g git /home/git/.ssh
sudo install -m 600 -o git -g git /dev/null /home/git/.ssh/authorized_keys
En tu equipo local, muestra tu clave pública y cópiala:
cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... ana@portatil
En el servidor, edita el archivo de claves autorizadas:
sudo nano /home/git/.ssh/authorized_keys
Añade una línea por desarrollador, anteponiendo la opción restrict a cada clave. restrict desactiva el reenvío de puertos, de agente y X11 y la asignación de terminal, que Git no necesita:
restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... ana@portatil
restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... luis@sobremesa
Para revocar el acceso de alguien, basta con borrar su línea.
Desde tu equipo local, prueba la conexión:
ssh git@your_server_ip
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to your_server_ip closed.
Ese mensaje confirma que la autenticación con clave funciona y que git-shell impide abrir una sesión interactiva. Si en cambio ves Permission denied (publickey), revisa la sección de solución de problemas.
Paso 4: Crear un repositorio bare
Un repositorio bare contiene solo la base de datos de Git, sin copia de trabajo, y es el formato adecuado para recibir push. Guarda los repositorios en /srv/git, propiedad del usuario git:
sudo install -d -m 750 -o git -g git /srv/git
Crea el primer repositorio con la rama inicial main. El comando se ejecuta como git para que los archivos tengan el propietario correcto:
sudo -u git git init --bare --initial-branch=main /srv/git/miproyecto.git
Initialized empty Git repository in /srv/git/miproyecto.git/
Repite este comando por cada repositorio nuevo. La terminación .git es una convención para los repositorios bare.
Paso 5: Clonar y subir cambios desde tu equipo
En tu equipo local, clona el repositorio usando la ruta absoluta en el servidor:
git clone git@your_server_ip:/srv/git/miproyecto.git
Cloning into 'miproyecto'...
warning: You appear to have cloned an empty repository.
Crea un primer commit y súbelo:
cd miproyecto
echo "# Mi proyecto" > README.md
git add README.md
git commit -m "Primer commit"
git push origin main
To your_server_ip:/srv/git/miproyecto.git
* [new branch] main -> main
Si ya tienes un proyecto local, en lugar de clonar añade el servidor como remoto y sube la rama:
git remote add origin git@your_server_ip:/srv/git/miproyecto.git
git push -u origin main
Para comprobar que el commit ha llegado, lista las referencias del remoto:
git ls-remote origin
3f9c2a1e8b7d6c5f4a3b2c1d0e9f8a7b6c5d4e3f HEAD
3f9c2a1e8b7d6c5f4a3b2c1d0e9f8a7b6c5d4e3f refs/heads/main
Acortar la URL de los repositorios (opcional)
Para escribir miservidor:miproyecto.git en lugar de la IP y la ruta completa, añade un alias en ~/.ssh/config de tu equipo local:
nano ~/.ssh/config
Host miservidor
HostName your_server_ip
User git
IdentityFile ~/.ssh/id_ed25519
La ruta del repositorio sigue siendo absoluta, así que el clon queda así:
git clone miservidor:/srv/git/miproyecto.git
Paso 6: Programar copias de seguridad de los repositorios
Los repositorios están en un único directorio, así que un archivo comprimido diario con rotación es suficiente como copia local. Guárdala después fuera del servidor (almacenamiento de objetos, otro servidor) para protegerte de la pérdida del disco.
Crea el script de copia:
sudo nano /usr/local/bin/git-backup
#!/usr/bin/env bash
set -euo pipefail
src="/srv/git"
dest="/var/backups/git"
keep_days=14
mkdir -p "$dest"
tar -czf "$dest/git-$(date +%F).tar.gz" -C "$(dirname "$src")" "$(basename "$src")"
find "$dest" -name 'git-*.tar.gz' -mtime +"$keep_days" -delete
Hazlo ejecutable y pruébalo:
sudo chmod 755 /usr/local/bin/git-backup
sudo /usr/local/bin/git-backup
ls -lh /var/backups/git/
-rw-r--r-- 1 root root 1.2K Sep 25 10:40 git-2026-09-25.tar.gz
Programa la ejecución diaria a las 03:30 con un archivo en /etc/cron.d:
sudo nano /etc/cron.d/git-backup
30 3 * * * root /usr/local/bin/git-backup
Para restaurar, extrae el archivo en /srv y devuelve la propiedad al usuario git:
sudo tar -xzf /var/backups/git/git-2026-09-25.tar.gz -C /srv
sudo chown -R git:git /srv/git
Solución de problemas
Permission denied (publickey). El servidor no acepta tu clave. Comprueba los permisos: /home/git/.ssh debe ser 700, authorized_keys 600 y ambos propiedad de git. Revisa también que la clave está en una sola línea, sin saltos. El motivo exacto aparece en el log de SSH del servidor:
sudo journalctl -u ssh -n 20 --no-pager
fatal: '/srv/git/miproyecto.git' does not appear to be a git repository. La ruta no existe o está mal escrita. Recuerda que es la ruta absoluta en el servidor e incluye la terminación .git.
error: insufficient permission for adding an object to repository database. Hay archivos del repositorio que no pertenecen al usuario git, normalmente porque se creó o modificó con sudo sin -u git. Corrige la propiedad:
sudo chown -R git:git /srv/git
fatal: detected dubious ownership in repository al ejecutar comandos en el servidor. Aparece si ejecutas Git sobre /srv/git con un usuario que no es el propietario. Ejecuta esos comandos como git, por ejemplo sudo -u git git -C /srv/git/miproyecto.git log --oneline.
Conclusión
Tienes un servidor Git privado en Ubuntu 24.04 al que los desarrolladores acceden por SSH con su propia clave, con un usuario limitado a operaciones de Git y copias diarias de los repositorios. Este esquema da a todos los usuarios acceso a todos los repositorios; si necesitas permisos por repositorio o rama, puedes añadir Gitolite sobre el mismo servidor, y si quieres interfaz web, pull requests e incidencias, instala Gitea o Forgejo. También puedes usar hooks post-receive en los repositorios bare para desplegar automáticamente tras cada push.
