By

Migrando de Wordpress a Ghost

¡Hola!

Hace ya bastante tiempo que no pasaba por aquí para escribir y compartir con el resto del mundo, pero he estado bastante liado (la excusa de siempre) y además decidí hace ya algún tiempo migrar mi blog de Wordpress a Ghost, que es de lo que vengo escribiendo hoy.

Pero, como siempre, empecemos por el principio…

¿Qué es Ghost?

Ghost es una plataforma de blogging de reciente aparición y que está teniendo bastante repercusión en Internet. El proyecto empezó en Kickstarter donde se pedía financiación para poder llevar a cabo la creación de una plataforma Open Source para blogging, que ofreciese una experiencia placentera a la hora de escribir y que tuviera como objetivo eso, ser una plataforma bien diseñada para hacer una sola cosa: publicar.

Su creador es John O’Nolan y es una aplicación Node.js que hace uso del framework Express. Ghost usa SQLite como base de datos por defecto, lo cual indica que puede ejecutarse casi en cualquier sitio, sin embargo, usa JugglingDB como ORM, que añade el soporte para el uso de otras bases de datos.

Además Ghost está disponible desde NPM, haciendo su instalación extremadamente simple y rápida en la mayoría de entornos.

¿Por qué he migrado de Wordpress a Ghost?

A decir verdad Wordpress cumplía sobradamente mis necesidades como blogger ocasional, precisamente por eso, , porque Wordpress ya me empezaba a quedar grande en cuanto a consumo de recursos para un blog pequeño como es el mío. Realmente no usaba muchos plugins, que normalmente añaden carga y consumo de recursos, sino solamente algunos que necesitaba como:

Todo esto ya lo tengo de serie en Ghost, excepto Jetpack que es propio de Wordpress, pero que realmente solo servía para optimizar tu Wordpress, mejorar el sharing de los posts, y más funcionalidades que van agregando poco a poco al plugin con cada actualización.

Además he de decir que estaba un poco harto ya de Wordpress y que, en mi opinión se ha convertido en “un monstruo” que está muy lejos de parecer para lo que se pensó en un principio. Ha pasado de ser una plataforma de blogging a ser un Framework PHP para crear sitios web, y que además puedes bloguear. Todo esto sin ánimo de ofender a nadie :-)

Tras probar la primera versión de Ghost en mi portatil, quedé bastante impresionado con la simplicidad de su instalación y uso, es algo que llevaba ya esperando y buscando mucho tiempo. De hecho, el verano pasado estuve barajando la posibilidad de usar Pelican (con el que llegué a contactar con el creador y contribuir con él), Hyde o Toto, que son generadores de sitios estáticos, es decir, tienes tus posts escritos en Markdown y generas un blog o website estático a partir de ellos.

Pero al fin me encontré con Ghost y quedé gratamente impresionado, desde el cual estoy ya escribiendo este post. He de decir también que el proyecto es aún muy reciente y algunas cosas como plugins están aún por llegar; pero en cuanto a themes ya se pueden encontrar algunos gratuitos y de pago en el Marketplace.

¿Lo instalamos?

Este blog está instalado y funcionando sobre una Debian 7 (Wheezy) en la cual el requisito fundamental de Ghost, que es Node.js, no se encuentra en los repositorios; por lo que he tenido que realizar una instalación alternativa.

Node.js

Hay varias formas de instalar Node.js. Podemos descargar el código, compilar e instalar; el mismo proceso de siempre. Pero en este caso, me ha parecido mejor crear un paquete Debian (.deb), que a la larga es más fácil de desinstalar y/o actualizar.

Para ello, primero instalaremos algunas dependencias necesarias en el sistema:

sudo apt-get install python g++ make checkinstall

A continuación, descargamos el código fuente de Node.js, descomprimimos el paquete y accedemos al directorio:

mkdir ~/node_js_src && cd $_
wget -N http://nodejs.org/dist/node-latest.tar.gz
tar xzvf node-latest.tar.gz && cd node-v*

Configuramos la compilación del paquete:

./configure

Pero esta vez no ejecutaremos make && make install, sino que utilizaremos la utilidad checkinstall con la que podremos modificar los metadatos del paquete:

checkinstall

Nota: Es necesario eliminar la v que aparece en la versión de Node.js (v0.10.24) y dejar solo los valores numéricos (0.10.24). En caso contrario, la compilación fallará.

Por último, y una vez generado el paquete .deb, lo instalamos:

sudo dpkg -i node_*

Ghost

Lo primero es descargar el código fuente de Ghost, en este caso sera la versión latest que corresponde a la v0.3.3, en el momento de escribir este post:

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

Descomprimimos el zip descargado y accedemos al directorio:

$ unzip -uo ghost.zip -d ghost
$ cd /path/to/ghost

A continuación, para instalar Ghost y todas sus dependencias, será necesario ejecutar el siguiente comando:

$ npm install --production

Y una vez finalizada la instalación, podemos iniciar Ghost en modo desarrollo con la siguiente instrucción:

$ npm start

También podemos iniciarlo en modo producción con la siguiente instrucción:

$ npm start --production

Ghost estará ejecutándose en http://127.0.0.1:2368

Nota:: podemos ejecutar Ghost con diferentes configuraciones, dependiendo si estamos en modo desarrollo o producción, para ello es recomendable ajustar esta configuración en el fichero config.js.

Para acceder a la administración de Ghost, es necesario acceder a http://127.0.0.1:2368/ghost y crear el usuario administrador para poder hacer login.

Nginx

Este paso no es necesario si lo que quieres es probar Ghost en tu portatil / pc. Pero sí que es recomendable si vas a pasar tu blog con Ghost a producción, que era mi caso. Es decir, tendremos como servidor web a Nginx escuchando en el puerto 80, que nos ayudará a gestionar mejor las peticiones de los usuarios, cacheo y compresión de los datos, etc.

Para ello, obviamente necesitamos tener instalado Nginx en nuestro servidor. Tan simple como ejecutar la siguiente instrucción:

$ sudo apt-get install nginx

En mi caso, edité el fichero de configuración /etc/nginx/nginx.conf y dejé la configuración de la siguiente forma:

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

events {
    worker_connections 768;
}

http {

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    server_names_hash_bucket_size 64;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

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

    gzip on;
    gzip_disable "msie6";

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

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

Hecho esto, forzamos a Nginx para que recargue la configuración:

$ sudo service nginx configtest
$ sudo service nginx reload

Ya solo necesitamos configurar un VirtualHost en Nginx para servir el blog a través del puerto 80. En mi caso, la configuración que he utilizado ha sido la siguiente:

server {
    listen 80;
    server_name blog.example.org;
    root /path/to/blog.example.org/;
    index index.php;

    if ($http_host != "blog.example.org") {
        rewrite ^ http://blog.example.org$request_uri permanent;
    }

    location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:2368;
    }

    location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
        access_log off;
        expires 30d;
        add_header Pragma public;
        add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
        proxy_pass http://127.0.0.1:2368;
    }

    location = /robots.txt { access_log off; log_not_found off; }
    location = /favicon.ico { access_log off; log_not_found off; }

    location ~ /\.ht {
        deny all;
    }
}

Por último, activamos el VirtualHost y recargamos la configuración de Nginx:

$ cd /etc/nginx/sites-enabled
$ sudo ln -s ../sites-available/blog.example.org
$ sudo service nginx configtest
$ sudo service nginx reload

¿Migramos?

La migración de Wordpress a Ghost lógicamente comprende más pasos que los listados anteriormente, que abarcan solamente el setup de Ghost inicialmente. Estos pasos y/o problemas durante la migración son realmente el objetivo de este post, así que aparecerán listados a continuación con la respectiva solución que he decidido aplicar para cada uno de ellos.

He de decir que en mi caso, la migración ha supuesto pasos adicionales y la resolución de algunos problemas que me he ido encontrando

#1 Extraer los datos de Wordpress

Bueno, una vez que tenemos Ghost funcionando, el siguiente paso para realizar la migración desde Wordpress es extraer todos los posts para importarlos, posteriormente, en Ghost. Para solucionar esto, seguí los siguientes pasos:

  1. Instalar en Wordpress un plugin llamado Ghost, que permite exportar tu blog para luego importarlo en una instalación de Ghost. Instalar este plugin es muy sencillo, desde el panel de administración de Wordpress > Plugins > Add new, buscarlo e instalarlo.
  2. Una vez instalado el plugin y desde Dashboard de Wordpress > Tools > Export to Ghost. Haciendo click en download ghost file obtendremos un fichero JSON con todos los posts de nuestro blog.

#2 Importar posts en Ghost

Una vez tenemos todos nuestros posts en un fichero JSON, el siguiente paso lógico es importar esos datos en nuestra instalación Ghost. En este caso, los pasos a seguir son los siguientes:

  1. Acceder a la sección debug de Ghost en http://blog.example.org/ghost/debug
  2. Click en Choose File y seleccionar el fichero JSON descargado desde el plugin de Ghost en Wordpress.
  3. Click en Import.

Si todo ha ido bien, todos los posts deberían estar visibles en Ghost.

#3 Exportar los comentarios

En mi caso he tenido que exportar los comentarios que había en mis posts, ya que estaba usando hasta ahora el sistema de comentarios propio de Wordpress.

Ghost no tiene un sistema de comentarios propio, así que se recomienda usar un servicio externo como Disqus. Disqus funciona muy bien y se puede decir que es el servicio para alojar comentarios en websites / blogs por excelencia, así que decidí migrar todos los comentarios a Disqus.

Hay varias formas de hacerlo, pero yo solo voy a describir la que yo usé, que es la exportación automática:

  1. Registrar un usuario en Disqus.
  2. Crear un sitio nuevo en Disqus y configurar un nombre para este sitio.
  3. En Wordpress, instalar el plugin Disqus Comment System.
  4. Acceder a la configuración del plugin y configurar el nombre del sitio creado en Disqus.
  5. En la configuración del plugin, click en Export comments to Disqus.

Nota: La exportación a Disqus no se inicia de forma instantanea, por lo que puede extenderse a varias horas.

#4 Redirecciones permanentes en URLs

En mi blog en Wordpress tenía configuradas las URLs de los posts con la siguiente estructura:

/YYYY/MM/nombre-del-post

Por lo que se construían URLs como las siguientes:

http://blog.manuelviera.es/2011/01/configurando-los-clientes-sip/
http://blog.manuelviera.es/2011/01/contribucion-a-trac-2/
http://blog.manuelviera.es/2011/01/crontab/
http://blog.manuelviera.es/2011/01/diagrama-y-componentes-de-red-con-asterisk/

Ghost no permite (aún) configurar URLs limpias de esta forma, sino que construye la URL incluyendo solamente el nombre del post. Para que Google no me penalice y los visitantes puedan seguir accediendo al blog desde las URLs ya indexadas en los buscadores, he tenido que añadir rewrites en el VirtualHost de Nginx. Algunos ejemplos de redirecciones permanentes son:

rewrite ^/2011/01/configurando-los-clientes-sip/ http://blog.manuelviera.es/configurando-los-clientes-sip/ permanent;
rewrite ^/2011/01/contribucion-a-trac-2/ http://blog.manuelviera.es/contribucion-a-trac-2/ permanent;
rewrite ^/2011/01/crontab/ http://blog.manuelviera.es/crontab/ permanent;
rewrite ^/2011/01/diagrama-y-componentes-de-red-con-asterisk/ http://blog.manuelviera.es/diagrama-y-componentes-de-red-con-asterisk/ permanent;
rewrite ^/2011/01/ficheros-de-configuracion-y-directorios-en-asterisk/ http://blog.manuelviera.es/ficheros-de-configuracion-y-directorios-en-asterisk/ permanent;

#5 Remapear URLs en los comentarios de Disqus

Una vez exportados todos los comentarios a Disqus me di cuenta que había un problema, y es que, lógicamente, Disqus almacena la URL donde se creó el comentario.

Esto supone un problema y es que, aunque las redirecciones estén hechas y los comentarios exportados, si la URL que tiene Disqus almacenada para un comentario, no concuerda con la URL del post que se está visualizando, el comentario no se ve al final de ese post.

Para solucionar esto tuve que remapear todas las URLs, que Disqus tenía almacenadas, por las nuevas. Para ello hay que seguir los siguienes pasos:

  1. Acceder al panel de administración de Disqus.
  2. Click en pestaña Discussions > Tools > Upload a URL map.
  3. Componer un fichero CSV que contenga un listado de todas las URLs antiguas y nuevas, separadas por comas entre sí (URL antigua,URL nueva).

#6 Arreglar imágenes en los posts

En mi caso he tenido problemas con las imágenes ya que la exportación de los artículos no contemplaba la exportación de esta imágenes. Se recomienda hacer uso de un servicio externo de almacenamiento de imágenes pero en mi caso he querido alojar las imágenes en mi propio servidor, bajo un dominio diferente (static.blog.manuelviera.es).

Para arreglar este problema seguí los siguientes pasos:

  1. Crear un directorio nuevo dentro del código de Ghost.

    $ sudo mkdir /path/to/ghost/content/static/
    
  2. Crear un nuevo VirtualHost en Nginx con el siguiente contenido:

    server {
        listen 80;
        server_name static.blog.example.org;
        root /path/to/blog.example.org/content/static/;
        index index.php;
    }
    
  3. Mover todas las imágenes especificadas a dicha ruta en el servidor.

  4. Modificar la URL a la que apunta cada imagen en cada post hacia la nueva ubicación.

¡Al fin! Pues esta ha sido mi experiencia migrando mi blog personal desde Wordpress a Ghost, espero no haberme dejado nada, pero si detectáis que algo no funciona como debe, por favor, reportádmelo! :-)

Espero que os sea de ayuda, ¡no os olvidéis de comentar! Para cualquier duda estoy a vuestra disposición :-D

Un saludo y ¡felices fiestas! Manu.