Ghost: revisited

Como ya expliqué en el post anterior el repositorio oficial de Debian y Ubuntu para node.js ha cambiado, así que aprovechando que estábamos sustituyendo el entorno de pruebas para Ghost en KVM por un contenedor sin privilegios vamos a revisitar nuestra instalación inicial del blog. Esta vez vamos a partir de una imagen inicial de Ubuntu 16.04 ya que hemos actualizado con éxito la distribución en el servidor en el que estáis leyendo estas líneas.

Lo primero es instalar el servidor de Node.js, para ello, como ya comenté anteriormente, han cambiado los repositorios del proyecto para Debian y Ubuntu. Pues bien, vamos a seguir las instrucciones del proyecto para instalar la versión correcta. Vamos a pararnos un momento aquí ya que cuando escribí el primer post, ambos proyectos, Ghost y Node.js, eran muy jóvenes y parece que las cosas no estaban muy ordenadas.

Según el equipo de desarrollo de Ghost, se intenta que la plataforma sólo soporte las versiones LTS de Node.js, cosa que me parece muy sensata. En el enlace que os he puesto podréis consultar la información al respecto, siempre actualizada, por supuesto, habrá que tener en cuenta la versión de Ghost sobre la que estamos trabajando. Un consejo, no os durmáis en los laureles, suscribíos a su newsletter y tan pronto como haya un cambio de versión importante, es decir, de la 0.x.y a la 0.z.y actualizaos, os evitaréis unas horas de investigación que no os supondrán ningún beneficio intelectual, lo digo por experiencia.

En este momento la versión soportada es la 4 por lo que los pasos a seguir son los siguientes:

# curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -

## Installing the NodeSource Node.js v4.x LTS Argon repo...

## Populating apt-get cache...

+ apt-get update
Get:1 http://security.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]  
[...]

Mediante este comando se añadirán las fuentes a nuestro sistema y lo único que restará es instalar el servidor en sí:

# apt install nodejs

Ahora vamos a instalar la base de datos que guardará celosamente todo lo que escribamos en nuestro blog:

# apt install mysql-server mysql-client

Durante la instalación se nos pedirá el password de administrador que utilizaremos en los siguientes pasos. Revisando mi procedimiento anterior me di cuenta que no es necesario crear las bases de datos de testeo ya que vamos a trabajar con un entorno similar al de producción. Por esta razón sólo crearemos una base de datos:

# mysql -uroot -p
Enter password: ********  
Welcome to the MySQL monitor.  Commands end with ; or \g.  
Your MySQL connection id is 4  
Server version: 5.7.13-0ubuntu0.16.04.2 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its  
affiliates. Other names may be trademarks of their respective  
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database ghost;  
Query OK, 1 row affected (0.00 sec)

mysql> create user 'ghost'@'localhost' identified by 'YOUR_PASSWORD';  
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on ghost.* to 'ghost'@'localhost';  
Query OK, 0 rows affected (0.01 sec)

mysql> flush privileges;  
Query OK, 0 rows affected (0.00 sec)

mysql> quit  
Bye  

Ahora instalaremos nuestro querido y ligero Nginx. Éste tampoco tiene pérdida ya que está disponible en los repositorios oficiales de Ubuntu:

# apt install nginx

Creamos los directorios necesarios para el correcto funcionamiento del servidor con nuestra configuración:

# mkdir /var/cache/nginx
# chown www-data:www-data /var/cache/nginx
# chown www-data:www-data /var/www

Según el artículo que usamos en su día como referencia nuestro archivo de configuración, /etc/nginx/nginx.conf, quedaría así:

user www-data;  
worker_processes 4;  
pid /run/nginx.pid;

events {  
    worker_connections 768;
    # multi_accept on;
}

http {  
    proxy_cache_path    /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
    proxy_temp_path     /var/tmp;
    include             mime.types;
    default_type        application/octet-stream;
    sendfile            on;
    keepalive_timeout   65;

    gzip                on;
    gzip_comp_level     6;
    gzip_vary           on;
    gzip_min_length     1000;
    gzip_proxied        any;
    gzip_types          text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_buffers        16 8k;

    upstream ghost_upstream {
        server          127.0.0.1:2368;
        keepalive       64;
    }

    server {
        listen          80;
        server_name     libreadmin.es;

        if ($host = 'libreadmin.es' ) {
            rewrite     ^/(.*)$ http://www.libreadmin.es/$1 permanent;
        }

        location ~ ^/(ghost/signup/) {
            rewrite     ^/(.*)$ http://libreadmin.es/ permanent;
        }

        location ~ ^/(img/|css/|lib/|vendor/|fonts/|robots.txt|humans.txt) {
            root        /var/www/core/client/assets;
            access_log  off;
            expires     max;
        }

        location ~ ^/(shared/|built/) {
            root        /var/www/core;
            access_log  off;
            expires     max;
        }

        location ~ ^/(favicon.ico) {
            root        /var/www/core/shared;
            access_log  off;
            expires     max;
        }

        location ~ ^/(content/images/) {
            root        /var/www;
            access_log  off;
            expires     max;
        }

        location / {
            proxy_redirect      off;
            proxy_set_header    X-Real-IP           $remote_addr;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto   $scheme;
            proxy_set_header    Host                $http_host;
            proxy_set_header    X-NginX-Proxy       true;
            proxy_set_header    Connection          "";
            proxy_http_version  1.1;
            proxy_cache         one;
            proxy_cache_key     ghost$request_uri$scheme;
            proxy_pass          http://ghost_upstream;
        }

        location /nginx_stat {
            stub_status     on;
            access_log      off;
            allow           192.168.99.0/24;
            deny            all;
        }
    }

    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    include     /etc/nginx/conf.d/*.conf;
    include     /etc/nginx/sites-enabled/*;
}

Respecto al servidor web sólo nos faltaría activar la configuración específica para el blog, pero primero desactivamos la página por defecto:

# rm /etc/nginx/sites-enabled/default

Y nos creamos un archivo nuevo, /etc/nginx/sites-available/ghost, con el siguiente contenido:

server {  
    listen 0.0.0.0:80;
    server_name libreadmin.es;
    access_log /var/log/nginx/libreadmin.es.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header HOST $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://127.0.0.1:2368;
        proxy_redirect off;
    }
}

Para activarlo simplemente lo enlazamos en el directorio indicado y reiniciamos Nginx:

# ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/ghost
# systemctl restart nginx.service 

Si intentáis ver en el navegador el resultado hasta ahora, os aparecerá un bonito Bad Gateway ya que no hay ninguna aplicación respondiendo en el puerto que le hemos indicado, pero ya podremos instalar Ghost sobre esta infraestructura. Primero descargamos la última versión:

$ curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip

Y lo descomprimimos en el directorio adecuado:

# unzip -uo ghost.zip -d /var/www

Para instalar la aplicación en ése directorio ejecutamos lo siguiente:

# npm install --production
# npm install mysql
# npm install forever -g

Este último comando es para lanzar y parar una aplicación de Node.js, en nuestro caso el propio Ghost. Para poder iniciar sin problemas nuestro blog, lo mejor es crearnos un script que ejecute los comandos adecuados, lo llamaremos starter.sh y lo situaremos en el directorio /var/www. Su contenido es el siguiente:

#!/bin/sh

if [ $(ps aux | grep node | grep -v grep | wc -l | tr -s "\n") -eq 0 ]  
then  
    export PATH=/usr/local/bin:$PATH
    export NODE_ENV=production
    NODE_ENV=production forever start --sourceDir /var/www index.js >> /var/log/nodelog.txt 2>&1
fi  

Antes de lanzar nuestro blog debemos establecer los permisos adecuados en el directorio de la aplicación:

# chmod +x /var/www/starter.sh
# chown -R www-data:www-data /var/www/

Y ahora sí podemos activar Ghost:

# ./starter.sh 
# forever list
info:    Forever processes running  
data:        uid  command         script   forever pid  id logfile                 uptime  
data:    [0] n5Za /usr/bin/nodejs index.js 2180    2186    /root/.forever/n5Za.log 0:0:0:3.561  

Como véis el blog parece que se ha iniciado correctamente. Para comprobarlo ponemos en nuestro navegador la ip de la máquina en la que hemos realizado todos los pasos y deberíamos ver lo siguiente:
Vista inicial Para futuros testeos, es decir, cuando tengáis los backups de vuestro blog de producción establecidos y restauréis los datos en la máquina de testeo, yo suelo engañar a mi navegador poniendo en mi /etc/hosts la DNS del blog apuntando a la ip interna, así puedo navegar por todos los menús sin miedo a salirme en algún enlace al blog de producción.

Otra forma de restaurar el blog por completo, si no actualizáis durante mucho tiempo, o queréis saltar directamente a una versión limpia de Ghost, pero con el contenido de los posts que habéis creado hasta ahora, pasa por utilizar la exportación de datos en formato json. Esta posibilidad la tenéis en el apartado de Settings, bajo el epígrafe Labs: Export, Export the blog settings and data. Obtendréis un archivo con la configuración del blog, los usuarios y los posts, de esta forma cuando instaléis la nueva versión desde cero, como hemos explicado hoy, no tendréis más que importar este fichero, y como mucho, si utilizáis un tema diferente a Casper, copiarlo directamente en su directorio correspondiente para que vuestro blog aparezca completo. El único post que os sobrará será el que aparece por defecto en la instalación de Ghost, pero borrándolo ya tendréis el blog listo para seguir dando guerra en su nueva ubicación.

Ah, y como dije en el post original de instalación, no olvidéis consultar la guía de uso de Ghost.

Llevamos una época con los zombies muy de moda, no? Pues bien, hace unos años un artista multidisciplinar nos hacía botar salvajemente con su álbum Hellbilly Deluxe, se llamaba Rob Zombie y de este disco os aconsejo su brutal Living Dead Girl una descarga de adrenalina, no muy aconsejable en estas noches tan calurosas, pero por otro lado necesaria para afrontar la vuelta al trabajo.

Enjoy!