Ghost: revisited

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!