Práctica 9 de IAW - Instalación de WordPress en distintos niveles

Esta práctica la realizaremos por fases, en la primera fase, fase-0, realizaremos la instalación de WordPress en un único nodo o instancia, en la segunda fase, fase-1, realizaremos la misma instalación en dos niveles, un frontend (servidor web Apache2) y un backend (servidor SQL), por último, en la tercera fase, fase-2, realizaremos la instalación de un balanceador de carga, dos frontend, un backend y un servidor NFS para almacenar datos compartidos para los dos frontend.

Los requisitos para las tres fases con una instancia Ubuntu Server 22.04 o Ubuntu Server 20.04 con al menos 2GB de RAM. Tendremos en cuenta los puertos de entrada en cada máquina que tendremos que abrir:

Prepararemos la siguiente estructura de directorios y archivos:

Crearemos un repositorio para la práctica.

Warning

Las imágenes pueden que funcionen o no

fase-0

Iniciaremos esta práctica explicando la primera fase, mediante scripting como con ansible.

Crearemos en No-IP un dominio asignado a una dirección IP.

No-IP

scripting

Una vez tengamos la estructura de directorios y archivos necesarios, empezaremos con los archivos que tenemos que nos sirven de plantillas para usar una configuración concreta en la instancia.

000-default.conf

Este archivo lo necesitaremos para permitir la creación de archivos htaccess mediante AllowOverride All y permitir que el sitio web funcione correctamente.

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    #LogLevel info ssl:warm

    <Directory "/var/www/html">
        AllowOverride All
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

dir.conf

Con este archivo priorizaremos el archivo index.php sobre el resto de los archivos.

<IfModule mod_dir.c>
        DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>

variables.sh

Este archivo nos permitirá tener variables globales para los scripts que las necesiten y no tener que cambiar el contenido de las variables en varios archivos.

DB_Name=wp_db
DB_User=wp_user
DB_Password=wp_pass

DB_Host=localhost

WP_Home=https://practicasiaw09jrrl.ddns.net
WP_SiteURL=https://practicasiaw09jrrl.ddns.net/wordpress

Certbot_Email=tetz_dqhwr17@yutep.com
Certbot_Domain=practicasiaw09jrrl.ddns.net

Las tres primeras líneas nos permiten establecer la base de datos con el usuario y la contraseña para ese usuario, la cuarta nos permite indicar dónde se encuentra la base de datos, en nuestro caso como está en la misma máquina será localhost. La cuarta variable nos permite indicar el formato de la URL que queremos para nuestro sitio web, la quinta variable establece la ruta local dónde se encuentra la instalación de WordPress, las dos últimas variables son para la obtención del certificado de Let's Encrypt usando Certbot.

install_lamp.sh

Instalaremos la pila LAMP en nuestra instancia, también copiaremos las dos plantillas a su respectiva ruta, habilitaremos el módulo rewrite para que WordPress pueda hacer cambios y reiniciaremos el servidor Apache2 para aplicar los cambios realizados.

apt-get update

apt-get upgrade -y

apt-get install apache2 -y

apt-get install mysql-server -y

apt-get install php libapache2-mod-php php-mysql -y

Como de costumbre, seguiremos los mismos pasos para la instalación de la pila LAMP.

cp ../conf/000-default.conf /etc/apache2/sites-available

cp ../conf/dir.conf /etc/apache2/mods-available

a2enmod rewrite

systemctl restart apache2

A continuación, copiaremos la primera plantilla, 000-default.conf a la ruta /etc/apache2/sites-available para permitir el uso de archivos .htaccess y que nuestro sitio web funcione correctamente en cuanto al contenido servido. Copiaremos la segunda plantilla, dir.conf a la ruta /etc/apache2/mods-available para priorizar los archivos index según formato, luego habilitaremos el módulo rewrite de Apache y reiniciaremos el servidor web.

config-https.sh

Este segundo script nos permitirá la configuración del servidor para usar el protocolo HTTPS, tendremos que instalar Certbot mediante Snap y obtener el certificado de Let's Encrypt. Este script lo hemos realizado en prácticas anteriores, por lo que realizaré una explicación superficial del script

source variables.sh

snap install core

snap refresh core

apt-get remove Certbot

snap install --classic Certbot

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

certbot --apache -m $Certbot_Email --agree-tos --no-eff-email -d $Certbot_Domain

Importaremos el archivo de variables e instalaremos Core mediante Snap, después actualizaremos Core y quitaremos la instalación por defecto de Certbot que viene con el sistema operativo, después instalaremos Certbot mediante Snap y solicitaremos el certificado de Let's Encrypt.

deploy_wordpress.sh

Con este script realizaremos el despliegue de WordPress en la instancia, necesitaremos descargar el código fuente de WordPress, así como Unzip, crear una base de datos, descomprimir los archivos en /var/www/html y personalizar WordPress.

source variables.sh

wget https://wordpress.org/latest.zip -O /tmp/latest.zip

apt install unzip -y

unzip /tmp/latest.zip -d /var/www/html

cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php

sed -i "s/database_name_here/$DB_Name/" /var/www/html/wordpress/wp-config.php

sed -i "s/username_here/$DB_User/" /var/www/html/wordpress/wp-config.php

sed -i "s/password_here/$DB_Password/" /var/www/html/wordpress/wp-config.php

sed -i "s/localhost/$DB_Host/" /var/www/html/wordpress/wp-config.php

En esta parte del script realizaremos la importación de las variables definidas, después descargaremos el código fuente de WordPress, instalaremos Unzip y descomprimiremos el contenido en /var/www/html, de forma que en la ruta deberemos tener tanto index.html como un directorio llamado wordpress.

A continuación, copiaremos el archivo wp-config-sample.php en la misma ruta con distinto nombre para realizar modificaciones sobre la copia, wp-config.php. Las modificaciones que deberemos hacer son la asignación de la base de datos, el usuario y su contraseña y la localización de la base de datos.

echo "DROP DATABASE IF EXISTS $DB_Name" | mysql -u root
echo "CREATE DATABASE $DB_Name CHARACTER SET utf8mb4" | mysql -u root

echo "DROP USER IF EXISTS $DB_User@'%'" | mysql -u root
echo "CREATE USER $DB_User@'%' IDENTIFIED BY '$DB_Password'" | mysql -u root
echo "GRANT ALL PRIVILEGES ON $DB_Name.* TO $DB_User@'%'" | mysql -u root

cp /var/www/html/wordpress/index.php /var/www/html

sed -i "s|wp-blog-header.php|wordpress/wp-blog-header.php|" /var/www/html/index.php

sed -i "/DB_COLLATE/a define('WP_HOME', '$WP_Home');" /var/www/html/wordpress/wp-config.php

sed -i "/WP_HOME/a define('WP_SITEURL', '$WP_SiteURL');" /var/www/html/wordpress/wp-config.php

chown www-data:www-data -R /var/www/html

Después, crearemos la base de datos junto al usuario y su contraseña y copiaremos el archivo index.php para ponerlo en un nivel superior, en /var/www/html para que en cuanto se acceda al dominio o a la dirección IP del servidor se acceda directamente sin tener que referenciar el directorio de instalación de WordPress en el equipo.

Por último, modificaremos el index.php para hacer referencia a la localización del archivo wp-blog-header.php y que nuestro WordPress funcione correctamente. También modificaremos el contenido del archivo wp-config.php para añadir un par de líneas que indicarán el formato de URL que tendrá el sitio y la ruta interna a los archivos de WordPress, además de cambiar el propietario y el grupo de html de forma recursiva.

ansible

Realizaremos la misma parte mediante ansible, de forma que modificaremos lo realizado mediante scripting para ajustarlo al uso de Ansible.

variables.yml

En este archivo tendremos las variables para usarlas en los playbooks que las necesiten.

Certbot:
  Email: tetz_dqhwr17@yutep.com
  Domain: practicasiaw09jrrl.ddns.net

Template_000_default:
  Local_Source: ../templates/000-default.conf.j2
  DocumentRoot: /var/www/html

Template_dir:
  Local_Source: ../templates/dir.conf.j2
  Directory_index: DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm

PHP_Packages:
  - php
  - libapache2-mod-php
  - php-mysql

Database:
  Name: wordpress_db
  User: wordpress_user
  Password: wordpress_pass
  Host: localhost

WordPress:
  Home: http://practicasiaw09jrrl.ddns.net
  SiteURL: http://practicasiaw09jrrl.ddns.net/wordpress

Introduciremos las variables que necesitamos dentro de otra variable que será la global para tenerlas agrupadas por función o máquina dónde se ejecutarán. De esta forma evitamos tener variables sueltas y evitamos el caos resultante.

Las dos primeras variables nos servirán para la obtención del certificado de Let's Encrypt y poder usar HTTPS, la tercera indica la ruta local del template 000-default.conf.j2 y la cuarta el contenido de la variable de dicho template. La quinta indica la ruta local del template dir.conf.j2 y la sexta el contenido de la variable de dicho template, en la séptima variable indicamos los paquetes de PHP que hay que instalar.

Las siguientes cuatro variables son para indicar la base de datos, el usuario y su contraseña y la localización de la base de datos. Las dos úNo-IPltimas son para la personalización de la URL de WordPress y la ruta interna de los archivos de WordPress en el equipo.

000-default.conf.j2

Al igual que hicimos con los scripts, crearemos una plantilla o template para copiar el template en el equipo local al equipo remoto y haremos unas modificaciones mediante variables, que en este caso, tenemos que hacer referencia a la variable global seguido de un punto (o dot) seguido de la variable que tiene el contenido que necesitamos.

<VirtualHost *:80>
    #ServerName www.example.org
    ServerAdmin webmaster@localhost
    DocumentRoot {{ Template_000_default.DocumentRoot }}

    #LogLevel info ssl:warm

    <Directory "{{ Template_000_default.DocumentRoot }}">
        AllowOverride All
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

El contenido del template es lo mismo, salvo que usaremos una variable para definir el directorio de localización de WordPress y si fuese necesario podríamos modificar el contenido de la variable sin tener que modificar el template.

dir.conf.j2

Al igual que con el scripting, priorizaremos las extensiones de los archivos index para que primero se nos muestre primero el index.php sobre el index.html.

<IfModule mod_dir.c>
        {{ Template_dir.Directory_index }}
</IfModule>

inventario

Definiremos los parámetros globales para el usuario de la instancia, la localización de la clave privada de la instancia en el equipo local y que no nos pregunte si queremos añadir el fingerprint o huella de la máquina. También especificaremos el grupo wordpress y la dirección IP que tiene la instancia en el momento de crearla o la dirección IP elástica si asignamos una a la instancia.

[wordpress]
18.204.227.200

[wordpress:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=/home/rayseink/claves/vockey.pem
ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new'

install_lamp.yml

Realizaremos la instalación de la pila LAMP y pasaremos los templates al equipo remoto, habilitaremos el módulo rewrite y reiniciaremos el servidor Apache2.

---
- name: Playbook para el despliegue de la pila LAMP
  hosts: wordpress
  become: true

  tasks:
    - name: Inclusión de variables para los templates
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Actualización de los repositorios
      ansible.builtin.apt:
        update_cache: true
        upgrade: true

    - name: Instalación del servidor web Apache2
      ansible.builtin.apt:
        name: apache2
        state: present

    - name: Instalación del servidor de bases de datos
      ansible.builtin.apt:
        name: mysql-server
        state: present

    - name: Instalación de PHP y módulos para conectar con la base de datos y Apache2
      ansible.builtin.apt:
        name: "{{ PHP_Packages }}"
        state: present

Hasta aquí es la inclusión del archivo de variables en el playbook para los dos templates que vamos a pasar al servidor, la actualización de los repositorios y los programas con respecto a los repositorios, la instalación de Apache2, MySQL Server y los paquetes de PHP.

    - name: Copiado del template 000-default.conf.j2 a la ruta /etc/apache2/sites-available
      ansible.builtin.template:
        src: "{{ Template_000_default.Local_Source }}"
        dest: /etc/apache2/sites-available/000-default.conf
        mode: 0644

    - name: Copiado del template dir.conf.j2 a la ruta /etc/apache2/mods-available
      ansible.builtin.template:
        src: "{{ Template_dir.Local_Source }}"
        dest: /etc/apache2/mods-available/dir.conf
        mode: 0644

    - name: Habilitación del módulo rewrite de Apache2
      community.general.apache2_module:
        name: rewrite
        state: present
      notify: Reiniciar servidor Apache2

  handlers:
    - name: Reiniciar servidor Apache2
      ansible.builtin.service:
        name: apache2
        state: restarted

Usaremos el módulo ansible.builtin.template para pasar los templates locales al servidor y habilitaremos el módulo rewrite de Apache2 para que WordPress pueda realizar cambios en el servidor web, por último reiniciaremos Apache2 para que se apliquen los cambios.

https.yml

Con este playbook realizaremos la descarga de Certbot y la obtención del certificado de Let's Encrypt para poder usar HTTPS en nuestro servidor.

---
- name: Descarga de Certbot mediante Snap y obtención de certificado de Let's Encrypt
  hosts: wordpress
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Desinstalación de la instalación previa de Certbot que viene con el sistema operativo
      ansible.builtin.apt:
        name: certbot
        state: absent

    - name: Instalación de Certbot mediante Snap
      community.general.snap:
        name: certbot
        classic: true
        state: present

    - name: Descarga de certificado para TLS / SSL
      ansible.builtin.command: certbot --apache -m "{{ Certbot_Email }}" --agree-tos --no-eff-email -d "{{ Certbot_Domain }}"
      register: realizar_cambio
      changed_when: realizar_cambio.rc == 0

Incluiremos el archivo de variables en el playbook y desinstalaremos Certbot que viene con el sistema operativo, después instalaremos mediante Snap la versión correcta de Certbot y obtendremos el certificado de Let's Encrypt.

deploy_wordpress.yml

Realizaremos el despliegue de WordPress en el equipo remoto, crearemos una base de datos con un usuario y una contraseña y haremos las modificaciones pertinentes para WordPress.

---
- name: Despliegue de WordPress en un único nodo
  hosts: wordpress
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Instalación de Unzip para descomprimir archivos
      ansible.builtin.apt:
        name: unzip
        state: present

    - name: Descarga del código fuente de WordPress en directorio temporal
      ansible.builtin.get_url:
        url: https://wordpress.org/latest.zip
        dest: /tmp/wordpress.zip
        mode: 664

    - name: Descompresión de WordPress en /var/www/html
      ansible.builtin.unarchive:
        src: /tmp/wordpress.zip
        dest: /var/www/html
        remote_src: true

    - name: Borrado del archivo comprimido en el directorio temporal
      ansible.builtin.file:
        path: /tmp/wordpress.zip
        state: absent

    - name: Copiado de archivo wp-config-sample.php a wp-config.php
      ansible.builtin.copy:
        src: /var/www/html/wordpress/wp-config-sample.php
        dest: /var/www/html/wordpress/wp-config.php
        mode: 0644
        remote_src: true

Empezaremos incluyendo el archivo de variables en el playbook, después instalaremos Unzip para la descompresión de archivos, descargaremos el código fuente de WordPress en el directorio temporal, descomprimiremos el archivo de WordPress en /var/www/html, borraremos el archivo comprimido que contiene WordPress y copiaremos el archivo wp-config-sample.php en la misma ruta para modificar el nombre del archivo a wp-config.php usando el módulo ansible.builtin.copy y con la opción remote_src: true para indicar que es en el equipo remoto.

    - name: Modificación del archivo wp-config.php para especificar la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: database_name_here
        replace: "{{ Database.Name }}"

    - name: Modificación del archivo wp-config.php para especificar el usuario de la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: username_here
        replace: "{{ Database.User }}"

    - name: Modificación del archivo wp-config.php para especificar la contraseña del usuario
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: password_here
        replace: "{{ Database.Password }}"

    - name: Modificación del archivo wp-config.php para especificar el servidor de la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: localhost
        replace: "{{ Database.Host }}"

Modificaremos el archivo wp-config.php para indicar la base de datos, el usuario de la base de datos y su contraseña, además de la conexión a la base de datos, que en este caso es localhost.

    - name: Instalación del gestor de paquetes de Python3
      ansible.builtin.apt:
        name: python3-pip
        state: present

    - name: Instalación del módulo PyMySQL mediante el gestor de paquetes de Python3 para conectar conectar con el socket
      ansible.builtin.pip:
        name: pymysql
        state: present

    - name: Creación de la base de datos usando el socket de PyMySQL
      community.mysql.mysql_db:
        name: "{{ Database.Name }}"
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock

    - name: Creación del usuario con la contraseña para la base de datos
      no_log: true
      community.mysql.mysql_user:
        name: "{{ Database.User }}"
        host: '%'
        password: "{{ Database.Password }}"
        priv: "{{ Database.Name }}.*:ALL"
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock

A continuación, crearemos la base de datos con el usuario y la contraseña, para ello, necesitamos instalar en el equipo remoto el gestor de paquetes de Python3 y el módulo PyMySQL. Para la base de datos con el usuario y contraseña necesitaremos usar el socket de MySQL (mysqld.sock) que se encuentra en /run/mysqld para poder realizar las operaciones pertinentes usando el módulo PyMySQL.

    - name: Copiado del archivo index.php de html/wordpress a html
      ansible.builtin.copy:
        src: /var/www/html/wordpress/index.php
        dest: /var/www/html/index.php
        mode: 0644
        remote_src: true

    - name: Modificación del archivo index.php para la redirección a WordPress
      ansible.builtin.replace:
        path: /var/www/html/index.php
        regexp: wp-blog-header.php
        replace: wordpress/wp-blog-header.php

    - name: Modificación del archivo wp-config.php para la personalización de la URL
      ansible.builtin.blockinfile:
        path: /var/www/html/wordpress/wp-config.php
        insertafter: DB_COLLATE
        block: |
          define('WP_HOME', '{{ WordPress.Home }}');
          define('WP_SITEURL', '{{ WordPress.SiteURL }}');

    - name: Cambio de propietario y grupo para /var/www/html
      ansible.builtin.file:
        path: /var/www/html
        owner: www-data
        group: www-data
        recurse: true

      notify: Reinicio de Apache2

  handlers:
    - name: Reinicio de Apache2
      ansible.builtin.service:
        name: apache2
        state: restarted

Para finalizar con el playbook, subiremos un nivel el archivo index.php que se encuentra en /var/www/html/wordpress y lo modificaremos para indicar la ruta al archivo wp-blog-header.php que se encuentra en el directorio wordpress. También modificaremos el archivo wp-config.php para personalizar la URL de WordPress y evitar que aparezca el directorio dónde se ubica, usaremos el módulo ansible.builtin.blockinfile, indicaremos la ruta del archivo y que vamos a añadir un bloque de código después de la línea que contenga DB_COLLATE con insertafter y con block las líneas que queremos añadir, la primera para indicar el formato de la URL y la segunda la ubicación interna de WordPress.

A continuación, cambiaremos el propietario y el grupo de la ruta /var/www/html de forma recursiva y provocaremos el reinicio de Apache2 mediante notify y el handler correspondiente.

main.yml

Este archivo será el que importará los playbooks y el que ejecutemos para realizar la instalación de la pila LAMP, la configuración para HTTPS y el despliegue de WordPress. Usaremos tags para cada importación de playbook ya que si queremos evitar que un playbook o playbooks se ejecuten tenemos que hacer referencia al tag o tags que no queremos que se ejecuten, como por ejemplo el playbook https, también podemos hacer el caso contrario de ejecutar un playbook o playbooks mediante el tag o tags, los tags también nos permiten referenciar cada task o playbook para su identificación.

---

- name: Importación de playbook para instalar la pila LAMP
  ansible.builtin.import_playbook:
    playbooks/install_lamp.yml
  tags: lamp

- name: Importación de playbook para preparar HTTPS
  import_playbook:
    playbooks/https.yml
  tags: certificado

- name: Importación de playbook para el despliegue de wordpress
  ansible.builtin.import_playbook:
    playbooks/deploy_wordpress.yml
  tags: wordpress

El orden de ejecución es primero pila LAMP, después la obtención del certificado de Let's Encrypt ya que para este playbook necesitamos tener instalado Apache y por último el despliegue de WordPress.

Comprobación del despliegue de WordPress en un nivel

Como tenemos dos formas de realizar esta fase, escogeremos la que queramos, podemos hacerlo mediante scripting que deberemos clonar el repositorio en el que hemos realizado los scripts al equipo en el que instalaremos WordPress o con ansible desde nuestro equipo local lanzando el archivo main.yml.

Debemos tener en cuenta el orden de ejecución de los scripts y de los playbooks, por ejemplo, para obtener el certificado de Let's Encrypt, necesitamos que la máquina tenga instalado el servidor Apache.

Mediante scripting tenemos que ejecutar los scripts en el siguiente orden y en la ruta dónde se encuentran:

sudo ./install_lamp.sh

sudo ./config-https.sh

sudo ./deploy_wordpress.sh

Mediante ansible en la ruta dónde se encuentra el archivo inventario y main.yml:

ansible-playbook -i inventario main.yml

De la forma anterior con Ansible ejecutamos todos los playbooks y en el caso de que queramos saltar un playbook, como por ejemplo la instalación de Certbot mediante Snap y la descarga del certificado de Let's Encrypt, usaremos:

ansible-playbook -i inventario main.yml --skip-tags certificado

Para el caso contrario, sólo tenemos que ejecutar:

ansible-playbook -i inventario main.yml --tags [lamp, wordpress]

Una vez lancemos la instalación de una forma u otra, cuando termine la ejecución, accederemos a través de un navegador web a la dirección IP de la instancia o mediante el dominio que hemos asignado.

Idioma de WordPress

Nos saldrá el idioma que queremos para nuestro WordPress, lo escogemos y pasamos al siguiente paso.

Configuración del sitio y datos del backoffice

Cuando terminemos de poner los datos que nos piden, pulsaremos en el botón Instalar WordPress.

Dominio para WordPress

Cuando hayamos accedido al backoffice, usaremos el dominio en una pestaña nueva para comprobar que funciona correctamente.

fase-1

Para esta fase necesitaremos dos equipos, un frontend y un backend, en este caso como no necesitamos balanceador de carga, por lo que tendremos que abrir los puertos de HTTPS, HTTP y SSH en la máquina frontend.

Crearemos un nuevo dominio y asignaremos la dirección IP pública de la máquina frontend o asignaremos una dirección IP elástica a la máquina y asignaremos la IP al dominio en No-IP.

No-IP Nuevo dominio

Parte de los archivos que hemos usado en la anterior fase los reutilizaremos y el resto los modificaremos y partiremos el contenido para adecuarlo a los dos niveles de esta parte.

scripting

Los archivos variables.sh, config-https.sh, 000-default.conf y dir.conf los reutilizaremos y en el caso de config-https.sh lo renombraremos a https_frontend.sh ya que tenemos que obtener el certificado de Let's Encrypt en la máquina frontend. Modificaremos el contenido de ambos scripts para que se adecúen a las dos nuevas máquinas que tenemos que crear. Los demás scripts los partiremos para que cada máquina realice su función.

En el archivo variables.sh hay una línea que tenemos que modificar.

DB_Host=172.31.66.200

Certbot_Domain=practica09iawjrrl.ddns.net
WP_Home=https://practica09iawjrrl.ddns.net
WP_SiteURL=https://practica09iawjrrl.ddns.net/wordpress

En la variable DB_Host tenemos que poner la dirección IP privada de la máquina backend ya que es la que tendrá el servidor MySQL para la base de datos con el usuario y la contraseña, también podemos modificar el dominio de las variables Certbot_Domain, WP_Home y WP_SiteURL.

install_frontend.sh

En esta máquina tenemos que actualizar los repositorios y los programas instalados, instalar el servidor web Apache y los paquetes relacionados con PHP, además de copiar las plantillas a sus respectivos directorios, habilitar el módulo rewrite y reiniciar el servidor web para aplicar los cambios. Deberá quedar de la siguiente manera:

apt-get update

apt-get upgrade -y

apt-get install apache2 -y

apt-get install php libapache2-mod-php php-mysql -y

cp ../conf/000-default.conf /etc/apache2/sites-available

cp ../conf/dir.conf /etc/apache2/mods-available

a2enmod rewrite

systemctl restart apache2

En la máquina frontend no instalaremos el servidor de bases de datos MySQL ya que esta instalación la realizaremos en la máquina backend.

install_backend.sh

En esta máquina tendremos que actualizar los repositorios y los programas con respecto a los repositorios instalados y realizar la instalación de MySQL y cambiar el Bind-Address para aceptar conexiones de otras máquinas.

apt-get update

apt-get upgrade -y

apt-get install mysql-server

sed -i 's/127.0.0.1/0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf

systemctl restart mysql

Como esta máquina será la que tenga la base de datos de WordPress, tendremos que instalar MySQL y hacer un cambio en el Bind-Address para que acepte conexiones de nuestra máquina frontend. Para finalizar, tendremos que reiniciar MySQL para que los cambios se apliquen.

deploy_wordpress.sh

Usaremos este script para descargar y desplegar WordPress en la máquina frontend, de forma que tendremos que realizar cambios en el archivo wp-config.php para especificar el nombre de la base de datos, el usuario a usar y su contraseña, también debemos especificar la máquina en la que se encuentra MySQL.

source variables.sh

wget https://wordpress.org/latest.zip -O /tmp/latest.zip

apt install unzip -y

unzip /tmp/latest.zip -d /var/www/html

cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php

sed -i "s/database_name_here/$DB_Name/" /var/www/html/wordpress/wp-config.php

sed -i "s/username_here/$DB_User/" /var/www/html/wordpress/wp-config.php

sed -i "s/password_here/$DB_Password/" /var/www/html/wordpress/wp-config.php

sed -i "s/localhost/$DB_Host/" /var/www/html/wordpress/wp-config.php

cp /var/www/html/wordpress/index.php /var/www/html

sed -i "s|wp-blog-header.php|wordpress/wp-blog-header.php|" /var/www/html/index.php

sed -i "/DB_COLLATE/a define('WP_HOME', '$WP_Home');" /var/www/html/wordpress/wp-config.php

sed -i "/WP_HOME/a define('WP_SITEURL', '$WP_SiteURL');" /var/www/html/wordpress/wp-config.php

chown www-data:www-data -R /var/www/html

En este script tenemos que importar el archivo de variables e iniciar la descarga del código fuente de WordPress, instalar Unzip y descomprimir el contenido de WordPress descargado en la máquina en el directorio /var/www/html, después cambiaremos el nombre del archivo wp-config-sample.php a wp-config.php para que coja la configuración del archivo que vamos a modificar para especificar la base de datos, el usuario, su contraseña y la ubicación de la base de datos. Después subiremos un nivel el archivo index.php para ubicarlo en /var/www/html.

Modificaremos el index.php para especificar la ubicación del archivo wp-blog-header.php que se encuentra en /var/www/html/wordpress y volveremos a modificar el archivo wp-config.php para añadir dos líneas, la primera nos permite especificar la URL que tendrá el sitio web y la segunda la ubicación interna de los archivos de WordPress. Por último, modificaremos el propietario y el grupo de los archivos y directorios que se encuentran en /var/www/html de forma recursiva a Apache.

deploy_backend.sh

Este script lo usaremos para crear la base de datos en el equipo backend.

source variables.sh

echo "DROP DATABASE IF EXISTS $DB_Name" | mysql -u root
echo "CREATE DATABASE $DB_Name CHARACTER SET utf8mb4" | mysql -u root

echo "DROP USER IF EXISTS $DB_User@'%'" | mysql -u root
echo "CREATE USER $DB_User@'%' IDENTIFIED BY '$DB_Password'" | mysql -u root
echo "GRANT ALL PRIVILEGES ON $DB_Name.* TO $DB_User@'%'" | mysql -u root

Importaremos el archivo de variables y crearemos tanto la base de datos con el usuario y la contraseña, también especificaremos los privilegios que tendrá el usuario con respecto la base de datos, en este caso tendrá todos los privilegios.

ansible

En este caso también reutilizaremos los archivos variables.yml, 000-default.conf.j2, dir.conf.j2 y https.yml, en el caso del archivo variables.yml tendremos que modificar el contenido de algunas de las variables que tenemos para adecuarlas a las máquinas y en el caso de https.yml tenemos que modificar la línea de hosts para que se ejecute en la máquina frontend.

variables.yml

Modificaremos el contenido de las siguientes variables para adecuarlo a la nueva fase, siendo opcionales tanto Domain, Home y SiteURL.

Host: 172.31.66.200

Domain: practica09iawjrrl.ddns.net
Home: https://practicasiaw09jrrl.ddns.net
SiteURL: https://practicasiaw09jrrl.ddns.net/wordpress

En la variable Host tenemos que poner la dirección IP privada de la máquina que tendrá el servidor de bases de datos.

inventario

En este archivo definiremos dos grupos, uno para la máquina frontend y otro para la máquina backend.

[frontend]
3.231.218.67

[backend]
35.168.113.213

[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=/home/rayseink/claves/vockey.pem
ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new'

Como necesitamos hacer la ejecución de cada playbook en su máquina correspondiente, tenemos que tener dos grupos en nuestro archivo de inventario y con la dirección IP pública de la máquina en su respectivo grupo. Por último, tenemos que usar all:vars para que la configuración global la coja todos los grupos de máquinas que hemos especificado.

install_frontend.yml

Al igual que hicimos con los scripts, tenemos que instalar en la máquina frontend el servidor Apache, PHP y sus respectivos módulos, copiar los templates locales a la máquina remota, habilitar el módulo rewrite para que WordPress pueda realizar cambios en el servidor web y reiniciar el servidor web.

---
- name: Instalación de Apache y PHP para el equipo frontend
  hosts: frontend
  become: true

  tasks:
    - name: Inclusión de archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Actualización de los repositorios y de los programas instalados
      ansible.builtin.apt:
        update_cache: true
        upgrade: true

    - name: Instalación de servidor web Apache
      ansible.builtin.apt:
        name: apache2
        state: present

    - name: Instalación de PHP y módulos de PHP para conectar con la base de datos y Apache
      ansible.builtin.apt:
        name: "{{ PHP_Packages }}"
        state: present

    - name: Copiado de template 000-default.conf.j2 al equipo remoto
      ansible.builtin.template:
        src: "{{ Template_000_default.Local_Source }}"
        dest: /etc/apache2/sites-available/000-default.conf
        mode: 0644

    - name: Copiado de template dir.conf.j2 al equipo remoto
      ansible.builtin.template:
        src: "{{ Template_dir.Local_Source }}"
        dest: /etc/apache2/mods-available/dir.conf
        mode: 0644

    - name: Habilitación del módulo rewrite de Apache
      community.general.apache2_module:
        name: rewrite
        state: present
      notify: Reiniciar servidor Apache

  handlers:
    - name: Reiniciar servidor Apache
      ansible.builtin.service:
        name: apache2
        state: restarted

Tenemos que especificar en hosts el grupo en el que se ejecutará este playbook y como hicimos con los scripts, realizaremos los cambios pertinentes para preparar la máquina frontend.

install_backend.yml

En este playbook tenemos que instalar MySQL y modificar el Bind-Address para que acepte conexiones de la red y reiniciar el servidor de bases de datos para que aplique el cambio realizado.

---
- name: Instalación de MySQL Server y cambio de Bind-Address
  hosts: backend
  become: true

  tasks:
    - name: Actualización de los repositorios y de los programas instalados
      ansible.builtin.apt:
        update_cache: true
        upgrade: true

    - name: Instalación de MySQL Server
      ansible.builtin.apt:
        name: mysql-server
        state: present

    - name: Cambio de Bind-Address para conectar con el equipo frontend
      ansible.builtin.replace:
        path: /etc/mysql/mysql.conf.d/mysqld.cnf
        regexp: 127.0.0.1
        replace: 0.0.0.0
      notify: Reiniciar servidor MySQL

  handlers:
    - name: Reiniciar servidor MySQL
      ansible.builtin.service:
        name: mysql
        state: restarted

Al igual que hicimos con el anterior playbook, tenemos que especificar en hosts el grupo en el que se ejecutará este playbook.

https.yml

Este archivo lo tenemos que ejecutar en la máquina frontend, de forma que modificaremos la línea de hosts para que se ejecute en el grupo frontend del archivo inventario.

---
- name: Descarga de Certbot mediante Snap y obtención de certificado de Let's Encrypt
  hosts: frontend
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Desinstalación de la instalación previa de Certbot que viene con el sistema operativo
      ansible.builtin.apt:
        name: certbot
        state: absent

    - name: Instalación de Certbot mediante Snap
      community.general.snap:
        name: certbot
        classic: true
        state: present

    - name: Descarga de certificado para TLS / SSL
      ansible.builtin.command: certbot --apache -m "{{ Certbot.Email }}" --agree-tos --no-eff-email -d "{{ Certbot.Domain }}"
      register: realizar_cambio
      changed_when: realizar_cambio.rc == 0
      when: certificado | d(False) == "descargar"

Usaremos para evitar la ejecución de la descarga del certificado de Let's Encrypt el Statement When, pondremos el When al mismo nivel y justamente después de la tarea concreta y usaremos una variable, certificado que por defecto no se ejecutará hasta que el contenido de la variable sea "descargar".

deploy_wordpress.yml

Este playbook lo ejecutaremos en la máquina frontend y nos servirá para descargar el código fuente de WordPress, descomprimirlo y conectar con la base de datos que se encuentra en el equipo backend.

---
- name: Despliegue de WordPress en el equipo frontend
  hosts: frontend
  become: true

  tasks:
    - name: Inclusión de archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Instalación de Unzip
      ansible.builtin.apt:
        name: unzip
        state: present

    - name: Descarga del código fuente de WordPress
      ansible.builtin.get_url:
        url: https://wordpress.org/latest.zip
        dest: /tmp/wordpress.zip
        mode: 0664

    - name: Descompresión de la descarga de WordPress
      ansible.builtin.unarchive:
        src: /tmp/wordpress.zip
        dest: /var/www/html
        remote_src: true

    - name: Borrado del archivo comprimido de WordPress
      ansible.builtin.file:
        path: /tmp/wordpress.zip
        state: absent

    - name: Copiado de archivo wp-config-sample.php a wp-config.php
      ansible.builtin.copy:
        src: /var/www/html/wordpress/wp-config-sample.php
        dest: /var/www/html/wordpress/wp-config.php
        mode: 0644
        remote_src: true

    - name: Modificación del archivo wp-config.php para especificar la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: database_name_here
        replace: "{{ Database.Name }}"

    - name: Modificación del archivo wp-config.php para especificar el usuario de la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: username_here
        replace: "{{ Database.User }}"

    - name: Modificación del archivo wp-config.php para especificar la contraseña del usuario
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: password_here
        replace: "{{ Database.Password }}"

    - name: Modificación del archivo wp-config.php para especificar el servidor de la base de datos
      ansible.builtin.replace:
        path: /var/www/html/wordpress/wp-config.php
        regexp: localhost
        replace: "{{ Database.Host }}"

    - name: Copiado del archivo index.php de html/wordpress a html
      ansible.builtin.copy:
        src: /var/www/html/wordpress/index.php
        dest: /var/www/html/index.php
        mode: 0644
        remote_src: true

    - name: Modificación del archivo index.php para la redirección a WordPress
      ansible.builtin.replace:
        path: /var/www/html/index.php
        regexp: wp-blog-header.php
        replace: wordpress/wp-blog-header.php

    - name: Modificación del archivo wp-config.php para la personalización de la URL
      ansible.builtin.blockinfile:
        path: /var/www/html/wordpress/wp-config.php
        insertafter: DB_COLLATE
        block: |
          define('WP_HOME', '{{ WordPress.Home }}');
          define('WP_SITEURL', '{{ WordPress.SiteURL }}');
    - name: Cambio de propietario y grupo para /var/www/html
      ansible.builtin.file:
        path: /var/www/html
        owner: www-data
        group: www-data
        recurse: true

      notify: Reinicio de Apache2

  handlers:
    - name: Reinicio de Apache2
      ansible.builtin.service:
        name: apache2
        state: restarted

deploy_backend.yml

Con este último playbook, crearemos la base de datos junto al usuario y su contraseña en la máquina backend.

---
- name: Despliegue de la base de datos para WordPress en el equipo backend
  hosts: backend
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Instalación del gestor de paquetes de Python3
      ansible.builtin.apt:
        name: python3-pip
        state: present

    - name: Instalación del módulo PyMySQL mediante el gestor de paquetes de Python3 para conectar conectar con el socket
      ansible.builtin.pip:
        name: pymysql
        state: present

    - name: Creación de la base de datos usando el socket de PyMySQL
      community.mysql.mysql_db:
        name: "{{ Database.Name }}"
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock

    - name: Creación del usuario con la contraseña para la base de datos
      no_log: true
      community.mysql.mysql_user:
        name: "{{ Database.User }}"
        host: '%'
        password: "{{ Database.Password }}"
        priv: "{{ Database.Name }}.*:ALL"
        state: present
        login_unix_socket: /run/mysqld/mysqld.sock

main.yml

En este archivo principal importaremos los playbooks para ejecutarlos.

---

- name: Importación del playbook de instalación para el equipo frontend
  ansible.builtin.import_playbook:
    playbooks/install_frontend.yml

- name: Importación del playbook de instalación para el equipo backend
  ansible.builtin.import_playbook:
    playbooks/install_backend.yml

- name: Importación del playbook de obtención del certificado de Let's Encrypt
  ansible.builtin.import_playbook:
    playbooks/https.yml

- name: Importación del playbook para el despliegue en el equipo frontend
  ansible.builtin.import_playbook:
    playbooks/deploy_wordpress.yml

- name: Importación del playbook para el despliegue en el equipo backend
  ansible.builtin.import_playbook:
    playbooks/deploy_backend.yml

Comprobación del despliegue de WordPress en dos niveles

Ejecutaremos bien los scripts concretos en los equipos clonando el repositorio en ambas máquinas o lanzaremos el archivo principal y el inventario mediante ansible para preparar e instalar WordPress en dos niveles. Lo mejor es montar la arquitectura mediante ansible.

Mediante scripts tenemos que acceder a las máquinas mediante SSH y clonar el repositorio en ambas máquinas y acceder a la fase-1 al directorio scripts.

Deberemos tener en cuenta que hay scripts o playbooks que tienen que ejecutarse unos antes que otros, de forma que seguiremos el siguiente orden establecido para que funcione correctamente, por ejemplo, para obtener el certificado de Let's Encrypt necesitamos que la máquina en la que se va a descargar tenga el servidor Apache instalado.

En la máquina frontend tenemos que ejecutar en el siguiente orden:

sudo ./install_frontend.sh

sudo ./https_frontend.sh

sudo ./deploy_wordpress.sh

En la máquina backend tenemos que ejecutar en el siguiente orden:

sudo ./install_backend.sh

sudo ./deploy_backend.sh

Mediante ansible tenemos que dirigirnos en la máquina local al directorio fase-1, dónde se encuentra tanto inventario como main.yml.

Con el siguiente comando evitamos ejecutar en el playbook https, la última tarea que consiste en la descarga del certificado de Let's Encrypt, que nos sirve para ejecuciones posteriores de los playbooks en las mismas máquina y siempre que una tenga un certificado de Let's Encrypt, ya que dejaría bloqueado el proceso de descarga del certificado al disponer la máquina de uno.

ansible-playbook -i inventario main.yml

Para nuestra primera vez con esta fase necesitamos que nuestro frontend tenga el certificado, por lo que tenemos que ejecutar:

ansible-playbook -i inventario main.yml --extra-vars "certificado=descargar"

Una vez hayamos finalizado, accederemos mediante la dirección IP pública o el nombre de dominio que hemos preparado en un navegador web.

Selección de idioma WordPress

Escogeremos el idioma que queramos y continuaremos.

WordPress Access BackOffice

Introduciremos el nombre del sitio, el usuario de acceso al BackOffice junto a su contraseña y el email y pulsaremos en el botón de Instalar WordPress.

WordPress

Una vez hayamos terminado de instalar WordPress, introduciremos el nombre de dominio y comprobaremos que funciona correctamente el TLS.

Database MySQL Backend

Si queremos comprobar que en nuestro equipo backend tenemos la base de datos, accederemos mediante SSH a la instancia y ejecutaremos el comando sudo mysql -u root, después usaremos show databases; y veremos las bases de datos que tenemos, accederemos a nuestra base de datos que hemos definido en el archivo de variables mediante ansible o scripting mediante use nombre_base_datos, siendo en mi caso use wordpress_db y usaremos show tables; para mostrar las tablas de la base de datos, como no hemos creado ninguna tabla antes de la instalación, no deberíamos tener ninguna, pero tras la instalación vemos que tenemos varias tablas creadas, por lo que la instalación de la base de datos se ha realizado correctamente en la máquina backend.

Private IP Backend

Para confirmar, usaremos el comando ip a para ver la dirección IP privada que tiene nuestra máquina backend en la interfaz eth0.

fase-2

Para esta fase, deberemos tener un balanceador de carga, dos frontend, un backend y un NFS Server. Con esta parte, tendremos un balanceador de carga que irá conmutando las peticiones que reciba a los frontend y estos a su vez se conectarán con el servidor NFS para servir las páginas que están almacenadas en el servidor NFS. Cuando tengamos listas las máquinas, en No-IP crearemos un dominio con la dirección IP de la máquina que hará de balanceador de carga.

No-IP

scripting

Comenzaremos esta práctica creando los scripts y las plantillas que necesitamos para realizar esta parte.

000-default-balancer.conf

Este archivo es para nuestro balanceador de carga para que haga el proxy inverso a las máquinas frontend, deberemos tener tantos BalancerMember como máquinas frontend tengamos.

<VirtualHost *:80>
    <Proxy balancer://cluster-frontend>
        # Frontend 1
        BalancerMember http://IP_HTTP_SERVER_1

        # Frontend 2
        BalancerMember http://IP_HTTP_SERVER_2
    </Proxy>

    ProxyPass / balancer://cluster-frontend/
</VirtualHost>

000-default-frontend.conf

Con este archivo haremos que los equipos frontend busquen en los directorios del sitio web los archivos .htaccess.

<VirtualHost *:80>
    #ServerName www.example.org
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    #LogLevel info ssl:warm

    <Directory "/var/www/html">
        AllowOverride All
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

dir.conf

Este archivo nos permite cambiar el orden de prioridades a la hora de servir el contenido de las máquinas frontend, le daremos más prioridad al archivo index.php que al archivo index.html

<IfModule mod_dir.c>
        DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>

exports

Este archivo nos permite establecer en la máquina NFS Server el directorio que vamos a compartir, a la red en la que compartiremos el directorio y las opciones para el directorio.

/var/www/html 172.31.0.0/16(rw,sync,no_root_squash,no_subtree_check)

install_nfs_server.sh

Este script nos permitirá realizar el despliegue del servidor NFS que tengamos dedicado a almacenamiento y dónde estarán las páginas web.

apt update

apt upgrade -y

apt install nfs-kernel-server -y

mkdir -p /var/www/html

chown nobody:nogroup /var/www/html

cp ../conf/exports /etc/exports

systemctl restart nfs-kernel-server

En la máquina NFS actualizaremos los repositorios y actualizaremos los programas con respecto a los repositorios descargados, después instalaremos el servidor NFS (nfs-kernel-server), cuando se realice la descarga e instalación de NFS Server, crearemos el directorio html usando mkdir y el modificador -p para crear todos los directorios si no están creados.

Al directorio creado le cambiaremos tanto el propietario como el grupo para que las máquinas puedan montar el directorio creado y acceder a los archivos y directorios que contendrán. Después, copiaremos el archivo exports, que contiene el directorio a compartir, a qué red y las opciones, a la ruta /etc, por último, tendremos que reiniciar el NFS Server.

deploy_wordpress.sh

Este script como ya lo hemos realizado en la segunda fase, fase-1, lo explicaré de forma superficial ya que no tiene cambios con respecto a la anterior fase.

source variables.sh

wget https://wordpress.org/latest.zip -O /tmp/latest.zip

apt install unzip -y

rm -rf /var/www/html/wordpress

unzip /tmp/latest.zip -d /var/www/html

cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php

sed -i "s/database_name_here/$DB_Name/" /var/www/html/wordpress/wp-config.php

sed -i "s/username_here/$DB_User/" /var/www/html/wordpress/wp-config.php

sed -i "s/password_here/$DB_Password/" /var/www/html/wordpress/wp-config.php

sed -i "s/localhost/$DB_Host/" /var/www/html/wordpress/wp-config.php

cp /var/www/html/wordpress/index.php /var/www/html

sed -i "s|wp-blog-header.php|wordpress/wp-blog-header.php|" /var/www/html/index.php

sed -i "/DB_COLLATE/a define('WP_HOME', '$WP_Home');" /var/www/html/wordpress/wp-config.php

sed -i "/WP_HOME/a define('WP_SITEURL', '$WP_SiteURL');" /var/www/html/wordpress/wp-config.php

sed -i "/WP_SITEURL/a \$_SERVER['HTTPS'] = 'on';" /var/www/html/wordpress/wp-config.php

chown www-data:www-data -R /var/www/html

Tenemos que importar el archivo de variables, descargar el código fuente de WordPress, instalar Unzip y descomprimir los archivos de WordPress en /var/www/html, después copiar el archivo wp-config-sample.php para renombrar el archivo wp-config.php y modificar su contenido, también subiremos un nivel el archivo index.php y modificaremos su contenido y por último, cambiaremos tanto el propietario como el grupo a Apache de todos los archivos que hay en /var/www/html.

sed -i "/WP_SITEURL/a \$_SERVER['HTTPS'] = 'on';" /var/www/html/wordpress/wp-config.php

Para que nuestra arquitectura funcione correctamente, tenemos que añadir a wp-config.php el código $_SERVER['HTTPS'] = 'on'; ya que como tenemos conexiones HTTP entre el balanceador de carga y los frontales, es posible que nos de problemas el hecho de que se mezclen peticiones HTTP con HTTPS, de forma que con esa línea hacemos que únicamente se realicen mediante HTTPS. Tenemos que usar el backslash o \ para hacer una secuencia de escape para el símbolo \$ ya que el comando SED cogería el símbolo y su continuación como una variable.

Este script lo ejecutaremos en la máquina que tiene el NFS Server.

deploy_balancer.sh

Necesitaremos que nuestra máquina que hace de balanceador de carga tenga un proxy inverso para que las peticiones que reciba las pase a los frontend para que atiendan las peticiones.

source variables.sh

apt update

apt upgrade -y

apt install apache2 -y

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_ajp
a2enmod rewrite
a2enmod deflate
a2enmod headers
a2enmod proxy_balancer
a2enmod proxy_connect
a2enmod proxy_html
a2enmod lbmethod_byrequests

cp ../conf/000-default-balancer.conf /etc/apache2/sites-available/000-default.conf

sed -i "s/IP_HTTP_SERVER_1/$IP_HTTP_Server_1/" /etc/apache2/sites-available/000-default.conf
sed -i "s/IP_HTTP_SERVER_2/$IP_HTTP_Server_2/" /etc/apache2/sites-available/000-default.conf

systemctl restart apache2

Tenemos que integrar las variables en el script, después, actualizar los repositorios y los programas con respecto a los repositorios, después, instalaremos el servidor Apache y habilitaremos los módulos necesarios para realizar el proxy inverso, copiaremos nuestra plantilla a sites-available de Apache, modificaremos el contenido de la plantilla para agregar las direcciones IP de los frontend y reiniciaremos el servidor Apache.

install_frontend.sh

Es igual al de la anterior fase, lo único que cambia es que tenemos una plantilla distinta para permitir el uso de los archivos .htaccess.

apt-get update

apt-get upgrade -y

apt-get install apache2 -y

apt-get install php libapache2-mod-php php-mysql -y

cp ../conf/000-default-frontend.conf /etc/apache2/sites-available

cp ../conf/dir.conf /etc/apache2/mods-available

a2enmod rewrite

systemctl restart apache2

install_nfs_client.sh

Con este script realizaremos el montaje del directorio /var/www/html de la máquina NFS Server en los dos frontend para que puedan acceder a los sitios web y agregaremos una línea en el archivo /etc/fstab para realizar el montaje del directorio de forma automática cuando alguna de las máquinas frontend se reinicie.

source variables.sh

apt install nfs-common -y

mount $Private_IP_NFS_Server:/var/www/html /var/www/html

echo "$Private_IP_NFS_Server:/var/www/html  /var/www/html   nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0" >> /etc/fstab

Realizaremos la importación del archivo de variables e instalaremos el cliente de NFS. Después, montaremos mediante el comando mount junto a la dirección IP que está en el archivo de variables y la ruta del directorio, /var/www/html, en el directorio /var/www/html de las máquinas frontend. Por último, con un echo añadiremos la dirección IP de la máquina NFS Server junto al directorio que hay que montar y la ruta dónde se montará, especificaremos que es nfs, auto para que se auto monte al iniciar la máquina frontend y varias opciones más mediante una redirección no destructiva (>>) a la ruta /etc/fstab.

install_backend.sh

Este script también lo hemos visto en la fase anterior y nos sirve para instalar el servidor de bases de datos, MySQL.

apt-get update

apt-get upgrade -y

apt-get install mysql-server -y

sed -i 's/127.0.0.1/0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf

systemctl restart mysql

deploy_backend.sh

También lo hemos visto en la anterior fase, nos sirve para crear la base de datos junto al usuario y la contraseña del usuario, además de dar privilegios al usuario sobre esa base de datos.

source variables.sh

echo "DROP DATABASE IF EXISTS $DB_Name" | mysql -u root
echo "CREATE DATABASE $DB_Name CHARACTER SET utf8mb4" | mysql -u root

echo "DROP USER IF EXISTS $DB_User@'%'" | mysql -u root
echo "CREATE USER $DB_User@'%' IDENTIFIED BY '$DB_Password'" | mysql -u root
echo "GRANT ALL PRIVILEGES ON $DB_Name.* TO $DB_User@'%'" | mysql -u root

ansible

Realizaremos la misma operación de esta fase, solo que en este caso la realizaremos mediante Ansible.

inventario

En nuestro archivo de inventario definiremos cuatro grupos, el primero para el balanceador de carga, el segundo para las máquinas frontend y que tendrán el cliente NFS, el tercer grupo para la máquina backend y el cuarto grupo para la máquina que tendrá el NFS Server.

[balancer]
3.233.217.136


[frontend_nfs_client]
18.207.158.92
18.206.16.232


[backend]
100.27.49.133


[nfs_server]
3.237.34.73


[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=/home/rayseink/claves/vockey.pem
ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new'

variables.yml

Podemos reciclar el anterior archivo de variables ya que tendremos que añadir un poco más de contenido y cambiar el contenido de algunas variables. En este archivo vamos a agrupar las variables que se ejecutan en una misma máquina.

Balancer:
  Local_Source: ../templates/000-default-balancer.conf.j2

  IP_HTTP_Server_1: 172.31.77.79
  IP_HTTP_Server_2: 172.31.78.66

Con estas tres siguientes variables establecemos la ruta local del template 000-default-balancer.conf.j2 para el balanceador de carga y las direcciones IP privadas de las máquinas frontend para el template.

Frontend:
  Local_Source_000: ../templates/000-default-frontend.conf.j2
  DocumentRoot: /var/www/html

  Local_Source_dir: ../templates/dir.conf.j2

  Directory_index: DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm

También estableceremos la ruta local del template 000-default-frontend.conf.j2 para los equipos frontend y la variable del DocumentRoot dónde se alojan los sitios web para el template.También estableceremos la ruta local del archivo dir.conf.j2 y el contenido del template para priorizar el archivo index.php sobre el index.html.

NFS_Server:
  Local_Source_exports: ../templates/exports.j2

  Shared_directory_exports: /var/www/html

  Range_AWS_Private_IP_exports: 172.31.0.0/16

  NFS_Options_exports: rw,sync,no_root_squash,no_subtree_check

  Private_IP_NFS_Server: 172.31.65.63

Las siguientes variables son la localización del template exports.j2 en el equipo local, el directorio del servidor NFS que hay que compartir, el rango de direcciones desde dónde tiene que aceptar el servidor NFS peticiones de compartición del directorio compartido, las opciones para el archivo exports y la IP privada de la máquina NFS Server.

000-default-balancer.conf.j2

Con este template estableceremos las direcciones IP de las máquinas frontend y pasaremos dicho template a la máquina que hará de balanceador de carga. Deberemos tener tantos BalancerMember como frontend tengamos.

<VirtualHost *:80>
    <Proxy balancer://cluster-frontend>
        # Frontend 1
        BalancerMember http://{{ Balancer.IP_HTTP_Server_1 }}

        # Frontend 2
        BalancerMember http://{{ Balancer.IP_HTTP_Server_2 }}
    </Proxy>

    ProxyPass / balancer://cluster-frontend/
</VirtualHost>

000-default-frontend.conf.j2

Usaremos este template para permitir el uso de archivos .htaccess en el directorio /var/www/html de las máquinas frontend y leer correctamente el contenido de los sitios web.

<VirtualHost *:80>
    #ServerName www.example.org
    ServerAdmin webmaster@localhost
    DocumentRoot {{ Frontend.DocumentRoot }}

    #LogLevel info ssl:warm

    <Directory "{{ Frontend.DocumentRoot }}">
        AllowOverride All
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

exports.j2

Este template nos permite establecer el directorio a compartir en el NFS Server, el rango de direcciones IP que admite para compartir y las opciones que tiene el directorio que vamos a compartir.

{{ NFS_Server.Shared_directory_exports }} {{ NFS_Server.Range_AWS_Private_IP_exports }}({{ NFS_Options_exports }})

install_nfs_server.yml

Este playbook nos permitirá realizar la instalación del servidor NFS en la máquina que hemos definido para este playbook en el archivo inventario y la compartición del directorio que nos interesa, /var/www/html.

---
- name: Instalación de servidor NFS y compartición de directorio
  hosts: nfs_server
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Actualización de los repositorios y de los programas
      ansible.builtin.apt:
        update_cache: true
        only_upgrade: true

    - name: Instalación del servidor NFS
      ansible.builtin.apt:
        name: nfs-kernel-server
        state: present

Incluiremos el archivo de variables en el playbook, actualizaremos los repositorios y los programas con respecto a los repositorios, después instalaremos el servidor NFS.

    - name: Creación del directorio que hay que compartir
      ansible.builtin.file:
        path: /var/www/html
        state: directory
        mode: 0755
        owner: nobody
        group: nogroup

    - name: Copiado de template exports.j2 al equipo remoto
      ansible.builtin.template:
        src: "{{ NFS_Server.Local_Source_exports }}"
        dest: /etc/exports
        mode: 0644

    - name: Reinicio del servidor NFS
      ansible.builtin.service:
        name: nfs-kernel-server
        state: restarted

Crearemos el directorio html o la ruta completa si no existe y cambiaremos el propietario y el grupo para que las máquinas frontend puedan acceder al directorio, después, pasaremos el template exports.j2 a la máquina y le cambiaremos el nombre, por último, reiniciaremos el servidor NFS para aplicar los cambios realizados.

deploy_wordpress.yml

Este playbook lo ejecutaremos en la máquina NFS Server para desplegar WordPress en nuestra arquitectura, es casi idéntico al de la fase anterior salvo por hosts.

---
- name: Despliegue de WordPress en el servidor NFS
  hosts: nfs_server
  become: true

    - name: Modificación del archivo wp-config.php para la personalización de la URL
      ansible.builtin.blockinfile:
        path: /var/www/html/wordpress/wp-config.php
        insertafter: DB_COLLATE
        block: |
          define( 'WP_HOME', '{{ WordPress.Home }}' );
          define( 'WP_SITEURL', '{{ WordPress.SiteURL }}' );
          $_SERVER['HTTPS'] = 'on';

    - name: Borrado del marcado del módulo blockinfile
      ansible.builtin.lineinfile:
        path: /var/www/html/wordpress/wp-config.php
        regexp: ANSIBLE MANAGED BLOCK
        state: absent

Puesto que tenemos que añadir tres líneas, usaremos el módulo blockinfile, es posible que con el módulo nos añada un par de líneas para indicar el inicio de la inserción de código y el final, por lo que tenemos que borrar dichas líneas para que no den problemas, para ello, usaremos el módulo lineinfile, buscaremos con toda la precisión posible las líneas para borrarlas y marcaremos su state como absent para eliminarlas.

deploy_balancer.yml

Con este playbook realizaremos el despliegue de nuestro balanceador de carga por software para que pase las peticiones HTTPS que reciba a los frontend mediante HTTP y que estas máquinas devuelvan las respuestas al balanceador de carga.

Debemos actualizar los repositorios y los programas instalados con respecto a los repositorios descargados, instalar el servidor Apache y habilitar varios módulos para realizar el proxy inverso.

    - name: Copiado de template 000-default-balancer.conf.j2 al equipo remoto
      ansible.builtin.template:
        src: "{{ Balancer.Local_Source }}"
        dest: /etc/apache2/sites-available/000-default.conf
        mode: 0644
      notify: Reinicio de servidor Apache

  handlers:
    - name: Reinicio de servidor Apache
      ansible.builtin.service:
        name: apache2
        state: restarted

Por último, pasaremos nuestro template 000-default-balancer.conf.j2 al equipo remoto y reiniciaremos el servidor Apache.

install_frontend.yml

Realizaremos la instalación de Apache, PHP y los módulos de PHP para conectar con Apache y MySQL en las máquinas frontend. También tenemos que pasar dos templates, uno para establecer el DocumentRoot a la ruta /var/www/html y el otro para establecer prioridades con respecto a los archivos index.

---
- name: Instalación de Apache y habilitación de módulo para Apache en los equipos frontend
  hosts: frontend_nfs_client
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Copiado de template 000-default-frontend.conf.j2 a los equipos remotos
      ansible.builtin.template:
        src: "{{ Frontend.Local_Source_000 }}"
        dest: /etc/apache2/sites-available/000-default.conf
        mode: 0644

    - name: Copiado de template dir.conf.j2 a los equipos remotos
      ansible.builtin.template:
        src: "{{ Frontend.Local_Source_dir }}"
        dest: /etc/apache2/mods-available/dir.conf
        mode: 0644

Esta es una parte del archivo YAML, tenemos que establecer el grupo de máquinas sobre las que ejecutar el playbook e incluir nuestro archivo de variables, con el primer template establecemos el DocumentRoot que por defecto servirán los frontend y con el segundo establecemos la prioridad del index.php sobre el index.html.

install_nfs_client.yml

Este playbook es para instalar el cliente NFS en las máquinas frontend y poder montar el directorio /var/www/html de la máquina NFS Server en el directorio local /var/www/html de las máquinas y poder servir el mismo contenido teniendo varias máquinas frontend.

---
- name: Instalación de cliente NFS para conectar con el servidor NFS
  hosts: frontend_nfs_client
  become: true

  tasks:
    - name: Inclusión del archivo de variables
      ansible.builtin.include_vars:
        ../vars/variables.yml

    - name: Instalación de NFS cliente
      ansible.builtin.apt:
        name: nfs-common
        state: present

    - name: Montado del directorio compartido del servidor NFS en los clientes
      ansible.posix.mount:
        path: /var/www/html
        src: "{{ NFS_Server.Private_IP_NFS_Server }}:/var/www/html"
        fstype: nfs
        state: mounted
        opts: auto,nofail,noatime,nolock,intr,tcp,actimeo=1800

Tenemos que establecer el grupo sobre el que ejecutar este playbook, las máquinas frontend, incluir el archivo de variables y realizar la instalación del cliente NFS, por último, con el FQCN ansible.posix.mount realizaremos el montado del directorio de la máquina NFS Server mediante su dirección IP y la ruta del directorio compartido, también estableceremos el tipo de file system (fstype), el state mount para que se monte y se configure el archivo /etc/fstab para añadir la dirección IP y la ruta junto a fstype y opts.

main.yml

Estableceremos el orden de ejecución de los playbooks en nuestro archivo principal.

---

- name: Ejecución del playbook de instalación del servidor NFS
  ansible.builtin.import_playbook:
    playbooks/install_nfs_server.yml

- name: Ejecución del playbook de despliegue de WordPress en el servidor NFS
  ansible.builtin.import_playbook:
    playbooks/deploy_wordpress.yml

- name: Ejecución del playbook de despliegue del balanceador de carga
  ansible.builtin.import_playbook:
    playbooks/deploy_balancer.yml

- name: Ejecución del playbook de obtención del certificado de Let's Encrypt
  ansible.builtin.import_playbook:
    playbooks/https.yml
  when: certificado | d(False) == "descargar"

- name: Ejecución del playbook de preparación de los equipos frontend
  ansible.builtin.import_playbook:
    playbooks/install_frontend.yml

- name: Ejecución del playbook de instalación de cliente NFS y conexión con el servidor
  ansible.builtin.import_playbook:
    playbooks/install_nfs_client.yml

- name: Ejecución del playbook de preparación del equipo backend
  ansible.builtin.import_playbook:
    playbooks/install_backend.yml

- name: Ejecución del playbook de creación de la base de datos con usuario y contraseña
  ansible.builtin.import_playbook:
    playbooks/deploy_backend.yml

Debemos tener un orden de ejecución correcto ya que de no ser así, podría no funcionar. Primero ejecutaremos la instalación del servidor NFS e inmediatamente después el despliegue de WordPress en la máquina NFS Server.

A continuación, realizaremos el despliegue del balanceador de carga y después la obtención del certificado de Let's Encrypt en el balanceador de carga.

Después, realizaremos la preparación de los equipos frontend para instalar tanto Apache como PHP y los módulos de PHP para conectar con MySQL y Apache, también realizaremos la instalación del cliente NFS en los equipos frontend y el montaje de la unidad de red del equipo NFS Server.

Por último, prepararemos el equipo backend y crearemos la base de datos.

El orden establecido en main.yml puede ser un poco aleatorio, aunque sí que es necesario que un playbook concreto se ejecute antes de otro playbook para realizar correctamente la fase, en este caso, tenemos que preparar la máquina NFS Server y compartir el directorio antes de que en los equipos frontend se instale el cliente NFS y se haga el montado del directorio, ya que de ser al contrario daría fallos. También debemos tener en cuenta que antes de descargar el certificado de Let's Encrypt en el balanceador de carga, debemos tener instalado el servidor Apache.

Comprobación del despliegue de WordPress en tres niveles

Seguiremos un orden concreto y correcto para esta práctica en cuanto a la ejecución de los scripts y el orden establecido anteriormente de ejecución de los playbooks de Ansible. Debemos tener en cuenta que si queremos ejecutar los scripts, debemos clonar el repositorio en todas las máquinas.

Mediante scripts en la máquina NFS Server debemos ejecutar el siguiente orden y en la ruta dónde se encuentran:

sudo ./install_nfs_server.sh

sudo ./deploy_wordpress.sh

Con este orden preparemos primero la máquina NFS Server para realizar la compartición del directorio /var/www/html y de los archivos de WordPress en las máquinas frontend tras realizar el despliegue de WordPress en la máquina.

Mediante scripts en la máquina balanceador de carga debemos ejecutar el siguiente orden y en la ruta dónde se encuentran:

sudo ./deploy_balancer.sh

sudo ./https_balancer.sh

Con este orden hacemos que el balanceador de carga instale Apache y realice la configuración necesaria para actuar como proxy inverso con los frontales, una vez se haga el despliegue del balanceador, se obtendrá el certificado de Let's Encrypt y dispondremos de HTTPS en las peticiones entrantes al balanceador.

Mediante scripts en las máquinas frontend debemos ejecutar el siguiente orden y en la ruta dónde se encuentran:

sudo ./install_frontend.sh

sudo ./install_nfs_client.sh

Con este orden instalamos Apache, PHP, los módulos de PHP necesarios para conectar con MySQL y Apache, también preparamos el directorio /var/www/html para conectar con la unidad de red del servidor NFS.

Mediante scripts en la máquina backend debemos ejecutar el siguiente orden y en la ruta dónde se encuentran:

sudo ./install_backend.sh

sudo ./deploy_backend.sh

Tal y como hicimos en la anterior fase, podemos saltar en este caso la ejecución completa del playbook https.yml mediante el Statement When, por lo que para nuestra primera ejecución tendremos que usar el comando:

ansible-playbook -i inventario main.yml --extra-vars "certificado=descargar"

Cuando hayamos realizado la ejecución mediante scripts o Ansible, accederemos mediante la dirección IP o el nombre de dominio que hemos puesto en No-IP.

WordPress Language

Escogeremos el idioma que queremos y continuaremos.

WordPress Configuration

Podremos los datos del sitio y pulsaremos en Instalar WordPress.

WordPress Domain

Cuando hayamos realizado la instalación de WordPress, accederemos mediante el dominio que hemos asignado para comprobar que nuestro certificado en el balanceador de carga funciona correctamente.

WordPress_BackOffice

Accederemos al BackOffice de WordPress para comprobar que funciona correctamente, en la URL tenemos que poner:

https://nombre-dominio/wp-login.php

Ó

https://nombre-dominio/wordpress/wp-login.php

De cualquiera de las formas nos sirven ya que con la primera usamos la redirección que hemos establecido en wp-config.php y con la segunda forma hacemos referencia al directorio y al archivo de acceso, ponemos los datos de acceso que hemos establecido durante la instalación en el navegador web y veremos que podemos acceder sin problemas.

fstab

Mediante SSH accederemos a una de las máquinas frontend y usaremos el comando cat /etc/fstab para comprobar que se ha modificado correctamente el archivo con la dirección IP privada del servidor NFS y el directorio compartido, el fstype y las options configuradas para los clientes.