/ prog

git@nasciiboy.land

Desde la posecion del vps entoy ansioso de montarle chismes, pero no tengo muy claro cuales, para que, o como hacelo bajo un mismo dominio

mmm, segun veo por las pruebas, cada “servicio” tienen un puerto predeterminado y funciona mas o menos de manera automagica. Por ejemplo al activar el demonio ssh inmediatamente funciona de la manera

> ssh usuario@dominio

y

> ssh -p numero-puerto usuario@dominio

en caso de haber modificado el puerto por defecto que es el 22

para el caso de las paginas web el puerto es el 80 y el 443 para el https, pero tambien se puede cambiar este puerto por uno arbitrario como en

> elinks http://dominio.algo:numero-puerto/

intentando comprender estas magias de los dominios, los dns y los puertos (y protocolos… o no) ocurrioseme que ya que venia de las paginas gratuitas de gitlab y github donde no se permite la subida de ficheros “sospechosamente grandes” (como un album musical) seria interesante ademas de tener el repo para el funcionamiento de la pagina, permitir su clonacion y que quien quiera almacene, modifique o “plagie” lo que le venga en gana

ya en plena investigacion (mas alla de los 4 comandos que utilizo en git) me entero que este tiene diversos protocolos por los cuales se puede utilizar (aunque ya los habia empleado sin razonar sobre ello), son los siguientes

git clone ruta                             # clonar desde el propio equipo
git clone file://ruta                      # clonar desde el propio equipo
git clone usuario-ssh@dominio:ruta         # clonar utilizando una conexion ssh
git clone git://dominio/repositorio-o-ruta # clonar utilizando el "protocolo git"
git clone http://dominio/repositorio       # clonar utilizando "http inteligente"

ignorando las dos primeras opciones por ser para “el autoconsumo” y la ultima que encontre “demasiado” complicada y “poco documentada” para nginx (que es el servidor que estoy utilizando), las maneras simples de compartir el repositorio serian dos: mediante SSH que ya lo estaba utilizando y pocos miesterios encierra o utilizar el “protocolo git”

al rollo pues =>

git daemon

El “protocolo git” no es otra cosa mas que un pequeño servidor escuchando en el puerto 9418 al que se le asigna un directorio raiz desde el cual explorara el nombre de las carpetas en el, vera si son o no repositorios, si estan “habilitados” y que se puede hacer o no con ellos

su funcionamiento es tan sencillo como lanzar lo siguiente en consola

> git daemon --reuseaddr --verbose --base-path=/ruta-a-repositorios/

aqui el programa es git con el comando daemon para que entre en el modo servidor, --reuseraddr por que aparecio en algun post, --verbose para que lance toda la informacion que se pueda y --base-path=/ruta-a-repositorios es la carpeta raiz desde donde trabajara. Para mas informacion git help daemon

podriamos poner a prueba esto de la sigiente manera

mkdir /tmp/roma
cd /tmp/roma

# creamos un repo de pruebas
mkdir rama
cd rama
git init
echo "algo" > txt
git add txt
git commit -m "primer commit"

listos nuestro directorio (roma) y repo de pruebas (rama) lanzamos el git demonizado

> git daemon --reuseaddr --verbose --base-path=/tmp/roma/
[12618] Ready to rumble

y luego desde otra secion (y ruta) de terminal ponemos a prueba el invento

> git clone git://localhost/rama
Clonando en 'rama'...
fatal: error remoto: access denied or repository not exported: /rama

he? que fallo aqui? git daemon revisa en los repositorios si existe un fichero expecial llamado git-daemon-export-ok. Este fichero actua a modo de “bandera” para permitir las “cosas” que hace el servidor. Pero un dato que es importante, git-daemon-export-ok debe estar dentro del repositorio, dentro del directorio .git

Creamos la “bandera” para dar permiso a git daemon tal que asi

> touch /tmp/roma/rama/.git/git-daemon-export-ok

y volvemos a intentar la clonacion

> git clone git://localhost/rama
Clonando en 'rama'...
remote: Enumerando objetos: 3, listo.
remote: Contando objetos: 100% (3/3), listo.
remote: Total 3 (delta 0), reusado 3 (delta 0)
Recibiendo objetos: 100% (3/3), listo.

puag! magia!

ahora hagamos un pequeño experimento, ¿nos permitira subir modificaciones del clon recien hecho?

# recordar, esto es el repo clonado en alguna ruta
# distinta a `--base-path=/tmp/roma/` de `git daemon`
> cd rama
> echo "algo mas" >> txt
> git commit -a -m "nuevo commit"
> git push
fatal: error remoto: access denied or repository not exported: /rama

del lado de nuestro servidor git, nos arroja lo siguiente

[13117] Request receive-pack for '/rama'
[13117] 'receive-pack': service not enabled for '/tmp/roma//rama/.git'
[12618] [13117] Disconnected (with error)

nos informa que tenemos una peticion receive-pack para /rama pero que el servicio receive-pack no esta habilitado para este repo. Solucionamos esto aniquilando el servidor git con Ctrl-C y volviendolo a lanzar con una nueva opcion --enable=receive-pack

> git daemon --reuseaddr --verbose --base-path=/tmp/roma/ --enable=receive-pack

intentemos de nuevo

> git push
Enumerando objetos: 5, listo.
Contando objetos: 100% (5/5), listo.
Escribiendo objetos: 100% (3/3), 244 bytes | 244.00 KiB/s, listo.
Total 3 (delta 0), reusado 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: Por defecto, actualizar la rama actual en un repositorio no vacío
...
To git://localhost/rama
 ! [remote rejected] master -> master (branch is currently checked o

que paso? pues que necesitamos un tipo de repositorio especial llamado git bare que no es otra cosa que la carpeta .git que esta en cada repo pero con otra “bandera especial” habilitada.

Tenemos dos opciones. Convertir nuestro repositorio en un git bare de la siguiente manera

> cp -R /tmp/roma/rama/.git /tmp/roma/remo.git
> cd /tmp/roma/remo.git
> git config --bool core.bare true

ahora cambiemos la fuente remota de nuestro repo modificado e intentemos subir la modificacion al nuevo repositorio “remoto” remo

# de nuevo, esto es el repo clonado en alguna ruta aleatoria
> git remote set-url origin git://localhost/remo
> git push
Enumerando objetos: 5, listo.
Contando objetos: 100% (5/5), listo.
Escribiendo objetos: 100% (3/3), 244 bytes | 244.00 KiB/s, listo.
Total 3 (delta 0), reusado 0 (delta 0)
To git://localhost/remo
   9f6cd12..262a37b  master -> master

puag! como mola!

La otra opcion era crear un repositor bare vacio

> git init --bare /tmp/roma/remi.git

agregar la “bandera”

> touch /tmp/roma/remi.git/git-daemon-export-ok

agregar el nuevo destino a nuestro repo modificado (o no)

> git remote add remi git://localhost/remi
> git push remi master
Enumerando objetos: 6, listo.
Contando objetos: 100% (6/6), listo.
Compresión delta usando hasta 2 hilos
Comprimiendo objetos: 100% (2/2), listo.
Escribiendo objetos: 100% (6/6), 416 bytes | 416.00 KiB/s, listo.
Total 6 (delta 0), reusado 3 (delta 0)
To git://localhost/remi
 * [new branch]      master -> master

puag! que gusto!

vps

Conocemos la teoria del (servidor) git demonizado, pero falta que lo pongamos a funcionar en nuestra maquina donde estara (en teoria) funcionando y sirviendo clones a todo el mundo. Como proceder?

Segun parece, deberiamos crear un nuevo usuario en la maquina y un unico directorio bajo su custodia que contendra los repos y sera a su vez la ruta raiz para git daemon

Como root

> useradd -c "repos de nascii - nasciiboy@gmail.com" git -m
# -c  : comentario
# git : nombre de usuario
# -m  : crear directorio en /home
> passwd git
# mi !super contraseña¡ del usuario git

en varias fuentes parece que lo recomendable es establecer un directorio raiz en un lugar que no sea la home del usuario (como /opt/git o /var/repo), y de hecho que el usuario no tenga home… pero, paque complicarnos? que sea persona y tenga su home (de hay el parametro -m en adduser)

ahora solo restaria que el sistema operativo se encargue de levantar nuestro git demonizado en cada arranque. Segun un sitio de consultas y puesto que hice esto en debian y tiene systemd y hay que copiar y pegar. Colocamos lo siguiente dentro del fichero /etc/systemd/system/git-daemon.service

[Unit]
Description=Git Daemon
Documentation=man:git-daemon(1)
ConditionPathExists=/home/git/

[Service]
# no permite recibir cambios
ExecStart=/usr/bin/git daemon --reuseaddr --verbose --base-path=/home/git/
# permite recibir cambios
# ExecStart=/usr/bin/git daemon --reuseaddr --enable=receive-pack --verbose --base-path=/home/git/
User=git
Group=git

[Install]
WantedBy=multi-user.target

(adaptar en caso de ser necesario las rutas)

para habilitar el servicio por los siglos de los siglos y los reinicios

> systemctl enable git-daemon
> systemctl start  git-daemon
> systemctl status git-daemon
● git-daemon.service - Git Daemon
   Loaded: loaded (/etc/systemd/system/git-daemon.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2018-11-03 17:43:42 CST; 21s ago
     Docs: man:git-daemon(1)
 Main PID: 46787 (git)
    Tasks: 2 (limit: 4915)
   CGroup: /system.slice/git-daemon.service
           ├─46787 /usr/bin/git daemon --reuseaddr --verbose --base-path=/home/git/
           └─46790 git-daemon --reuseaddr --verbose --base-path=/home/git/

Nov 03 17:43:42 tachikoma systemd[1]: Started Git Daemon.
Nov 03 17:43:42 tachikoma git[26758]: [26762] Ready to rumble

(systemctl + (stop|disable) git-daemon para… se entiende por si mismo)

listo y facilmente! Ya pueden copiar nuestros repositorios (sin registro o contraseñas) tal que asi

> git clone git://mi-dominio.algo/repo

ho, quiza olvide mencionarlo, pero al demonio de git, cuando nuestro repositorio se llama repo.git le es indiferente si lo mencionamos con o sin el .git. Lo nombramos asi para permitir ambas opciones, por que lo contrario (hacer tareas en un repo-sin-punto-git) agregando el .git no funciona

Antes de terminar con los detalles configuratorios, me preguntaba por que o como permitir que alguien tenga acceso al repositorio para modificarlo. Para esto pues la mejor manera seria agregar su clave publica en ~git/.ssh/authorized_keys.

tambien podriamos habilitar para el usuario git el acceso mediante contraseña agregardo al final del fichero /etc/ssh/sshd_config

Match User git
    PasswordAuthentication yes

Si se diera el caso de tener colaboradores “quiza” no querriamos que hicieran nada no relacionado con git. En tal situacion y solo de esta manera deberiamos substituir la shell del usuario git por una shell que no permita hacer absolutamente nada

> chsh git -s /usr/bin/git-shell

Pero esta es solo una medida extrema, unicamente aplicable si no confiamos en quien tenga acceso. Al hacer esto tambien nosotros tendriamos que sufrir incomodidades inecesarios, pues ni un scp funciona si la shell es git-shell

Asi pues, bajo el supuesto que usamos “ssh con llaves”, pues no veo por que implementar ninguna medida adicional

nasciiboy-land

y llegado a este punto, ya podeis clonar el repo que da vida a esta web

> git clone git://nasciiboy.land/nasciiboy-land

son algo mas de 2GiB! Como el vps esta bastante corto tanto en ram como en procesador hacerlo solo una vez por persona multiplicando el minuto actual de su reloc por la hora y sumando 3 y tomando el resultado como los segundos de espera. La comprecion que realiza git pone al 100% al procesador y el GB de ram se satura (tube que agregar un ficherito swap de 2 GB mas para que sea posible)

si quieren construir la web, entran a la copia del repo y ejecutan el programa hugo. El resultado estara en el directorio public

se supone que hugo serve te permite ver y modificar el sitio al vuelo, pero mi maquina con 8GB de ram y 8GiB de swap no puede con tal encargo…

happy hacking!

/ prog