Cómo instalar Ghost CMS con Docker en Ubuntu 20.04

Página de inicio fantasma

Ghost es una plataforma de blogs de código abierto para ayudarte a crear un blog de aspecto profesional. Se lanzó en 2013 como una alternativa a WordPress porque se estaba volviendo demasiado complejo. Ghost está escrito en JavaScript y funciona con Node.js.

En este tutorial, exploraremos cómo instalar Ghost CMS usando Docker en un servidor con Ubuntu 20.04. También usaremos Nginx como proxy y el certificado Let’s Encrypt SSL para asegurar nuestra instalación.

requisitos previos

  • Un servidor con Ubuntu 20.04.
  • Un usuario sudo no root.
  • Asegúrate de que todo esté actualizado.
    $ sudo apt update 
    $ sudo apt upgrade
    

Paso 1: configurar el cortafuegos UFW

El primer paso es configurar el cortafuegos. Ubuntu viene con ufw (Cortafuegos sin complicaciones) por defecto.

Compruebe si el cortafuegos se está ejecutando.

$ sudo ufw status

Deberías obtener el siguiente resultado.

Status: inactive

Permita el puerto SSH para que el firewall no interrumpa la conexión actual al habilitarlo.

$ sudo ufw allow OpenSSH

Permita también los puertos HTTP y HTTPS.

$ sudo ufw allow 80
$ sudo ufw allow 443

Habilitar el cortafuegos

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Vuelva a comprobar el estado del cortafuegos.

$ sudo ufw status

Deberías ver una salida similar.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Paso 2: instale Certbot y obtenga el certificado SSL

Antes de continuar, debemos instalar la herramienta Certbot e instalar un certificado SSL para nuestro dominio.

Para instalar Certbot, usaremos el instalador del paquete Snapd. El repositorio oficial de Certbot ha quedado obsoleto y el paquete Certbot de Ubuntu tiene más de un año. Snapd siempre lleva la última versión estable de Certbot y debería usarla. Afortunadamente, Ubuntu 20.04 viene con Snapd preinstalado.

Asegúrese de que su versión de Snapd esté actualizada.

$ sudo snap install core 
$ sudo snap refresh core

Elimine cualquier versión anterior de Certbot.

$ sudo apt remove certbot

Instale Certbot.

$ sudo snap install --classic certbot

Utilice el siguiente comando para asegurarse de que el comando Certbot se pueda ejecutar creando un enlace simbólico al directorio /usr/bin.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Genere un certificado SSL.

$ sudo certbot certonly --standalone -d example.com

El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/example.com de su servidor.

Paso 3: instale Docker y Docker Compose

El primer paso es instalar Docker Engine y Docker Compose. Primero, desinstale cualquier versión anterior de Docker.

$ sudo apt remove docker docker-engine docker.io containerd runc

Instale algunos paquetes necesarios para que se ejecute Docker.

$ sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

Agregue la clave GPG oficial de Docker.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Agregue el repositorio oficial de Docker.

$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Actualice los repositorios del sistema.

$ sudo apt update

Instale la última versión de Docker Engine.

$ sudo apt install docker-ce docker-ce-cli containerd.io

Verifique que Docker Engine esté funcionando e instalado correctamente.

$ sudo docker run hello-world

De forma predeterminada, Docker requiere sudo para ejecutarse. Para evitar eso, podemos agregar la cuenta de usuario actual al grupo de usuarios de Docker.

$ sudo usermod -aG docker ${USER}

Para aplicar la nueva pertenencia al grupo, cierre la sesión y vuelva a iniciarla o use el siguiente comando.

$ su - ${USER}

Ahora, puede ejecutar los comandos de la ventana acoplable sin usar sudo.

A continuación, descargue la versión estable actual de Docker compose.

sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Al momento de escribir este tutorial, 1.28.6 es la última versión de Docker compose. Siempre puede cambiar o elegir una versión diferente en el comando comprobando desde el Github lanza la página de Docker compose.

Aplique el permiso ejecutable a la versión instalada de Docker compose.

$ sudo chmod +x /usr/local/bin/docker-compose

Pruebe la instalación.

$ docker-compose --version
docker-compose version 1.28.6, build 5db8d86f

Paso 4 – Instalar fantasma

La instalación de Ghost constará de tres componentes: el paquete Ghost, un servidor de base de datos como MySQL y un servidor web (Nginx). Todos estos servicios se pueden instalar utilizando un único archivo de composición de Docker.

Crear archivo de redacción de Docker

Primero, cree un directorio para almacenar y ejecutar su archivo de composición de Docker.

$ mkdir ghost && cd ghost

Cree un archivo llamado docker-compose.yml y ábralo con el editor Nano.

$ nano docker-compose.yml

Pegue el siguiente código en el archivo. Reemplaza ejemplo.com con tu dominio e inserta una contraseña de base de datos en lugar del valor de tu_contraseña. Mantenga los mismos valores para la base de datos__conexión__contraseña y MYSQL_ROOT_PASSWORD. Reemplace con el nombre de usuario de su servidor.

version: '3.3'
services:

  ghost:
    image: ghost:latest
    restart: always
    depends_on:
      - db
    environment:
      url: https://example.com
      database__client: mysql
      database__connection__host: db
      database__connection__user: ghost
      database__connection__password: ghostdbpass
      database__connection__database: ghostdb
      mail__transport: SMTP
      mail__options__host: {Your Mail Service host}
      mail__options__port: {Your Mail Service port}
      mail__options__secureConnection: {true/false}
      mail__options__service: {Your Mail Service}
      mail__options__auth__user: {Your User Name}
      mail__options__auth__pass: {Your Password}
    volumes:
      - /home/<username>/ghost/content:/var/lib/ghost/content

  db:
    image: mariadb:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_mysql_root_password
	  MYSQL_USER: ghost
      MYSQL_PASSWORD: ghostdbpass
      MYSQL_DATABASE: ghostdb
    volumes:
      - /home/<username>/ghost/mysql:/var/lib/mysql

  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    restart: always
    depends_on:
      - ghost
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /usr/share/nginx/html:/usr/share/nginx/html

El archivo de composición de Docker crea algunos puntos de montaje, es decir, asigna ciertos directorios en el servidor a directorios dentro del contenedor.

  • Los directorios /var/lib/ghost/content y /var/lib/mysql dentro de sus contenedores están asignados a /home//ghost/content y /home//ghost/mysql en el servidor.
  • Nginx usa el enlace /etc/letsencrypt/ para acceder a los certificados de Let’s Encrypt desde el servidor.
  • Nginx también necesita acceso al directorio de usuarios /usr/share/nginx/html para que pueda acceder a los archivos de Let’s Encrypt Challenge para el certificado.

En el archivo anterior, también hemos incluido opciones para configurar el correo. Si está utilizando un servicio de correo SMTP popular como Mailgun, Mailjet, Mandrill, Postmark, Sendgrid, SendCloud, SES, Zoho o Gmail, simplemente puede agregar el nombre del servicio y su nombre de usuario y contraseña SMTP y eliminar el resto de los campos. De lo contrario, complete todas las demás opciones y elimine el nombre del servicio y aún debería funcionar. Puedes consultar más opciones de correo en Documentación de Ghost sobre las opciones de correo.

Cree directorios para todos los montajes de enlace descritos anteriormente (excepto para /etc/letsencrypt, que ya se creó cuando creamos el certificado antes)

$ cd ~/ghost
$ mkdir content
$ mkdir mysql
$ sudo mkdir -p /usr/share/nginx/html

Crear la imagen acoplable de Nginx

El archivo de redacción de Docker que creamos se basa en la imagen de Nginx Docker. Para que funcione, debemos incluir un archivo de configuración personalizado para Nginx que funcionará con Ghost.

Cree un directorio para esta imagen en el directorio actual.

$ mkdir nginx

Cree un archivo llamado Dockerfile en este directorio.

$ touch nginx/Dockerfile

Pegue el siguiente código en el Dockerfile.

FROM nginx:latest
RUN rm /etc/nginx/conf.d/default.conf
COPY ghost.conf /etc/nginx/conf.d

El código anterior le indica a Docker que use la última imagen de Nginx. También elimina el archivo de configuración predeterminado de Nginx y copia el archivo de configuración personalizado que hemos creado para nuestro Ghost CMS.

Cree un archivo llamado ghost.conf en el directorio nginx.

$ touch nginx/ghost.conf

Pegue el siguiente código en el archivo ghost.conf. Reemplace todas las instancias de ejemplo.com con su dominio.

server {
  listen 80;
  listen [::]:80;
  server_name example.com;
  # Useful for Let's Encrypt
  location /.well-known/acme-challenge/ { root /usr/share/nginx/html; allow all; }
  location / { return 301 https://$server_name$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com;
    
  access_log /var/log/nginx/ghost.access.log;
  error_log /var/log/nginx/ghost.error.log;
  client_max_body_size 20m;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers on;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://ghost:2368;
  }
}

La configuración anterior redirigirá todas las solicitudes HTTP a HTTPS y servirá como un proxy para que el servicio Ghost lo sirva a través de su dominio.

Paso 5 – Ejecute el sitio

Ejecute el siguiente comando desde el directorio fantasma para iniciar el servicio Ghost.

$ docker-compose up -d

Ahora, puede verificar su instalación abriendo https://example.com en su navegador web. Es posible que Docker tarde varios minutos en encender todos los servicios, por lo que es posible que deba actualizar si no ve su blog de inmediato.

Página de inicio fantasma

Si su sitio no aparece en el navegador, debe revisar los registros de Docker. Para eso, primero cierra tu contenedor.

$ cd ghost
$ docker-compose down

Ejecute Docker compose en un estado adjunto para ver los registros generados por cada contenedor.

$ docker-compose up

Para cerrar el contenedor y volver al indicador de bash, presione CTRL+C. Una vez que haya terminado de solucionar el problema, puede ejecutar el contenedor nuevamente y su blog debería estar visible esta vez.

Paso 6 – Configuración completa

Para terminar de configurar su blog de Ghost, visite https://example.com/ghost en su navegador. El /fantasma adicional al final del dominio de su blog lo redirige al Panel de administración de Ghost o, en este caso, a la configuración, ya que está accediendo a él por primera vez.

Página de configuración fantasma

Aquí, se le pedirá que cree su cuenta de administrador y elija un título de blog.

Detalles de configuración fantasmaAnuncio publicitario

También puede invitar a miembros del personal o colaboradores adicionales para su blog, lo que también puede hacer más tarde si elige omitir ahora.

Página de invitación del personal fantasma

Al final de la configuración, aparecerá el panel de administración de Ghost.

Panel de administración fantasma

Si desea cambiar al modo oscuro, puede hacerlo haciendo clic en el interruptor junto al botón de configuración en la parte inferior de la página de configuración.

Cambio de modo fantasma oscuro

Ya verá algunas publicaciones predeterminadas que son básicamente guías para ayudarlo a navegar y usar Ghost. Puede anular su publicación o eliminarlos y comenzar a publicar.

Paso 7 – Actualizar fantasma

En nuestro archivo de composición de Docker, extraemos la última versión de Ghost disponible en el momento de la instalación, lo que facilita la actualización de su blog de Ghost.

Para actualizar, debe cerrar su contenedor, extraer las imágenes más recientes y luego ejecutar el contenedor nuevamente.

$ docker-compose down
$ docker-compose pull && docker-compose up -d

Paso 8: renueve su certificado SSL de Let’s Encrypt

Los certificados de Let’s Encrypt son válidos solo por 90 días. Por lo tanto, debemos configurar un cronjob que renovará el certificado automáticamente.

Abra Crontab en su editor.

$ sudo crontab -e

Pegue la siguiente línea al final que ejecutará Certbot a las 11 p. m. todos los días. Reemplaza ejemplo.com con tu dominio.

0 23 * * *   certbot certonly -n --webroot -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'

La ejecución a las 11 p. m. todos los días no significa que su certificado se renovará todos los días, ya que Certbot renovará su certificado solo si su fecha de vencimiento es dentro de los 30 días. Ejecutar esto todas las noches le da al script varias oportunidades para intentarlo antes de que caduque.

El comando anterior también reiniciará el servidor Nginx dentro del contenedor Docker después de la renovación exitosa.

Puede probar el cronjob usando la opción –dry-run de Certbot.

$ sudo bash -c "certbot certonly -n --webroot --dry-run -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'"

Conclusión

Esto concluye nuestro tutorial sobre cómo configurar Ghost CMS en su servidor basado en Ubuntu 20.04 usando Docker. Si tiene alguna pregunta o comentario, compártalos en los comentarios a continuación.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *