index.html (9085B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Construcción de servidor Git propio</title> 7 <link rel="icon" type="image/png" href="/favicon.png" /> 8 <link rel="stylesheet" type="text/css" href="../article.css" /> 9 </head> 10 <body> 11 <header> 12 <p class="title">Construcción de servidor Git propio</p> 13 <p class="date">22 de noviembre de 2020 • fjbalon</p> 14 </header> 15 <p>Una buena razón para alojar tus propios repositorios git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando incluso el secreto de aquellos códigos que quieras mantener en secreto. Considero que los servidores de git comúnmente utilizados como github, gitlab, bitbucket... No son de fiar, en cuanto son propietarios desconocidos y sostenedores de tu código. No es secreto que estos servicios analizan el código, aplican telemetría e inteligencia sobre ellos, analizan las conexiones de sus usuarios y aplican restricciones y limitaciones. Al fin y al cabo son empresas con fines comerciales, y a menudo en el sistema actual con fines ocultos. En el caso de Microsoft, como propietario de github es mucho más lamentable y peligrosa la situación.</p> 16 <p>En cuanto a economía doméstica, estos servicios también tienen diferentes planes de precios y varias restricciones (arbitrarias en muchos casos). Sin embargo cuando usted mismo lo aloja, las restricciones son los límites de recursos del sistema y su conexión, por lo tanto, es una solución mucho más flexible, adaptada y convergente con el usuario.</p> 17 18 <h1>Creación de servidor git - ssh</h1> 19 <p>El primer paso sería crear el usuario git, encargado de gestionar todos los procesos referentes a los repositorios y al servidor. Además, con el objetivo de dotar acceso mediante SSH añadimos authorized_keys y añadimos al fichero las claves públicas de los clientes.</p> 20 21 <pre><code># adduser git 22 # su git 23 $ cd 24 $ mkdir .ssh && chmod 700 .ssh 25 $ touch .ssh/authorized_keys 26 $ chmod 600 .ssh/authorized_keys</code></pre> 27 <p>Los repositorios pueden estar en el directorio que se quiera. En este caso, se encontrarán en el directorio git en la raíz del sistema. Para lo que tendremos que crearlo. Por cada repositorio, se crea un directorio (aconsejable es que terminen con .git). Para iniciar un repositorio como server usamos el parámetro init --bare.</p> 28 29 <pre><code>$ mkdir /git 30 $ cd /git 31 $ mkdir code.git 32 $ chown git:git code.git 33 $ cd code.git 34 $ git init --bare 35 Initialized empty Git repository in /git/code.git/</code></pre> 36 37 <h1>Publicando repositorios</h1> 38 <p>El proceso anterior acepta comunicación SSH, por lo que el cliente necesitará o bien acceso por clave o acceso mediante RSA. En caso que queramos que alguno de estos repositorios sean clonables desde cualquier comunicación, y usando el eficiente protocolo git://, debemos publicarlos.</p> 39 <p>Para ello empleamos git-daemon, indicándole el directorio donde se encuentran los repositorios.</p> 40 41 <pre><code>$ git daemon --reuseaddr --base-path=/git/ /git/</code></pre> 42 <p>Esto no basta para publicar el repositorio, ya que el demonio de git iterará en el directorio anteriormente pasado en busca de repositorios exportables, éstos son aquellos que tengan el fichero git-daemon-export-ok en su raíz.</p> 43 44 <pre><code>$ touch /git/code.git/git-daemon-export-ok</code></pre> 45 46 <h1>Externalización con stagit</h1> 47 <p>A veces es agradable navegar por el registro del historial de git en un navegador web o en algún otro programa sin tener que mirar el repositorio local. Es además una forma de mantener un registro de los repositorios que sean públicos, a modo de currículum o expositor de código.</p> 48 <p>Para ello uso <a href="https://codemadness.org/git/stagit">stagit</a>, que es un static page generator para git. Su uso es simple. Manualmente consta de dos partes, que son la creación de directorios html (que deben ser accesibles mediante servidor web) y su enlace con el directorio del servidor git:</p> 49 50 <pre><code>$ mkdir -p /srv/git/htmlrepo1 && cd /srv/git/htmlrepo1 51 $ stagit /git/gitrepo1</code></pre> 52 <p>Y la formación del índice y el htmlroot:</p> 53 54 <pre><code>$ cd /srv/git 55 $ stagit-index /git/gitrepo1 /git/gitrepo2 /git/gitrepo3 > index.html</code></pre> 56 <p>Ejemplos de resultados son:</p> 57 <ul> 58 <li><a href="/git/">balong.es/git</a></li> 59 <li><a href="https://codemadness.org/git/">codemadness.org/git</a></li> 60 <li><a href="https://git.suckless.org/">git.suckless.org</a></li> 61 </ul> 62 <p>Para automatizar la actualización del directorio en función de los cambios de push añadimos a htmlroot (/srv/git) el script:</p> 63 64 <pre><code># /srv/git/create.sh 65 reposdir="/git" 66 curdir="$(pwd)" 67 68 # make index. 69 stagit-index "${reposdir}/"*/ > "${curdir}/index.html" 70 71 # make files per repo. 72 for dir in "${reposdir}/"*/; do 73 # strip .git suffix. 74 r=$(basename "${dir}") 75 d=$(basename "${dir}" ".git") 76 printf "%s... " "${d}" 77 78 mkdir -p "${curdir}/${d}" 79 cd "${curdir}/${d}" || continue 80 stagit -c ".cache" -u "/git/$d/" "${reposdir}/${r}" 81 82 # symlinks 83 ln -sf log.html index.html 84 ln -sf ../style.css style.css 85 ln -sf ../logo.png logo.png 86 ln -sf ../favicon.png favicon.png 87 88 echo "done" 89 done</code></pre> 90 <p>Por supuesto, el script anterior debe contar con permisos de ejecución; y el directorio htmlroot debe tener permisos adecuados para su manipulación, que siendo en este caso el usuario git el que genere de nuevo los HTML, debería éste tener permisos totales.</p> 91 92 <pre><code>drwxr-xr-x 19 git git 4096 Dec 14 15:46 git</code></pre> 93 <p>Además, por cada repositorio del servidor debemos añadir el hook post-receive tal que:</p> 94 95 <pre><code>#!/bin/sh 96 # /git/code.git/hooks/post-receive 97 98 export LC_CTYPE="en_US.UTF-8" 99 100 name="$1" 101 if test "${name}" = ""; then 102 name=$(basename "$(pwd)") 103 fi 104 105 # config 106 # paths must be absolute. 107 reposdir="/git" 108 dir="${reposdir}/${name}" 109 htmldir="/srv/git" 110 stagitdir="/" 111 destdir="${htmldir}${stagitdir}" 112 cachefile=".htmlcache" 113 # /config 114 115 if ! test -d "${dir}"; then 116 echo "${dir} does not exist" >&2 117 exit 1 118 fi 119 cd "${dir}" || exit 1 120 121 # detect git push -f 122 force=0 123 while read -r old new ref; do 124 test "${old}" = "0000000000000000000000000000000000000000" && continue 125 test "${new}" = "0000000000000000000000000000000000000000" && continue 126 127 hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) 128 if test -n "${hasrevs}"; then 129 force=1 130 break 131 fi 132 done 133 134 # strip .git suffix. 135 r=$(basename "${name}") 136 d=$(basename "${name}" ".git") 137 printf "[%s] stagit HTML pages... " "${d}" 138 139 mkdir -p "${destdir}/${d}" 140 cd "${destdir}/${d}" || exit 1 141 142 # remove commits and ${cachefile} on git push -f, this recreated later on. 143 if test "${force}" = "1"; then 144 rm -f "${cachefile}" 145 rm -rf "commit" 146 fi 147 148 # make index. 149 stagit-index "${reposdir}/"*/ > "${destdir}/index.html" 150 151 # make pages. 152 stagit -c "${cachefile}" -u "/git/$d/" "${reposdir}/${r}" 153 154 ln -sf log.html index.html 155 ln -sf ../style.css style.css 156 ln -sf ../logo.png logo.png 157 158 echo "done"</code></pre> 159 160 <pre><code>$ chmod +x hook/post-receive</code></pre> 161 <p>Lo que hará que en cada push recibido, el contenido HTML de stagit se actualice. Para una correcta impresión de los datos, es necesario que cada directorio de repositorio tenga en su raíz los ficheros owner, description y url:</p> 162 163 <pre><code>$ cd /git/code 164 $ echo "Fco Javier Balón" > owner 165 $ echo "Description code" > description 166 $ echo "git://balong.es/code.git" > url</code></pre> 167 <p>Las imágenes por defecto empleadas son favicon.png y logo.png, que irán en la raíz de htmlroot (/srv/git). También style.css.</p> 168 169 <pre><code>$ cp stagit/style.css /srv/git/ 170 $ cp stagit/favicon.png /srv/git/ 171 $ cp stagit/logo.png /srv/git/</code></pre> 172 173 <h1>Autodespliegue con hooks</h1> 174 <p>En este ejemplo damos al hook post-receive del repositorio del sitio web la capacidad de autodesplegarse al recibir push. </p> 175 176 <pre><code>#!/bin/sh 177 # /git/arrakis.git/hooks/post-receive 178 179 echo "Ejecutando hook postreicive: desplegando a producción el static-site" 180 git --work-tree=/srv/http --git-dir=/tex/arrakis.git checkout -f master</code></pre> 181 <p>Por supuesto, los permisos del directorio htmlroot deben tener los permisos para git.</p> 182 183 <pre><code>drwxr-xr-x 3 git git 4096 Dec 14 15:53 http</code></pre> 184 185 <h1>Configuración de cliente</h1> 186 <pre><code>$ git config --global user.name "balon" 187 $ git config --global user.email fcojavierba@protonmail.com 188 $ git config --global core.editor emacs</code></pre> 189 190 <pre><code># ~/.gitconfig 191 [user] 192 email = fcojavierba@protonmail.com 193 name = balon 194 [core] 195 editor = emacs</code></pre> 196 <p>La descarga mediante ssh y git-daemon se hará tal que:</p> 197 198 <pre><code>$ git clone git@balong.es:/git/code.git 199 $ git clone git://balong.es/code.git</code></pre> 200 201 </body> 202 </html>