/ Azure

Como poner en producción Ghost 1.x en Azure Web Apps.

Como saben mi blog está en la plataforma Ghost alojado en Microsoft Azure, hace algunas semanas el equipo de desarrollo libero la versión 1.x (actualmente va en la 1.9) y esta se hizo incompatible con entornos Windows ya que implementaron su propio CLI, con esto me pusieron en un aprieto, o seguía usando la versión 0.11 o creaba una máquina virtual con Ubuntu para mí blog.

Perdiendo así los beneficios de las web apps que nos proporciona esta plataforma, entre los que se encuentra principalmente iisnode que hace que nuestras web apps basadas en NodeJS escalen de forma automática y que sean multi hilo por lo tanto puedan aprovechar todos los núcleos del procesador, sin olvidarnos de copias de seguridad automáticas, CDN, y un largo etc.

Visto lo anterior y decidido a no perder esos beneficios me he puesto manos a la obra colaborando con un miembro del equipo de desarrollo para hacer funcionar esta magnífica plataforma de blogs en una magnifica plataforma de cloud, acompáñenme.

Felix Rieseberg tiene un repo donde instaló un despliegue de un solo clic para configurar un blog Ghost en Azure el único problema es que no se ha actualizado para Ghost 1.x, sigue en la versión 0.11.9.

Nueva herramienta de CLI

En esta nueva versión Ghost ha introducido una herramienta de línea de comandos CLI que automatiza el proceso de instalación de un blog, pero desafortunadamente, no he encontrado una manera de usarlo en el servicio de aplicaciones de Azure.

Además, no creo que funcione con las modificaciones de código que se requieren. Por lo tanto, no traté de utilizarlo.

Pero ¿suponiendo que tenemos acceso al PowerShell en la Web App de Azure se debería poder instalar no?

Nuevo Sistema de Configuración

Ghost 1.x tiene un sistema de configuración completamente nuevo que presenta un problema con la forma en que Felix configuro la versión anterior.

Irónicamente, se supone que el nuevo sistema de configuración facilita el soporte de más fuentes de configuración (por ejemplo, variables env, archivos json, etc.), pero en este caso particular, lo ha hecho más difícil.

Cuando alojas una aplicación de NodeJS en Azure, se ejecutará a través de iisnode, esto hace posible disfrutar de una escalabilidad horizontal automática y aprovechar al máximo los recursos, iisnode pasa el puerto en una variable de entorno llamada PORT lo que parece bastante sencillo de implementar.

Anteriormente Ghost sólo permitía poner un config.js en la raíz de la app, de esta forma se podía utilizar cualquier código JavaScript arbitrario para configurar la aplicación.

Ahora no se puede hacer eso y hay que pasar una variable env llamada SERVER_PORT o configurar el puerto en un archivo json como este:

{
    "server": {
        "port": 69420
    }
}

Larga historia corta, tuve que modificar core/server/config/index.js para extraer el puerto específicamente de la variable env PORT:

nconf.set('server:port', process.env.PORT);

No sé si es la mejor opción, pero es la forma que encontré para hacer esto y funciona perfectamente.

La otra cosa que tenía que hacer era agregar un archivo iisnode.yml y un web.config con la configuración estándar para alojar una aplicación de NodeJS en Azure, también incluí algunas cosas de HSTS en el web.config ya que sólo quiero usar HTTPS.

Creando la base de datos

Ghost en su versión anterior crea una base de datos SQLite automáticamente si no encontró una al iniciar por primera vez.

Esto hizo increíblemente fácil comenzar con él, pero tenía sus limitaciones, con la introducción de la nueva herramienta CLI, es esta la que se encarga de crear la base de datos y como dije antes, no podía ejecutar el CLI en Azure App Service.

Indagando un poco encontré que knex-migrator es lo que Ghost utiliza de forma interna para crear la base de datos así solo faltaba ejecutarlo de forma manual para que funcione, por lo tanto he creado un archivo db.js en la raíz de la aplicación el cual tenemos que ejecutar con PowerShell despues de npm install con el comando node db.js:

var KnexMigrator = require('knex-migrator');
var knexMigrator = new KnexMigrator({
    knexMigratorFilePath: __dirname
});

knexMigrator.init();

Esto supone que ya ha creado los archivos de configuración config.development.json y/o un config.production.json en la raíz con la base de datos que desea. Para mí funciona perfecto SQLite:

{
    "database": {
        "client": "sqlite3",
        "connection": {
            "filename": "content/data/ghost.db"
            }
      }
}

Despliegue en Azure

Estos pasos suponen que ya usted sabe cómo configurar la implementación continua desde un repositorio de Github o Visual Studio Team Services.

Antes de configurar el despliegue automático es necesario configurar la url de la aplicación como una variable de entorno así que nos vamos a la configuración de nuestra aplicación web y agregamos la siguiente configuración:
app-setting-1

Configurado lo anterior estamos listos para iniciar el despliegue automático, una vez configurado esperamos a que el primer despliegue finalice y veremos algo como esto:
despliegue

Cuando la polímita nos indique que el despliegue se ha hecho correctamente iremos a las herramientas avanzadas y abriremos una consola PowerShell en la siguiente ruta \home\site\wwwroot> en esta ruta ejecutaremos los siguientes comandos en orden:

npm install
node db.js

Una vez que finalicen los procesos desencadenados por estos comandos vamos a la página principal de nuestra aplicación y la reiniciamos, esperamos unos 5 minutos y accedemos a nuestra url en donde se verá el contenido por defecto de Ghost y si accedemos a /ghost se iniciara el asistente de configuración.

Esto solo es necesario la primera vez ya que si después actualizamos nuestro repositorio de origen la aplicación será actualizada correctamente de forma automática.

Si quieren hacer un fork o utilizar mi repositorio como repo de origen son libres de hacerlo.

Saludos, Jesús Verduzco (El Yisus)