Renombrar volumen Docker

El cliente docker tiene un conjunto de opciones destinadas a administrar volúmenes (docker volume), pero ninguna de ellas permite renombrar un volumen existente.

Me puse a investigar cómo hacerlo y me fui a ver el filesystem y a buscar la carpeta que representa el volumen y hacer el cambio allí, pero cuando investigaba para no dañar la configuración me encontré con esta solución que me pareció muy filosofía docker, inclusive es lo que se hace para copiar un disco en una nueva unidad:

docker volume create --name <nuevo_volumen>
docker run --rm -it -v <viejo_volumen>:/from -v <nuevo_volumen>:/to alpine ash -c "cd /from ; cp -av . /to"
docker volume rm <viejo_volumen>

En definitiva se trata de crear un nuevo volumen, lanzar un contenedor que monta el volumen viejo y el volumen nuevo y copia los datos de uno a otro, y finalizar borrando el viejo volumen. Simple, seguro, y elegante.

La idea no es mía, la obtuve de este issue de Github, donde incluso alguien propone un script:

$ docker-rename-vol viejo-volumen nuevo-volumen

#/bin/bash
docker volume create --name $2
docker run --rm -it -v $1:/from -v $2:/to alpine ash -c "cd /from ; cp -av . /to"
[ $? -eq 0 ] && docker volume rm $1

Y ahora, está aquí mi blog para tenerlo presente.

Remover dominio de certificado Let’s Encrypt

Tengo un sitio que responde por varios dominios y, a su vez, con y sin www, por lo que el certificado let’s encrypt tiene un Nombre Común y varios Nombres Alternativos.

$ certbot-auto certificates
  Certificate Name: cert.com
    Serial Number: 40d6f1a43875cf95b5eeb284c2902060d8e
    Key Type: RSA
    Domains: cert.com dom.com test.us play.cert.com win.cert.com www.cert.com www.dom.com www.test.us
    Expiry Date: 2021-04-04 15:33:09+00:00 (VALID: 79 days)
    Certificate Path: /etc/letsencrypt/live/cert.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/cert.com/privkey.pem

resulta que de este certificado se había cancelado, borrado, eliminado el sitio win.cert.com por lo que necesitabamos bajarlo del DNS también. Si no modificamos el certificado, la próxima renovación automática de Let’s Encrypt produciría un error al no poder validar la existencia del sitio.

El procedimiento para eliminar un dominio es borrar el certificado en primer lugar:

$ certbot-auto delete --cert-name cert.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
The following certificate(s) are selected for deletion:

  * cert.com

Are you sure you want to delete the above certificate(s)?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(Y)es/(N)o: (Y)es/(N)o: (Y)es/(N)o: (Y)es/(N)o: (Y)es/(N)o: 

Al borrar el certificado no se afecta el servidor web que está corriendo, mientras el servidor no sea reiniciado.

Y se puede volver a tramitar un certificado, ahora con la lista de dominios excluyendo el que se quiere elimintar:

$ certbot-auto certonly -d cert.com -d cert.com -d dom.com \
  -d test.us -d play.cert.com -d www.cert.com -d www.dom.com \
  -d www.test.us

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1: Nginx Web Server plugin (nginx) [Misconfigured]
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2
Plugins selected: Authenticator standalone, Installer None
Requesting a certificate for cert.com and 6 more domains

Espero le sea útil a alguien más.

Monitoreo de Docker

Podemos poner a correr uno, dos o más dockers sin problema, podemos armarnos un docker-compose.yml que se encargue de levantar redes, definir volúmenes, correr dockers en órden de dependencia, en fin, podemos tener dockers corriendo… pero después, ¿cómo sabemos por qué nuestro sistema está lento? ¿por qué el host se queda sin memoria?

Claro que tenemos las herramientas de siempre: top, vmstat, htop … por nombrar algunas. Pero desde el host vemos el 100% de los procesos, pero no los contenedores responsables.

Asi que esta es una lista de las herramientas que utilizo para monitoreo de docker:

CTOP

Un top, pero por contenedor, como si cada contenedor fuera un proceso

ctop

https://github.com/bcicen/ctop

y en mis servidores lo incluyo (mediante una task de ansible) en este alias:

alias ctop='docker run --rm -ti \
   -v /var/run/docker.sock:/var/run/docker.sock:ro \
   quay.io/vektorlab/ctop:latest'

LazyDocker

Un panel en la consola para todo tu docker (imágenes, docker corriendo, volúmenes) que te permite ver logs, stats, etc. y algunas acciones basicas como stop/start, delete, etc…. y todo todo sensible al mouse (click!) y por SSH

lazydocker

https://github.com/jesseduffield/lazydocker

y en mis servidores ansible lo deja configurado asi:

alias lazydocker='docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  lazyteam/lazydocker'

Si conoces alguna otra herramienta, compártela en los comentarios.

Deepin

Ya hace tiempo que vengo utilizando Deepin como mi distribución de escritorio de Linux. Es algo que podemos cambiar, pero hace tiempo que Deepin es mi distribución preferida a la hora de montar un desktop.

Se trata de una distribución para desktop que busca ser elegante y fácil de utilizar para el usuario promedio.

No solo viene out-of-the-box con el software que uno espera (navegador Chrome, Correo Thunderbird, etc.) sino que trae algunas aplicaciones propias que buscan seguir la misma idea de sencillez y elegancia como un centro de aplicaciones (Deepin Store), Deepin ScreenShot y multimedia con Deepin Music y Deepin Movie.

Para ofimática viene ya pre-instalado todo el WPS Office que busca seguir la estética de los ciéntos de íconos y sub-menúes del MS-Office.

La base es GNU/Debian Linux, por lo que esta todo, todo lo demás que quieras instalar para personalizar tu deepin.

Hay una barra de aplciaciones preferidas donde puedes anclar tus aplicaciones más usadas y un launcher para buscar y lanzar tus aplciaciones.

El Centro de Control es un panel que se despliegua a la derecha y permite hacer tus configuraciones.

Es lindo, me gusta y lo uso y recomiendo y aquí está el enlace al sitio en español.

Cambiando vencimiento llave GPG

Las llaves GPG que me identifican les coloco un vencimiento anual.

Mi llave pública GPG en keybase

entonces cada año en esta época debo proceder a renovar la llave, que lo que hago es correrle un año para adelante el vencimiento y vovler a sincronizar con los keyservers.

Este es el proceso total que ejecuto:

Buscar mi llame en mi llavero:

$ gpg --list-keys Rodolfo
pub   rsa2048 2014-09-07 [SC] [caduca: 2017-09-14]
      FCE66FC5849DA0F6E30DD1FCA33C4E6423B5BE7B
uid           [  absoluta ] Rodolfo Pilas <rodolfo@>
uid           [  absoluta ] Rodolfo Pilas <rodolfo@>
uid           [  absoluta ] Rodolfo Pilas <rpilas@>
uid           [  absoluta ] [jpeg image of size 4579]
uid           [  absoluta ] [jpeg image of size 13611]
sub   rsa2048 2014-09-07 [E] [caduca: 2017-09-14]

Editar la llave:

$ gpg --edit-key FCE66FC5849DA0F6E30DD1FCA33C4E6423B5BE7B

Clave secreta disponible.

sec  rsa2048/A33C4E6423B5BE7B
     creado: 2014-09-07  caduca: 2017-09-14  uso: SC
     confianza: absoluta      validez: absoluta
ssb  rsa2048/65841C4E15CF2ADC
     creado: 2014-09-07  caduca: 2017-09-14  uso: E
[  absoluta ] (1). Rodolfo Pilas <rodolfo@>
[  absoluta ] (2)  Rodolfo Pilas <rodolfo@>
[  absoluta ] (3)  Rodolfo Pilas <rpilas@>
[  absoluta ] (4)  [jpeg image of size 4579]
[  absoluta ] (5)  [jpeg image of size 13611]

Está editando la key 0 o sea la que se identifica como A33C4E6423B5BE7B

gpg> expire
Cambiando caducidad de clave primaria.
Por favor, especifique el per'iodo de validez de la clave.
         0 = la clave nunca caduca
      <n>  = la clave caduca en n d'ias
      <n>w = la clave caduca en n semanas
      <n>m = la clave caduca en n meses
      <n>y = la clave caduca en n a~nos
?Validez de la clave (0)? 1y
La clave caduca Tue Sep 11 17:26:48 2018 -03
?Es correcto? (s/n) s

sec  rsa2048/A33C4E6423B5BE7B
     creado: 2014-09-07  caduca: 2018-09-11  uso: SC
     confianza: absoluta      validez: absoluta
ssb  rsa2048/65841C4E15CF2ADC
     creado: 2014-09-07  caduca: 2017-09-14  uso: E
[  absoluta ] (1). Rodolfo Pilas <rodolfo@>
[  absoluta ] (2)  Rodolfo Pilas <rodolfo@>
[  absoluta ] (3)  Rodolfo Pilas <rpilas@>
[  absoluta ] (4)  [jpeg image of size 4579]
[  absoluta ] (5)  [jpeg image of size 13611]

Ya quedo cambiada la caducidad de la llave primaria, ahora la secundaria 65841C4E15CF2ADC:

gpg> key 1

sec  rsa2048/A33C4E6423B5BE7B
     creado: 2014-09-07  caduca: 2018-09-11  uso: SC
     confianza: absoluta      validez: absoluta
ssb* rsa2048/65841C4E15CF2ADC
     creado: 2014-09-07  caduca: 2017-09-14  uso: E
[  absoluta ] (1). Rodolfo Pilas <rodolfo@>
[  absoluta ] (2)  Rodolfo Pilas <rodolfo@>
[  absoluta ] (3)  Rodolfo Pilas <rpilas@>
[  absoluta ] (4)  [jpeg image of size 4579]
[  absoluta ] (5)  [jpeg image of size 13611]

gpg> expire
Cambiando fecha de caducidad de subclave.
Por favor, especifique el per'iodo de validez de la clave.
         0 = la clave nunca caduca
      <n>  = la clave caduca en n d'ias
      <n>w = la clave caduca en n semanas
      <n>m = la clave caduca en n meses
      <n>y = la clave caduca en n a~nos
?Validez de la clave (0)? 1y
La clave caduca Tue Sep 11 17:27:37 2018 -03
?Es correcto? (s/n) s

sec  rsa2048/A33C4E6423B5BE7B
     creado: 2014-09-07  caduca: 2018-09-11  uso: SC
     confianza: absoluta      validez: absoluta
ssb* rsa2048/65841C4E15CF2ADC
     creado: 2014-09-07  caduca: 2018-09-11  uso: E
[  absoluta ] (1). Rodolfo Pilas <rodolfo@>
[  absoluta ] (2)  Rodolfo Pilas <rodolfo@>
[  absoluta ] (3)  Rodolfo Pilas <rpilas@>
[  absoluta ] (4)  [jpeg image of size 4579]
[  absoluta ] (5)  [jpeg image of size 13611]

Guardar la llave editada y salir de gpg

gpg> save

Subir la llave al keyserver, para que los cambios se repliquen

$ gpg --keyserver pgp.mit.edu --send-keys FCE66FC5849DA0F6E30DD1FCA33C4E6423B5BE7B
gpg: enviando clave A33C4E6423B5BE7B a hkp://pgp.mit.edu

Y aprovechar a actualizar todas las demas llaves de mi llavero, pero eso ya es otra tarea.

LXC en Debian con Ansible

Desde antes del 2013 vengo insitiendo con las ventajas de los containers en Linux, ya que permiten un rápido despliegue de muchos sistemas Linux corriendo en forma independiente.

En 2014 había hecho experiencias para tener con una máquina virtual de DigitalOcean muchos contenedores Linux instalados y prestando servicios y en 2016 tuve la oportunidad de compartir en forma práctica con la comunidad de Paysandú un ejemplo de uso de contenedores.

Hace unos meses atrás armé un perfil de vagrant (Vagrantfile) que permite levantar una máquina virtual con Debian e instalar (aprovisionar) un servidor de contenedores LXC, y un primer contenedor de pruebas.

Este artículo tiene por objetivo, compartir esa configuración, para que la pueda usar quién desee.

Repositorio: debian-lxc-ansible

El aprovisionamiento se realiza mediante Ansible, por lo que es fácil de parametrizar y adaptar.

Una vez levantado el primer contenedor (que ya queda en el aprovisionamiento inicial, luego de correr vagrant up) es muy fácil levantar más contenedores con los comandos normales.

También, en el directorio /vagrant/utils se entregan scripts (requieren revisión y adaptación a la instalación particular) que sirven cómo muestra de cómo levantar containers para producción:

a) Levantar un container con sitio web funcional

/vagrant/utils/create-container.sh name

b) Borrar el container creado con el script anterior

/vagrant/utils/destroy-container.sh name

c) Crear una página web para ver el status de los containers a través de web en el servidor lxc

/vagrant/utils/status.sh

Toda esta instalación, obviamente puede ser modificada y mejorada. Si desean compartir sus mejoras conmigo lo pueden hacer a través de Merge Request.

Actualización y los 4 millones de archivos

Un tiempo atrás actualicé un sistema Debian en forma rutinaria y hace un par de días comenzó a producir problemas extraños en las aplicaciones: desde pérdida de sesión al editar páginas web, errores para escribir en las bases de datos, hasta problemas de permisos en los archivos temporales.

El problema resultó ser la temida y oscura: tabla de inodos llena.

# df -i
Filesystem      Inodes    IUsed           IFree IUse% Mounted on
/dev/sda1       5120000 5120000     0        100%   /

Entonces, a salir a buscar dónde estaban los millones de archivos que ocupaban todos los inodos:

# find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
...
3945231  /var/lib/php5/

y resulta que en ese directorio se mantenían unos casi cuatro millones de archivos llamados como sess_dn5m6oc4fcpfo0c95pq1se4rp0.

Aparte de iniciar un proceso de borrado masivo:

# cd /var/lib/php5
# find . -name "sess_*" -print | xargs rm -v

Inicié la búsqueda de las causas de fondo para evitar que el problema se vuelva a repetir en el futuro.

En Debian/Ubuntu el encargado de mantener los archivos de sesiones que se generan en /var/lib/php5 es el script

# cat /etc/cron.d/php5
# /etc/cron.d/php5: crontab fragment for php5
#  This purges session files older than X, where X is defined in seconds
#  as the largest value of session.gc_maxlifetime from all your php.ini
#  files, or 24 minutes if not defined.  See /usr/lib/php5/maxlifetime

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -x /usr/lib/php5/sessionclean ] && [ -d /var/lib/php5 ] && /usr/lib/php5/sessionclean /var/lib/php5 $(/usr/lib/php5/maxlifetime)

que como se puede ver, utiliza la salida de la ejecución de /usr/lib/php5/maxlifetime para determinar el tiempo de mantenimiento de los archivos de sesión de php.

El problema se generó en la ejecución de /usr/lib/php5/maxlifetime que producía el error de al ejecutar por la presencia de la directiva safe_mode en el archivo php.ini:

#  grep safe_mode /etc/php5/apache2/php.ini
safe_mode = On

en razón de que:

42 | WARNING | INI directive ‘safe_mode’ is deprecated from PHP 5.3 and forbidden from PHP 5.4.

Así la actualización a PHP 5.4 hizo que el archivo /usr/lib/php5/maxlifetime dejara de devolver un valor para devolver un error. Entonces el proceso de limpieza, dejó de limpiar y se juntaron cuatro millones de archivos que llenaron la tabla de inodos.

Solución permanente: comentar safe_mode = On en el archivo php.ini.

Listar permisos rwx en octal

Estamos acostumbrados a ver los permisos de los archivos con el comando ls -l con la típica representación de rw-r–r– y generalmente hago la traducción a octal 644 en forma mental.

Pero si necesitamos desplegarlos en octal, tenemos a nuestra disposición el comando stat que soporta dar formato a la salida para ver sobre el estado de nuestro sistema de archivos:

En GNU/Linux que utilizamos stat de GNU Coreutils:

stat -c «%n %a» *
config.cf 644
containers.txt 644
libs 755

En MacOS que utilizamos stat de BSD:

stat -f «%N %Lp» *
config.cf 644
containers.txt 644
libs 755

Felicidades y happy hacking en 2017

GNU/Linux Distribution Timeline

El proyecto GNU/Linux Distribution Timeline (GLDT) mantiene un diagrama de la evolución de las distribuciones de GNU/Linux desde 1992 a la fecha.

Se trata de un proyecto iniciado en 2006 y que actualmente mantiene unas 480 distribuciones activas.

Si desean acceder a esas distribuciones, uno de los mejores sitios es distrowatch.com.

Recuperar desde BackupPC por línea de comandos

BackupPC es una herramienta formidable para respaldar y guardar un registro histórico de respaldos en el storage del servidor. Pero está orientado al uso mediante interfaz web, y cuando queremos vincularos con el servidor por la línea de comandos, es algo complicado.

Recuperar el directorio /usr/local/sbin en forma automática se puede usar este comando, ejecutado en el servidor a recuperar.


cd /usr/local; \
ssh backuppc@server.backuppc \
/usr/share/backuppc/bin/BackupPC_tarCreate \
-h "$(hostname -f)" -n -1 -s "$(pwd)" "sbin" | tar xf -

Explicándolo:

cd /usr/local: es el directorio ‘source’ respaldado, registrado en $Conf{RsyncShareName}
ssh backuppc@server.backuppc: supone que tenemos acceso ssh al servidor backuppc y las credenciales como el usuario bakcuppc. Si se accede como root se puede ejecutar con sudo -u backuppc pues el comando BackupPC_tarCreate lo debe ejecutar el usuario backuppc obligatoriamente.
-h $(hostname -f): va a ser reemplazado con el nombre del host respaldado, desde el cual se ejecuta el comando. Si BackupPC lo conoce por la IP se puede poner directamente luego del -h.
-n -1: recupera el último backup realizado. Se puede colocar el numero de backup se se desea otro.
-s $(pwd): va a ser reemplazado con el directorio actual del host respaldado, desde el cual se ejecuta el comando ssh. Es el nombre registrado en $Conf{RsyncShareName}.
sbin: es la carpeta/archivo a recuperar. Se puede utilizar un punto "." si se desea recuperar todo el contenido.
tar xf –: el comando BackupPC_tarCreate que se ejecuta mediante ssh en el servidor BackupPC genera un archivo tar en stdout. Este tar xf - se ejecuta localmente en el host respaldado y extrae del tar los archivos en el disco local.

Se puede mejorar haciendo un gzip antes de pasar los datos por la red.

Si alguien conoce un método más óptimo, agradezco lo comparta y, si encuentro algo mejor, lo documentaré por aqui.