… pasadas a limpio.
Hoy he tenido que ponerme manos a la obra para reconstruir mi repositorio git personal dado que empezaba a ser un poco caótico el acceso al mismo.
En esta entrada comencé hablando de ello y en esta otra amplié la información. Ahora veo que necesito una lista más ordenada y detallada del procedimiento.
Ojo: esta información sirve para un repositorio de un único usuario; si son varios es mejor echarle un vistazo a otro tipo de programas.
[toc]
Objetivos
- Repositorio git para un único desarrollador.
- Acceso de escritura seguro.
- Acceso de lectura sencillo.
Requerimientos
- Cuenta de usuario específica para gestionar el repositorio.
- Paquetes: git y gitweb.
- Scripts de mantenimiento del repositorio vía ssh.
Puesta en marcha
Se puede poner en marcha en dos partes: por una la gestión del propio repositorio en sí empleando SSH y git, lo que consigue accesos seguros de lectura y escritura; por otra el montaje del acceso vía web (con Apache y gitweb), que facilita mucho clonar los repositorios desde cualquier sitio sin comprometer la seguridad.
Creación de cuenta de usuario
$ sudo adduser --home /var/lib/git --no-create-home --shell /usr/bin/git-shell git $ chown -R git.www-data /var/lib/git
Scripts de mantenimiento
El programa git-shell sólo tiene acceso a los programas que aparezcan en el directorio ~/git-shell-commands y que tengan permisos de ejecución.
En el directorio /usr/share/doc/git/contrib se encuentran algunos y en la página Plan Zero otros.
create
#!/bin/sh
#
# Stolen idea from
# http://planzero.org/blog/2012/10/24/hosting_an_admin-friendly_git_server_with_git-shell
#
# If the user is not root
#if [ "$USERNAME" != "root" ]
#then
#
# # Dislpay a notice and stop
# echo "Sorry, only root can use this command."
# exit 1
#
#fi
# If no project name is given
if [ $# -eq 0 ]
then
# Display usage and stop
echo "Usage: create <project.git>"
exit 1
fi
# Set the project name, adding .git if necessary# Check for errors
if [ $(echo "$fingerprint" | egrep -c '(R|D)SA') -eq 0 ]
then
# Display the fingerprint error and clean up
echo "Error: $fingerprint"
rm $keyfile
exit 1
fi
# Add the key to the authorised keys file and clean up
mkdir -p .ssh &&\
echo -n "no-agent-forwarding,no-port-forwarding,no-X11-forwarding " >> .ssh/authorized_keys &&\
cat $keyfile >> .ssh/authorized_keys
rm $keyfile
# Display the fingerprint for reference
echo "Success! Added a key with the following fingerprint:"
echo $fingerprint
project=$(echo "$*" | sed 's/\.git$\|$/.git/i')
# Create and initialise the project
mkdir "$project" && \
cd "$project" && \
git --bare init
description
#!/bin/sh
# If no project name is given
if [ $# -eq 0 ]
then
# Display usage and stop
echo "Usage: description <project.git>"
exit 1
else
REPO=$1.git
fi
if [ ! -d "$REPO" ]; then
echo "Repository $REPO not found"
exit 1
else
echo "Current description: "
cat $REPO/description
fi
# Read the description
echo "Enter the new description:"
read desc
if [ -z "$desc" ]; then
echo "Description not changed !"
else
echo $desc > $REPO/description
echo "Description updated"
fi
exit 0
addkey
#!/bin/sh
#
# Stolen idea from
# http://planzero.org/blog/2012/10/24/hosting_an_admin-friendly_git_server_with_git-shell
#
# If the user is not root
#if [ "$USERNAME" != "root" ]
#then
#
# # Dislpay a notice and stop
# echo "Sorry, only root can use this command."
# exit 1
#
#fi
# Read in the SSH key
echo "Input the key to be added:"
read key
# Place the key in a temporary file (it's hard to get ssh-keygen
# to read from stdin; <<< works for bash, but is non-posix)
keyfile=$(tempfile) &&\
echo "$key" > $keyfile
# Generate a fingerprint
fingerprint=$(ssh-keygen -lf $keyfile)
# Check for errors
if [ $(echo "$fingerprint" | egrep -c '(R|D)SA') -eq 0 ]
then
# Display the fingerprint error and clean up
echo "Error: $fingerprint"
rm $keyfile
exit 1
fi
# Add the key to the authorised keys file and clean up
mkdir -p .ssh &&\
echo -n "no-agent-forwarding,no-port-forwarding,no-X11-forwarding " >> .ssh/authorized_keys &&\
cat $keyfile >> .ssh/authorized_keys
rm $keyfile
# Display the fingerprint for reference
echo "Success! Added a key with the following fingerprint:"
echo $fingerprint
Interfaz web
Lo que pretendo instalando el programa gitweb es conseguir un acceso sencillo a los repositorios empleando un navegador web y, de paso, una manera de clonar los repositorios en máquinas donde puedo necesitarlos sin tener que complicarme la vida con accesos SSH de usuarios.
Es un programa escrito en Perl, flexible en su configuración y muy versátil. Está bastante bien documentado y ofrece ejemplos para instalaciones muy variadas.
Iba a decir que lo primero es elegir el esquema de URL para acceder al contenido, y es importante que sea sencillo de recordar, pero creo que es más conveniente decidir primero qué contenido queremos que sea accesible.
Lista de proyectos de gitweb
Si no se indica otra cosa la lista de proyectos que muestra el programa se crea recorriendo el directorio raíz de los repositorios (/var/lib/git). Como ésto puede ser demasiado abierto considero que es mejor crear una lista de proyectos a mostrar y añadir algún tipo de mecanismo a la cuenta SSH para cambiar el estatus entre público y privado.
La variable $projects_list contiene la ruta de un archivo de texto donde se listan, uno por línea, aquellos repositorios que queremos que sean públicos. El formato es un tanto riguroso pero muy sencillo y está descrito en la documentación. También conviene indicar la exportación sea lo más rigurosa posible por lo que esa parte de la configuración queda así.
$projects_list = "/var/www/html/git.astillas.net/repositories.txt"; $strict_export = 1;
El servidor web y los URL
Todas las indicaciones a continuación son para el servidor web Apache y teniendo en cuenta la baja carga que tendrá el repositorio. No está optimizado para accesos masivos.
Lo primero es determinar qué URL vamos a utilizar para acceder. En mi caso ya dispongo de un servidor virtual llamado git.astillas.net y lo que quiero es:
- Acceder al interfaz web empleando un URL simple: https://git.astillas.net.
- Clonar repositorios directamente y también con un URL sencillo: https://git.astillas.net/msat.git por ejemplo.
En Debian el paquete gitweb sitúa el programa principal en /usr/lib/cgi-bin/gitweb.cgi y los contenidos extras bajo /usr/share/gitweb/static de tal manera que es necesario emplear varias directivas para acceder a ellos. También será necesario activar en Apache la configuración de programas CGI del sistema (serve-cgi-bin.conf).
El directorio del servidor virtual será el propio de los repositorios git en /var/lib/git y el fragmento de la configuración es el siguiente:
<VirtualHost *:443>
ServerName git.astillas.net
UseCanonicalName on
LogLevel info
ErrorLog /var/log/apache2/git.astillas.net/error.log
CustomLog /var/log/apache2/git.astillas.net/access.log combined
CustomLog /var/log/apache2/git.astillas.net/agent.log agent
CustomLog /var/log/apache2/git.astillas.net/referer.log referer
# Conexión segura
Include /etc/apache2/conf.d/astillas-ssl.conf
# Entorno para el programa
SetEnv GITWEB_CONFIG /etc/gitweb.conf
SetEnv GIT_PROJECT_ROOT /var/lib/git
SetEnv GIT_HTTP_EXPORT_ALL
# Directorio raíz y alias a recursos estáticos de gitweb
DocumentRoot /var/lib/git
<Directory /var/lib/git>
Options +ExecCGI +FollowSymLinks
Require all granted
</Directory>
# Gitweb y git-http-backend
ScriptAlias / /usr/lib/git-core/git-http-backend/
<Directory "/usr/lib/git-core">
AllowOverride None
Options +ExecCGI +FollowSymLinks
Require all granted
</Directory>
ScriptAliasMatch \
"(?x)^/(.*/(HEAD | \
info/refs | \
objects/(info/[^/]+ | \
[0-9a-f]{2}/[0-9a-f]{38} | \
pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
git-upload-pack))$" \
/usr/lib/git-core/git-http-backend/$1/
# turning on mod rewrite
RewriteEngine on
RewriteRule ^/$ /cgi-bin/gitweb.cgi [QSA,L,PT]
</VirtualHost>
El archivo que incluye astillas-ssl.conf define los parámetrros para la conexión segura con el servidor y no merece atención para este fin.
El resto emplea la directiva ScriptAliasMatch y mod_rewrite para asegurarse de que:
- Cuando se solicite una operación de clonado del repositorio o información concreta sobre su historial y demás se llame a un programa específico incluído con git:
git-http-backend. - Si no se pide nada concreto se cede el control a
gitweb.cgi.
También se indica que en dos lugares concretos se pueden ejecutar scripts y algún que otro detalle más. Esto es necesario porque el paquete Debian sitúa en diferentes sitios (siguiendo su normativa) los ejecutables normales y los de CGI.
Un detalle final que queda bonito es añadir un alias al directorio donde residen los archivos estáticos del programa como hojas de estilo, imágenes y demás.
Recetario
Crear el repositorio
$ ssh git@servidor create repositorio.git
y añadirle una descripción para la vista web:
$ ssh git@servidor description repositorio.git Descrition: xxxxxxxx $
Clonar el repositorio
$ git clone https://servidor/repositorio.git $ git clone git@servidor:repositorio.git
Actualizar el repositorio
git push git@servidor:repositorio.git