{"id":2191,"date":"2017-06-06T10:20:26","date_gmt":"2017-06-06T10:20:26","guid":{"rendered":"https:\/\/esferas.org\/msqlu\/?p=2191"},"modified":"2017-06-06T10:20:26","modified_gmt":"2017-06-06T10:20:26","slug":"instrucciones-para-un-repositorio-git","status":"publish","type":"post","link":"https:\/\/esferas.org\/msqlu\/2017\/06\/06\/instrucciones-para-un-repositorio-git\/","title":{"rendered":"Instrucciones para un repositorio git &#8230;"},"content":{"rendered":"<div class='__iawmlf-post-loop-links' style='display:none;' data-iawmlf-post-links='[{&quot;id&quot;:744,&quot;href&quot;:&quot;https:\\\/\\\/packages.debian.org\\\/git&quot;,&quot;archived_href&quot;:&quot;https:\\\/\\\/web-wp.archive.org\\\/web\\\/20260415151737\\\/https:\\\/\\\/packages.debian.org\\\/git&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[],&quot;broken&quot;:false,&quot;last_checked&quot;:null,&quot;process&quot;:&quot;done&quot;},{&quot;id&quot;:745,&quot;href&quot;:&quot;https:\\\/\\\/packages.debian.org\\\/gitweb&quot;,&quot;archived_href&quot;:&quot;https:\\\/\\\/web-wp.archive.org\\\/web\\\/20080531075740\\\/http:\\\/\\\/packages.debian.org:80\\\/gitweb&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[{&quot;date&quot;:&quot;2026-04-15 15:15:15&quot;,&quot;http_code&quot;:200}],&quot;broken&quot;:false,&quot;last_checked&quot;:{&quot;date&quot;:&quot;2026-04-15 15:15:15&quot;,&quot;http_code&quot;:200},&quot;process&quot;:&quot;done&quot;},{&quot;id&quot;:746,&quot;href&quot;:&quot;http:\\\/\\\/planzero.org\\\/blog\\\/2012\\\/10\\\/24\\\/hosting_an_admin-friendly_git_server_with_git-shell&quot;,&quot;archived_href&quot;:&quot;&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[],&quot;broken&quot;:false,&quot;last_checked&quot;:null,&quot;process&quot;:&quot;done&quot;},{&quot;id&quot;:747,&quot;href&quot;:&quot;https:\\\/\\\/git-scm.com\\\/docs\\\/gitweb&quot;,&quot;archived_href&quot;:&quot;https:\\\/\\\/web-wp.archive.org\\\/web\\\/20260308142911\\\/https:\\\/\\\/git-scm.com\\\/docs\\\/gitweb&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[{&quot;date&quot;:&quot;2026-04-15 15:15:25&quot;,&quot;http_code&quot;:206}],&quot;broken&quot;:false,&quot;last_checked&quot;:{&quot;date&quot;:&quot;2026-04-15 15:15:25&quot;,&quot;http_code&quot;:206},&quot;process&quot;:&quot;done&quot;},{&quot;id&quot;:748,&quot;href&quot;:&quot;https:\\\/\\\/git.astillas.net&quot;,&quot;archived_href&quot;:&quot;https:\\\/\\\/web-wp.archive.org\\\/web\\\/20230331023205\\\/https:\\\/\\\/git.astillas.net\\\/&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[{&quot;date&quot;:&quot;2026-04-15 15:15:37&quot;,&quot;http_code&quot;:404},{&quot;date&quot;:&quot;2026-05-05 03:12:14&quot;,&quot;http_code&quot;:404}],&quot;broken&quot;:false,&quot;last_checked&quot;:{&quot;date&quot;:&quot;2026-05-05 03:12:14&quot;,&quot;http_code&quot;:404},&quot;process&quot;:&quot;done&quot;}]'><\/div>\n<p>&#8230; pasadas a limpio.<\/p>\n<p><!--more--><\/p>\n<p>Hoy he tenido que ponerme manos a la obra para reconstruir mi repositorio git personal dado que empezaba a ser un poco ca\u00f3tico el acceso al mismo.<\/p>\n<p>En <a href=\"https:\/\/esferas.org\/msqlu\/2013\/10\/11\/creando-un-servidor-git\/\">esta entrada<\/a> comenc\u00e9 hablando de ello y en <a href=\"https:\/\/esferas.org\/msqlu\/2013\/10\/11\/seguimos-completando-el-servidor-git\/\">esta otra<\/a> ampli\u00e9 la informaci\u00f3n. Ahora veo que necesito una lista m\u00e1s ordenada y detallada del procedimiento.<\/p>\n<p style=\"padding-left: 60px;\"><strong>Ojo<\/strong>: esta informaci\u00f3n sirve para un repositorio de un \u00fanico usuario; si son varios es mejor echarle un vistazo a otro tipo de programas.<\/p>\n<p>[toc]<\/p>\n<h3>Objetivos<\/h3>\n<ul>\n<li>Repositorio git para un \u00fanico desarrollador.<\/li>\n<li>Acceso de escritura seguro.<\/li>\n<li>Acceso de lectura sencillo.<\/li>\n<\/ul>\n<h3>Requerimientos<\/h3>\n<ul>\n<li>Cuenta de usuario espec\u00edfica para gestionar el repositorio.<\/li>\n<li>Paquetes: <a href=\"https:\/\/packages.debian.org\/git\">git<\/a> y <a href=\"https:\/\/packages.debian.org\/gitweb\">gitweb<\/a>.<\/li>\n<li><em>Scripts<\/em> de mantenimiento del repositorio v\u00eda <em>ssh<\/em>.<\/li>\n<\/ul>\n<h3>Puesta en marcha<\/h3>\n<p>Se puede poner en marcha en dos partes: por una la gesti\u00f3n del propio repositorio en s\u00ed empleando SSH y git, lo que consigue accesos seguros de lectura y escritura; por otra el montaje del acceso v\u00eda web (con Apache y gitweb), que facilita mucho clonar los repositorios desde cualquier sitio sin comprometer la seguridad.<\/p>\n<h4>Creaci\u00f3n de cuenta de usuario<\/h4>\n<pre class=\"lang:default decode:true \">$ sudo adduser --home \/var\/lib\/git --no-create-home --shell \/usr\/bin\/git-shell git\r\n$ chown -R git.www-data \/var\/lib\/git \r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4>Scripts de mantenimiento<\/h4>\n<p>El programa <code>git-shell<\/code> s\u00f3lo tiene acceso a los programas que aparezcan en el directorio <code>~\/git-shell-commands<\/code> y que tengan permisos de ejecuci\u00f3n.<\/p>\n<p>En el directorio <code>\/usr\/share\/doc\/git\/contrib<\/code> se encuentran algunos y en la p\u00e1gina <a href=\"http:\/\/planzero.org\/blog\/2012\/10\/24\/hosting_an_admin-friendly_git_server_with_git-shell\">Plan Zero<\/a> otros.<\/p>\n<h5>create<\/h5>\n<pre class=\"lang:sh decode:true\">#!\/bin\/sh\r\n\r\n#\r\n#       Stolen idea from \r\n#       http:\/\/planzero.org\/blog\/2012\/10\/24\/hosting_an_admin-friendly_git_server_with_git-shell\r\n#\r\n\r\n# If the user is not root\r\n#if [ \"$USERNAME\" != \"root\" ]\r\n#then\r\n#\r\n#       # Dislpay a notice and stop\r\n#       echo \"Sorry, only root can use this command.\"\r\n#       exit 1\r\n#\r\n#fi\r\n\r\n# If no project name is given\r\nif [ $# -eq 0 ]\r\nthen\r\n\r\n        # Display usage and stop\r\n        echo \"Usage: create &lt;project.git&gt;\"\r\n        exit 1\r\n\r\nfi\r\n\r\n# Set the project name, adding .git if necessary# Check for errors\r\nif [ $(echo \"$fingerprint\" | egrep -c '(R|D)SA') -eq 0 ]\r\nthen\r\n\r\n # Display the fingerprint error and clean up\r\n echo \"Error: $fingerprint\"\r\n rm $keyfile\r\n exit 1\r\n\r\nfi\r\n\r\n# Add the key to the authorised keys file and clean up\r\nmkdir -p .ssh &amp;&amp;\\\r\necho -n \"no-agent-forwarding,no-port-forwarding,no-X11-forwarding \" &gt;&gt; .ssh\/authorized_keys &amp;&amp;\\\r\ncat $keyfile &gt;&gt; .ssh\/authorized_keys\r\nrm $keyfile\r\n\r\n# Display the fingerprint for reference\r\necho \"Success! Added a key with the following fingerprint:\"\r\necho $fingerprint\r\nproject=$(echo \"$*\" | sed 's\/\\.git$\\|$\/.git\/i')\r\n\r\n# Create and initialise the project\r\nmkdir \"$project\" &amp;&amp; \\\r\ncd \"$project\" &amp;&amp; \\\r\ngit --bare init<\/pre>\n<h5>description<\/h5>\n<pre class=\"lang:default decode:true\">#!\/bin\/sh\r\n\r\n# If no project name is given\r\nif [ $# -eq 0 ]\r\nthen\r\n\r\n        # Display usage and stop\r\n        echo \"Usage: description &lt;project.git&gt;\"\r\n        exit 1\r\nelse\r\n        REPO=$1.git\r\nfi\r\n\r\nif [ ! -d \"$REPO\" ]; then \r\n        echo \"Repository $REPO not found\"\r\n        exit 1\r\nelse \r\n        echo \"Current description: \"\r\n        cat $REPO\/description\r\nfi \r\n\r\n# Read the description\r\necho \"Enter the new description:\" \r\nread desc\r\n\r\nif [ -z \"$desc\" ]; then \r\n        echo \"Description not changed !\"\r\nelse\r\n        echo $desc &gt; $REPO\/description\r\n        echo \"Description updated\"\r\nfi\r\n\r\nexit 0\r\n<\/pre>\n<h5>addkey<\/h5>\n<pre class=\"lang:swift decode:true\">#!\/bin\/sh\r\n\r\n#\r\n#       Stolen idea from \r\n#       http:\/\/planzero.org\/blog\/2012\/10\/24\/hosting_an_admin-friendly_git_server_with_git-shell\r\n#\r\n\r\n# If the user is not root\r\n#if [ \"$USERNAME\" != \"root\" ]\r\n#then\r\n#\r\n#       # Dislpay a notice and stop\r\n#       echo \"Sorry, only root can use this command.\"\r\n#       exit 1\r\n#\r\n#fi\r\n\r\n# Read in the SSH key\r\necho \"Input the key to be added:\"\r\nread key\r\n\r\n# Place the key in a temporary file (it's hard to get ssh-keygen\r\n# to read from stdin; &lt;&lt;&lt; works for bash, but is non-posix)\r\nkeyfile=$(tempfile) &amp;&amp;\\\r\necho \"$key\" &gt; $keyfile\r\n\r\n# Generate a fingerprint\r\nfingerprint=$(ssh-keygen -lf $keyfile)\r\n\r\n# Check for errors\r\nif [ $(echo \"$fingerprint\" | egrep -c '(R|D)SA') -eq 0 ]\r\nthen\r\n\r\n        # Display the fingerprint error and clean up\r\n        echo \"Error: $fingerprint\"\r\n        rm $keyfile\r\n        exit 1\r\n\r\nfi\r\n\r\n# Add the key to the authorised keys file and clean up\r\nmkdir -p .ssh &amp;&amp;\\\r\necho -n \"no-agent-forwarding,no-port-forwarding,no-X11-forwarding \" &gt;&gt; .ssh\/authorized_keys &amp;&amp;\\\r\ncat $keyfile &gt;&gt; .ssh\/authorized_keys\r\nrm $keyfile\r\n\r\n# Display the fingerprint for reference\r\necho \"Success! Added a key with the following fingerprint:\"\r\necho $fingerprint\r\n\r\n<\/pre>\n<h4>Interfaz web<\/h4>\n<p>Lo que pretendo instalando el programa <em>gitweb<\/em> es conseguir un acceso sencillo a los repositorios empleando un navegador web y, de paso, una manera de clonar los repositorios en m\u00e1quinas donde puedo necesitarlos sin tener que <em>complicarme<\/em> la vida con accesos SSH de usuarios.<\/p>\n<p>Es un programa escrito en Perl, flexible en su configuraci\u00f3n y muy vers\u00e1til. Est\u00e1 bastante bien <a href=\"https:\/\/git-scm.com\/docs\/gitweb\">documentado<\/a> y ofrece ejemplos para instalaciones muy variadas.<\/p>\n<p>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\u00e1s conveniente decidir primero qu\u00e9 contenido queremos que sea accesible.<\/p>\n<p>Lista de proyectos de gitweb<\/p>\n<p>Si no se indica otra cosa la lista de proyectos que muestra el programa se crea recorriendo el directorio ra\u00edz de los repositorios (<code>\/var\/lib\/git<\/code>). Como \u00e9sto puede ser demasiado abierto considero que es mejor crear una lista de proyectos a mostrar y a\u00f1adir alg\u00fan tipo de mecanismo a la cuenta SSH para cambiar el estatus entre p\u00fablico y privado.<\/p>\n<p>La variable <code>$projects_list<\/code> contiene la ruta de un archivo de texto donde se listan, uno por l\u00ednea, aquellos repositorios que queremos que sean p\u00fablicos. El formato es un tanto riguroso pero muy sencillo y est\u00e1 descrito en la documentaci\u00f3n. Tambi\u00e9n conviene indicar la exportaci\u00f3n sea lo m\u00e1s rigurosa posible por lo que esa parte de la configuraci\u00f3n queda as\u00ed.<\/p>\n<pre class=\"lang:apache decode:true\">$projects_list = \"\/var\/www\/html\/git.astillas.net\/repositories.txt\";\r\n$strict_export = 1;<\/pre>\n<p>&nbsp;<\/p>\n<h5>El servidor web y los URL<\/h5>\n<p>Todas las indicaciones a continuaci\u00f3n son para el servidor web Apache y teniendo en cuenta la baja carga que tendr\u00e1 el repositorio. No est\u00e1 optimizado para accesos masivos.<\/p>\n<p>Lo primero es determinar qu\u00e9 URL vamos a utilizar para acceder. En mi caso ya dispongo de un servidor virtual llamado <em>git.astillas.net<\/em> y lo que quiero es:<\/p>\n<ol>\n<li>Acceder al interfaz web empleando un URL simple: <a href=\"https:\/\/git.astillas.net\">https:\/\/git.astillas.net<\/a>.<\/li>\n<li>Clonar repositorios directamente y tambi\u00e9n con un URL sencillo: <em>https:\/\/git.astillas.net\/msat.git<\/em> por ejemplo.<\/li>\n<\/ol>\n<p>En Debian el paquete gitweb sit\u00faa el programa principal en <code>\/usr\/lib\/cgi-bin\/gitweb.cgi<\/code> y los contenidos extras bajo <code>\/usr\/share\/gitweb\/static<\/code> de tal manera que es necesario emplear varias directivas para acceder a ellos. Tambi\u00e9n ser\u00e1 necesario activar en Apache la configuraci\u00f3n de programas CGI del sistema (<del><code><\/code><\/del><code>serve-cgi-bin.conf<\/code>).<\/p>\n<p>El directorio del servidor virtual ser\u00e1 el propio de los repositorios git en <code>\/var\/lib\/git<\/code> y el fragmento de la configuraci\u00f3n es el siguiente:<\/p>\n<pre class=\"lang:apache decode:true\">&lt;VirtualHost *:443&gt;\r\n        ServerName              git.astillas.net\r\n        UseCanonicalName        on\r\n\r\n        LogLevel info\r\n        ErrorLog \/var\/log\/apache2\/git.astillas.net\/error.log\r\n        CustomLog \/var\/log\/apache2\/git.astillas.net\/access.log combined\r\n        CustomLog \/var\/log\/apache2\/git.astillas.net\/agent.log agent\r\n        CustomLog \/var\/log\/apache2\/git.astillas.net\/referer.log referer\r\n\r\n        # Conexi\u00f3n segura\r\n        Include         \/etc\/apache2\/conf.d\/astillas-ssl.conf\r\n\r\n        # Entorno para el programa\r\n        SetEnv  GITWEB_CONFIG   \/etc\/gitweb.conf\r\n        SetEnv  GIT_PROJECT_ROOT \/var\/lib\/git\r\n        SetEnv  GIT_HTTP_EXPORT_ALL\r\n\r\n        # Directorio ra\u00edz y alias a recursos est\u00e1ticos de gitweb\r\n        DocumentRoot \/var\/lib\/git\r\n        &lt;Directory \/var\/lib\/git&gt;\r\n                Options +ExecCGI +FollowSymLinks\r\n                Require all granted\r\n        &lt;\/Directory&gt;\r\n        #  Gitweb y git-http-backend\r\n        ScriptAlias \/   \/usr\/lib\/git-core\/git-http-backend\/\r\n        &lt;Directory \"\/usr\/lib\/git-core\"&gt;\r\n                AllowOverride None\r\n                Options +ExecCGI +FollowSymLinks\r\n                Require all granted\r\n        &lt;\/Directory&gt;\r\n\r\n        ScriptAliasMatch \\\r\n         \"(?x)^\/(.*\/(HEAD | \\\r\n          info\/refs | \\\r\n           objects\/(info\/[^\/]+ | \\\r\n           [0-9a-f]{2}\/[0-9a-f]{38} | \\\r\n           pack\/pack-[0-9a-f]{40}\\.(pack|idx)) | \\\r\n           git-upload-pack))$\" \\\r\n           \/usr\/lib\/git-core\/git-http-backend\/$1\/\r\n\r\n        # turning on mod rewrite\r\n        RewriteEngine on\r\n        RewriteRule ^\/$  \/cgi-bin\/gitweb.cgi [QSA,L,PT]\r\n&lt;\/VirtualHost&gt;\r\n<\/pre>\n<p>El archivo que incluye <code>astillas-ssl.conf<\/code> define los par\u00e1metrros para la conexi\u00f3n segura con el servidor y no merece atenci\u00f3n para este fin.<\/p>\n<p>El resto emplea la directiva <code>ScriptAliasMatch<\/code> y <code>mod_rewrite<\/code> para asegurarse de que:<\/p>\n<ol>\n<li>Cuando se solicite una operaci\u00f3n de clonado del repositorio o informaci\u00f3n concreta sobre su historial y dem\u00e1s se llame a un programa espec\u00edfico inclu\u00eddo con git: <code>git-http-backend<\/code>.<\/li>\n<li>Si no se pide nada concreto se cede el control a <code>gitweb.cgi<\/code>.<\/li>\n<\/ol>\n<p>Tambi\u00e9n se indica que en dos lugares concretos se pueden ejecutar <em>scripts<\/em> y alg\u00fan que otro detalle m\u00e1s. Esto es necesario porque el paquete <em>Debian<\/em> sit\u00faa en diferentes sitios (siguiendo su normativa) los ejecutables normales y los de CGI.<\/p>\n<p>Un detalle final que queda bonito es a\u00f1adir un alias al directorio donde residen los archivos est\u00e1ticos del programa como hojas de estilo, im\u00e1genes y dem\u00e1s.<\/p>\n<h3>Recetario<\/h3>\n<p>&nbsp;<\/p>\n<h4>Crear el repositorio<\/h4>\n<pre class=\"lang:sh decode:true\">$ ssh git@servidor create repositorio.git<\/pre>\n<p>y a\u00f1adirle una descripci\u00f3n para la vista web:<\/p>\n<pre class=\"lang:default decode:true\">$ ssh git@servidor description repositorio.git \r\nDescrition:\r\nxxxxxxxx\r\n$<\/pre>\n<h4>Clonar el repositorio<\/h4>\n<pre class=\"lang:sh decode:true\">$ git clone https:\/\/servidor\/repositorio.git \r\n$ git clone git@servidor:repositorio.git\r\n<\/pre>\n<h4>Actualizar el repositorio<\/h4>\n<pre class=\"lang:default decode:true\">git push git@servidor:repositorio.git\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8230; pasadas a limpio.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","webmentions_disabled_pings":false,"webmentions_disabled":false,"footnotes":""},"categories":[2],"tags":[18,75,73,689,688,711],"class_list":["post-2191","post","type-post","status-publish","format-standard","hentry","category-software","tag-administracion-de-sistemas","tag-apache","tag-git","tag-git-shell","tag-gitweb","tag-mod_rewrite"],"_links":{"self":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts\/2191","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/comments?post=2191"}],"version-history":[{"count":0,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts\/2191\/revisions"}],"wp:attachment":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/media?parent=2191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/categories?post=2191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/tags?post=2191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}