Despliegue de Aplicaciones Web
José Juan Sánchez Hernández
Curso 2023/2024
GRANT
En esta práctica deberá automatizar la instalación y configuración de una aplicación web LAMP en dos máquinas virtuales EC2 de Amazon Web Services (AWS), con la última versión de Ubuntu Server. En una de las máquinas deberá instalar Apache HTTP Server y los módulos necesarios de PHP y en la otra máquina deberá instalar MySQL Server.
Ahora vamos a tener la pila LAMP repartida en dos máquinas virtuales, una se encargará de gestionar las peticiones web y la otra de gestionar la base de datos.
Una vez que hayas comprobado que todos los servicios de la pila LAMP están funcionando correctamente en las dos máquinas, instala y configura WordPress en ellas.
Ten en cuenta que tendrás que modificar la configuración de MySQL Server para que permita conexiones remotas y también tendrás que revisar los privilegios del usuario que se conecta a la base de datos de la aplicación.
La arquitectura estará formada por:
Edita el siguiente archivo de configuración:
/etc/mysql/mysql.conf.d/mysqld.cnf
Busca la directiva de configuración bind-address
dentro
del bloque de [mysqld]
:
[mysqld]
bind-address = 127.0.0.1
En la configuración por defecto, MySQL sólo permite conexiones desde
localhost (127.0.0.1
). Habrá que modificar este valor por
la dirección IP de la máquina donde se está ejecutando el servicio de
MySQL.
[mysqld]
bind-address = IP_SERVIDOR_MYSQL
El valor de IP_SERVIDOR_MYSQL
indica desde que
interfaz de red del servidor de MySQL se van a permitir
conexiones. En nuestro caso, los valores que podemos poner aquí son:
IP pública de AWS
: Permitimos el
acceso a cualquier máquina que envíe una petición de conexión desde la
red pública de AWS.IP privada de AWS
: Sólo permitimos el
acceso desde máquinas que estén en la misma red privada de AWS.127.0.0.1
: No permitimos conexiones
remotas, sólo se permiten conexiones dentro de la misma máquina.0.0.0.0
: Indica que permitimos
conexiones desde cualquier interfaz de red que tenga la máquina.Si nuestra máquina dispone más de una interfaz de red podemos poner
la dirección IP 0.0.0.0
para permitir que se puedan
conectar a MySQL desde cualquiera de las interfaces de red
disponibles.
[mysqld]
bind-address = 0.0.0.0
Una vez hecho esto tenemos que reiniciar el servicio de MySQL:
sudo systemctl restart mysql
GRANT
Si queremos mejorar la seguridad de nuestro servidor de MySQL, podemos configurar que el usuario de MySQL sólo pueda conectarse desde una determinada dirección IP.
Paso 1. Eliminar si existe algún usuario previo con el mismo nombre
Antes de crear un usuario, debemos comprobar si existe y eliminarlo en caso de que exista. Para ello, ejecutamos la siguiente sentencia SQL:
Donde $DB_USER
es el nombre del usuario de MySQL y
$IP_MAQUINA_CLIENTE
es la dirección IP desde la que el
usuario puede conectarse al servidor de MySQL.
Paso 2. Creación de un usuario
La sintaxis para crear un usuario de MySQL es la siguiente:
Donde $DB_USER
es el nombre del usuario de MySQL,
$DB_PASS
es la contraseña y
$IP_MAQUINA_CLIENTE
es la dirección IP desde la que el
usuario podrá conectarse al servidor de MySQL.
Los valores que podemos utilizar para
$IP_MAQUINA_CLIENTE
son los siguientes:
localhost
: No permitimos conexiones
remotas, sólo se permiten conexiones dentro de la misma máquina.%
: Este comodín indica que permitimos
conexiones desde cualquier máquina.172.31.10.11
.172.31.%.
Tenga en cuenta que tendrá que reemplazar los valores de las
variables $DB_USER
, $DB_PASS
y
$IP_MAQUINA_CLIENTE
por los valores que necesite.
Paso 3. Asignación de privilegios
Una vez que hemos creado el usuario le asignamos los privilegios que
sean necesarios sobre la base de datos de la aplicación. Para asignar
privilegios utilizaremos la sentencia GRANT
de SQL. La
sintaxis es la siguiente:
Por ejemplo:
En este comando, los asteriscos indican que estamos aplicando el
permiso ALL PRIVILEGES
al usuario
nombre_usuario
para que pueda acceder a todas las tablas de
cada una de las bases de datos. En el ejemplo anterior, el usuario sólo
puede conectarse al servidor de MySQL dede localhost
.
En esta práctica tenemos que asignar todos los privilegios con
ALL PRIVILEGES
al usuario de MySQL que vamos a utilizar
para conectarnos desde la máquina donde está corriendo el servicio de
Apache HTTP.
Tenga en cuenta que tendrá que reemplazar los valores de las
variables $DB_NAME
, $DB_USER
y
$IP_MAQUINA_CLIENTE
por los valores que necesite.
Los diferentes tipos de permisos que podemos aplicar son los siguientes:
ALL PRIVILEGES
: permite a un usuario de MySQL acceder a
todas las bases de datos asignadas en el sistema.CREATE
: permite crear nuevas tablas o bases de
datos.DROP
: permite eliminar tablas o bases de datosDELETE
: permite eliminar registros de tablas.INSERT
: permite insertar registros en tablas.SELECT
: permite leer registros en las tablas.UPDATE
: permite actualizar registros seleccionados en
tablas.GRANT OPTION
: permite asignar privilegios a otros
usuarios.Paso 4. Actualizamos las tablas de privilegios
Para que los cambios que hemos realizado sobre los privilegios de los usuarios se apliquen de forma inmediata, tendremos que ejecutar el siguiente comando.
Ejemplo
En el script de bash de la práctica que va a realizar debería tener el siguiente bloque de instrucciones SQL para crear el usuario de MySQL y asignarle los privilegios necesarios sobre la base de datos de la aplicación web:
DROP USER IF EXISTS '$DB_USER'@'$IP_MAQUINA_CLIENTE';
CREATE USER '$DB_USER'@'$IP_MAQUINA_CLIENTE' IDENTIFIED BY '$DB_PASS';
GRANT ALL PRIVILEGES ON '$DB_NAME'.* TO '$DB_USER'@'$IP_MAQUINA_CLIENTE';
Las variables estarán definidas en un archivo .env
:
Los usuarios de MySQL se almacenan en la tabla
mysql.user
. La clave primaria de esta tabla está formada
por los valores user
y host
, de modo que cada
fila vendrá identificada por un nombre de usuario y el host desde el que
puede conectarse.
La siguiente consulta nos devuelve el listado de usuarios que tenemos en MySQL y desde qué host pueden conectarse:
En nuestra caso la consulta anterior devuelve el siguiente resultado:
+------------------+--------------+
| user | host |
+------------------+--------------+
| root | % |
| root | localhost |
| lamp_user | % |
| lamp_user | localhost |
| debian-sys-maint | localhost |
| phpmyadmin | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
+------------------+--------------+
El siguiente diagrama muestra un ejemplo de dos usuarios que se están
conectando a una máquina con MySQL Server. El usuario
root@localhost
es un usuario que sólo puede conectarse
desde la máquina local y el usuario root@'%'
es un usuario
que se puede conectar desde una máquina remota.
También podemos consultar qué permisos específicos tiene un
determinado usuario. La siguiente consulta nos devuelve los permisos que
tiene el usuario root
:
+------------------------------------------------+
| Grants for root@% |
+------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' |
+------------------------------------------------+
Ahora vamos a comprobar que podemos conectarnos con MySQL desde la
máquina donde está corriendo el servicio de Apache HTTP. Podemos
comprobarlo conectando con el shell de mysql
:
mysql -u USERNAME -p -h IP-SERVIDOR-MYSQL
O haciendo un telnet al puerto donde está corriendo el servicio de MySQL:
telnet IP-SERVIDOR-MYSQL 3306
Si no podemos conectarnos a MySQL revisaremos que el servicio está activo y que no tenemos ningún firewall que nos esté filtrando el puerto del servicio donde se ejecuta MySQL.
Una vez que has realizado los pasos anteriores debes instalar y configurar WordPress para que pueda conectar a MySQL.
Recuerda que tendrás que modificar el archivo de configuración de
WordPress wp-config.php
y configurar las constantes
relacionadas con la base de datos.
// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );
/** Database username */
define( 'DB_USER', 'username_here' );
/** Database password */
define( 'DB_PASSWORD', 'password_here' );
/** Database hostname */
define( 'DB_HOST', 'localhost' );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
En esta práctica la constante DB_HOST
tendrá que tener
el valor de la dirección IP privada de la máquina donde
se está ejecutando el servicio de MySQL.
A continuación se describe una secuencia de pasos que se pueden realizar para detectar posibles errores cuando desde la máquina de front-end (Apache HTTP Server) no puedo conectar con la máquina de back-end (MySQL).
Lo primero que deberíamos hacer sería comprobar que las dos instancias están en ejecución.
Una vez que hemos comprobado que las dos instancias están en
ejecución, deberíamos comprobar que están en la misma subred y que
pueden verse entre sí haciendo uso de la utilidad
ping
.
Si las máquinas están en la misma subred y pueden verse entre sí,
debemos comprobar que el puerto 3306
de la máquina donde se
ejecuta MySQL está abierto. Revisa la configuración del firewall para
verificar que el puerto 3306
está abierto.
Una vez que hemos verificado que el puerto 3306
está
abierto en el firewall, podemos comprobar si el servicio de MySQL está
en ejecución en ese puerto. Para comprobarlo podemos hacer un
telnet
al puerto 3306
desde la máquina de
front-end, donde se ejecuta Apache HTTP Server. Ejemplo:
telnet IP-SERVIDOR-MYSQL 3306
.
Si el puerto está abierto recibirás algún mensaje de respuesta al
hacer un telnet
. Si no recibes ninguna respuesta comprueba
que el parámetro bind-address
está bien configurado en el
archivo de configuración de MySQL, para que pueda aceptar conexiones
desde la subred donde está la máquina de front-end donde se
ejecuta Apache HTTP Server.
Si el puerto 3306
está abierto, podemos comprobar
que el usuario de MySQL de la aplicación web puede conectarse desde la
máquina de front-end donde se ejecuta Apache HTTP Server.
Recuerda que el usuario que se conecta desde otra máquina tiene que
crearse con el comodín %
en el valor del host. En la
máquina de Apache puedes instalar el cliente de MySQL con
apt install mysql-client
y comprobar que puedes
conectarte a MySQL con el usuario de la aplicación web. Ejemplo:
mysql -u USERNAME -p -h IP-SERVIDOR-MYSQL
.
Comprueba que has configurado correctamente el archivo de configuración de la aplicación web para que pueda conectarse a MySQL.
En esta práctica habrá que entregar un documento técnico con la descripción de los pasos que se han llevado a cabo.
El documento debe incluir como mínimo los siguientes contenidos:
URL del repositorio de GitHub donde se ha alojado el documento técnico escrito en Markdown.
Scripts de bash utilizados para realizar el aprovisionamiento de las máquinas virtuales.
Tenga en cuenta que el aprovisionamiento de las máquinas virtuales se realizará mediante un script de bash. Cada máquina usará su propio script. El contenido de cada uno de los scripts deberá ser incluido en el documento y deberá describir qué acciones se han ido realizando en cada uno de ellos.
Deberá crear un repositorio en GitHub con el nombre de la práctica y añadir al profesor como colaborador.
El repositorio debe tener el siguiente contenido:
Además del contenido anterior puede ser necesario crear otros archivos de configuración. A continuación se muestra un ejemplo de cómo puede ser la estructura del repositorio:
.
├── README.md
├── conf
│ └── 000-default.conf
└── scripts
├── .env
├── install_lamp_frontend.sh
├── install_lamp_backend.sh
├── setup_letsencrypt_https.sh
├── deploy_frontend.sh
└── deploy_backend.sh
El documento técnico README.md
tiene que estar escrito
en Markdown y debe
incluir como mínimo los siguientes contenidos:
El directorio scripts
debe incluir los siguientes
archivos:
.env
: Este archivo contiene todas las variables de
configuración que se utilizarán en los scripts de Bash.
install_lamp_frontend.sh
: Script de Bash con la
automatización del proceso de instalación de la pila LAMP en la máquina
de frontend.
install_lamp_frontend.sh
: Script de Bash con la
automatización del proceso de instalación de la pila LAMP en la máquina
de backend.
setup_letsencrypt_https.sh
: Script de Bash con la
automatización del proceso de solicitar un certificado SSL/TLS de Let’s
Encrypt y configurarlo en el servidor web Apache.
deploy_frontend.sh
: Script de Bash con la
automatización del proceso de instalación de WordPress sobre el
directorio raíz /var/www/html
en la máquina donde se
ejecuta el servidor web Apache.
deploy_backend.sh
: Script de Bash con la
automatización del proceso de creación de la base de datos y el usuario
de WordPress en la máquina donde se ejecuta MySQL Server.
Esta
página forma parte del curso
Implantación de Aplicaciones
Web de José Juan Sánchez
Hernández y su contenido se distribuye bajo una
licencia
Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0
Internacional.