Nuevo campo de juegos (LXD)

Hola, no sé si me recordaréis, pero yo antes solía escribir por aquí, es lo que tiene haber tenido dos preciosos niños, a ver si consigo ordenar un poco el tiempo y sacar ratitos para esto, no prometo nada.

Vamos a retomar con algo sencillito, como sabéis siempre he preferido utilizar contenedores puros, LXC, dejando un poco aparte Docker, por nada en especial, simplemente los primeros se adaptan mejor a mi forma de trabajar. Yo no soy un desarrollador, excepto por mis pinitos en Python, y por tanto para mis proyectos prefiero tratar mis contenedores más como servidores a los que puedo acceder tranquilamente, pero ya sabéis que lo mejor es utilizar la herramienta adecuada para cada problema.

La propia Canonical está liderando el desarrollo de una capa que envuelva a LXC llamada LXD, en mi empresa ya he empezado a utilizarlo en cargas de trabajo internas y su principal virtud, por ahora, es la comodidad en su manejo frente a los LXC en crudo.

Para este primer experimento voy a revisitar uno de mis posts sobre LXC en el que explicaba cómo montar una máquina en la que probar las actualizaciones y cualquier cosa que tuviera que ver con la plataforma sobre la que está montada este blog.

Como recordaréis yo tengo preferencia por Debian y mis máquinas de casa están montadas sobre esta distribución, en principio parecería que tendría que renunciar al uso de esta nueva capa, pero nada más lejos de la realidad, gracias al proyecto snapcraft podremos utilizarla sin problemas. Para su instalación simplemente debemos ejecutar los siguientes comandos:

# apt install snapd
# snap install lxd

El proceso está perfectamente explicado por el propio Stéphane Graber, el responsable del proyecto LXD en Canonical, en una entrada de su blog. Dependiendo de la distribución Debian que estéis utilizando obtendréis una versión u otra, en mi caso, se me ha instalado la versión 3.3, la penúltima liberada, aunque para instalaciones más empresariales deberíais quedaros en la 3.0.

Después de la instalación, si no queremos reiniciar, como mínimo la sesión, debemos reajustar el PATH de ejecución:

# . /etc/profile.d/apps-bin-path.sh

El siguiente paso es inicializar el entorno de LXD, para ello sólo hay que ejecutar la siguiente orden:

# lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:  
Do you want to configure a new storage pool? (yes/no) [default=yes]:  
Name of the new storage pool [default=default]: lxd_storage  
Name of the storage backend to use (btrfs, ceph, dir, lvm) [default=btrfs]: dir  
Would you like to connect to a MAAS server? (yes/no) [default=no]:  
Would you like to create a new local network bridge? (yes/no) [default=yes]: no  
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes  
Name of the existing bridge or host interface: lxc-bridge-nat  
Would you like LXD to be available over the network? (yes/no) [default=no]: yes  
Address to bind LXD to (not including port) [default=all]:  
Port to bind LXD to [default=8443]:  
Trust password for new clients:  
Again:  
No password set, client certificates will have to be manually trusted.Would you like stale cached images to be updated automatically? (yes/no) [default=yes]  
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:  

Como véis el proceso de configuración es muy sencillo, se define un almacén para albergar las imágenes de los contenedores y el acceso de red de los mismos. Yo he aprovechado un bridge que tenía montado en mi portátil, lxc-bridge-nat, para darles salida a internet y no me he complicado mucho con el almacenamiento, he elegido un directorio en el propio ordenador. También tenemos la posibilidad de utilizar una partición ZFS si tenemos instalados los paquetes correspondientes. Btrfs casi viene por defecto en Debian pero zfs es más peliagudo por temas de licencias, aunque para esta primera aproximación, como he comentado, utilizaremos un directorio del sistema.

Si queréis hacer una prueba rápida sólo tenéis que ejecutar el siguiente comando:

$ lxc launch ubuntu:bionic ubuntu-test
Creating ubuntu-test  
Starting ubuntu-test  
$ lxc list
+-------------+---------+------+------+------------+-----------+
|    NAME     |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------------+---------+------+------+------------+-----------+
| ubuntu-test | RUNNING |      |      | PERSISTENT | 0         |
+-------------+---------+------+------+------------+-----------+

Como véis no aparece ninguna dirección ipv4, esto es así porque yo no tengo un servidor dhcp configurado para esta interfaz de red. Si queréis utilizar el nuevo método que también ha creado Canonical para estandarizar la inicialización de las redes, sobre todo en contenedores, os daré un pequeño apunte, ya que en la página del proyecto tenéis ejemplos suficientes incluso para utilizar estas configuraciones en vuestras Ubuntu de escritorio. Primero entraremos en nuestro flamante contenedor y editaremos el fichero que se crea por defecto en los contenedores con ubuntu:

$ lxc exec ubuntu-test /bin/bash
# vi /etc/netplan/50-cloud-init.yaml

La configuración inicial es la siguiente:

network:  
    version: 2
    ethernets:
        eth0:
            dhcp4: true

Como véis, con esta simple configuración la red se inicializaría con cualquier servidor de dhcp, pero la configuración para mi red interna es ésta:

network:  
  version: 2
  ethernets:
    eth0:
      addresses:
        - 192.168.100.10/24
      gateway4: 192.168.100.1
      nameservers:
        addresses: [1.1.1.1, 8.8.8.8, 8.8.4.4]

Últimamente estoy probando los servidores de nombres que proporciona Cloudflare aparte de los de Google como podéis ver en la configuración. Para probar que la sintaxis es correcta podemos ejecutar lo siguiente:

# netplan generate
# netplan apply
# ip addr

Si el primer comando no escupe ningún error es que la configuración es sintácticamente correcta por lo que ya podéis aplicarla y comprobar mediante la última orden que todo está bien. Estas órdenes son muy útiles para no tener que reiniciar la máquina sin saber si todo estará bien a la vuelta.

Ahora otro pequeño apunte para poder acceder más cómodamente a nuestros contenedores. Si tenemos una clave privada generada desde nuestra cuenta de usuario local podemos, fácilmente, añadirla a todos los contenedores que vayamos generando. Para estos menesteres disponemos en LXD de los perfiles. Si no especificamos nada, todos se generarán utilizando el perfil por defecto que sorprendentemente se llama default. Si no tenéis clave privada generada, debéis ejecutar el siguiente comando:

$ ssh-keygen -t rsa

Y para cambiar el perfil por defecto sólo debemos lanzar la siguiente orden:

$ lxc profile edit default

Esto nos abrirá un editor de texto para cambiar el perfil y debemos coger el contenido del fichero ~/.ssh/id_rsa.pub, cambiar el campo config para que contenga los siguientes datos, siendo la última línea la parte pública de nuestra clave:

config:  
  user.user-data: |
    #cloud-config
    ssh_authorized_keys:
      - ssh-rsa ...

A partir de este momento cuando generemos un contenedor sin especificar perfil, aunque de todas formas no tenemos otro, nacerá con esta autorización y podremos acceder a él por ssh utilizando el usuario ubuntu, que en todos los LXD tiene permisos de sudo.

Bien, pues ya tendríamos nuestro contenedor preparado para albergar nuestro blog en pruebas antes de actualizar el principal. Como ha pasado tanto tiempo desde que dejé de actualizarlo vamos a saltar de la versión 0.11 hasta la 2.0, sí, lo sé, es una vergüenza, pero ya sabéis lo que dicen, en casa del herrero, cuchillo de palo.

Como expliqué con anterioridad el proceso de instalación del blog es muy sencillo, pero con el paso de los años, lo han simplificado aún más. Ahora acabamos de estrenar la versión 2.0 de Ghost, con mi anhelado multilenguaje, ya podré escribir estos posts para el resto del mundo. Parece ser que con la versión 1.0 ya mejoró bastante la instalación y el propio sistema adquirió habilidad para configurar el resto de elementos que intervienen en su implementación.

De nuestro post anterior podemos rescatar los requisitos:

# apt install mysql-server mysql-client nginx
# curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
# apt install nodejs

Según la documentación actualizada se nos pide un usuario que no sea root pero con permisos para ejecutar comandos de administración, esto ya lo hemos conseguido con los pasos anteriores por lo que nuestro usuario ideal en este caso es ubuntu. Para adecuar nuestra instalación de mysql debemos realizar un paso más:

$ sudo mysql
> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<password>';

Recordad que debéis cambiar el campo password por una contraseña que protegerá esta base de datos. Con esto ya lo tenemos todo preparado y podemos instalar la interfaz de comandos de ghost que implementaron los chicos responsables del proyecto en la versión 1.0:

$ sudo npm install i -g ghost-cli

Ahora crearemos el directorio sobre el que instalaremos el blog:

$ sudo mkdir -p /var/www/ghost
$ sudo chown ubuntu:ubuntu /var/www/ghost
$ sudo chmod 775 /var/www/ghost
$ cd /var/www/ghost
$ ghost install

Antes de pasar a detallar los pasos a seguir para esta instalación os comentaré que me he encontrado con un problema de permisos que no sé si se os reproducirá, pero por si acaso lo comento. El proceso de instalación chequea ciertas cosas y entre ellas intenta escribir en el directorio /home/ubuntu/.config/ que en mi caso tiene como propietario al usuario root por lo que para solucionarlo he tenido que hacer dos cosas:

$ sudo chown -R ubuntu:ubuntu /home/ubuntu/.config
$ sudo rm -Rf /var/www/ghost/*

Este último comando es necesario ya que el primer intento escribe un archivo de log que al instalador le impide continuar ya que exige un directorio vacío para avanzar. Y ahora sí, los pasos son los siguientes:

✔ Checking system Node.js version
✔ Checking logged in user
✔ Checking current folder permissions
✔ Checking operating system compatibility
✔ Checking for a MySQL installation
✔ Checking memory availability
✔ Checking for latest Ghost version
✔ Setting up install directory
✔ Downloading and installing Ghost v2.1.2
✔ Finishing install process
? Enter your domain: http://192.168.100.10
? Enter your MySQL hostname: localhost
? Enter your MySQL username: root
? Enter your MySQL password: [hidden]
? Enter your database name: ghost_prod
✔ Configuring Ghost
✔ Setting up instance
+ sudo useradd --system --user-group ghost
+ sudo chown -R ghost:ghost /var/www/ghost/content
✔ Setting up "ghost" system user
? Do you wish to set up "ghost" mysql user? Yes
✔ Setting up "ghost" mysql user
? Do you wish to set up Nginx? Yes
✔ Creating nginx config file at /var/www/ghost/system/files/192.168.100.10.conf
+ sudo ln -sf /var/www/ghost/system/files/192.168.100.10.conf /etc/nginx/sites-available/192.168.100.10.conf
+ sudo ln -sf /etc/nginx/sites-available/192.168.100.10.conf /etc/nginx/sites-enabled/192.168.100.10.conf
+ sudo nginx -s reload
✔ Setting up Nginx
? Do you wish to set up SSL? No
ℹ Setting up SSL [skipped]
? Do you wish to set up Systemd? Yes
✔ Creating systemd service file at /var/www/ghost/system/files/ghost_192-168-100-10.service
+ sudo ln -sf /var/www/ghost/system/files/ghost_192-168-100-10.service /lib/systemd/system/ghost_192-168-100-10.service
+ sudo systemctl daemon-reload
✔ Setting up Systemd
? Do you want to start Ghost? Yes
+ sudo systemctl is-active ghost_192-168-100-10
✔ Ensuring user is not logged in as ghost user
✔ Checking if logged in user is directory owner
✔ Checking current folder permissions
+ sudo systemctl is-active ghost_192-168-100-10
✔ Validating config
✔ Checking folder permissions
✔ Checking file permissions
✔ Checking content folder ownership
✔ Checking memory availability
+ sudo systemctl start ghost_192-168-100-10
✔ Starting Ghost
+ sudo systemctl is-enabled ghost_192-168-100-10
+ sudo systemctl enable ghost_192-168-100-10 --quiet
✔ Enabling Ghost instance startup on server boot

Ghost uses direct mail by default. To set up an alternative email method read our docs at https://ghost.org/mail

------------------------------------------------------------------------------

Ghost was installed successfully! To complete setup of your publication, visit: 

    http://192.168.100.10/ghost/

Si queréis profundizar en las preguntas a contestar, en esta dirección se explican pormenorizadamente, pero las importantes son, el dominio, que en mi caso he puesto la dirección ip del contenedor en la red, el usuario root de mysql y la contraseña que establecimos con anterioridad, así como la aceptación de que el propio instalador añada la configuración de nginx, la creación del servicio de systemd y su arranque.

Ahora, si apuntáis vuestro navegador a la dirección ip consignada en la instalación podréis ver el blog con sus valores de fábrica. Si además añadís la palabra ghost a la dirección podréis entrar en la configuración del mismo.

Bueno, este post ya me está quedando bastante largo y como vuelta al trabajo creo que es más que suficiente. Tengo a medias la segunda parte, hablaré un poquito más de LXD y de la migración del blog.

Esperando tener la migración hecha para la siguiente vez que nos leamos, me despido con un melocotonazo, año 1990, aunque yo la conocí un poco más tarde, a mediados de década, Mtv Gratest Hits para más señas, Depeche Mode de su disco Violator, esa obra maestra llamada Enjoy The Silence. Si repasáis el vídeo veréis más o menos cómo me he sentido escribiendo este post, unas largas caminatas, con tu tumbona a cuestas, simplemente para disfrutar del silencio cuando llegas a tu destino deseado.

Enjoy!