Instalar LAMP en instancia Oracle con Ubuntu 22.04

Qué es LAMP

En este artículo, aprenderemos cómo instalar la llamada pila LAMP. La pila LAMP es un conjunto de software de código abierto que se utiliza para desarrollar y ejecutar aplicaciones web dinámicas. La pila LAMP está compuesta por cuatro componentes principales que trabajan juntos para habilitar el alojamiento y la ejecución de sitios web y aplicaciones web:

  • Linux, sistema operativo del servidor que ejecuta la pila.
  • Apache, servidor web HTTP muy popular.
  • MySQL o MariaDB, gestón de bases de datos.
  • Php, lenguaje de programación del lado servidor usado para acceder a las bases de datos.
Apache HTTP Server (Apache)

El servidor web Apache, comúnmente conocido como Apache, es uno de los servidores web más populares y ampliamente utilizados en el mundo. Fue creado por la Apache Software Foundation y ha sido un pilar en el alojamiento de sitios web desde su lanzamiento en 1995. Apache es de código abierto y se ejecuta en la mayoría de los sistemas operativos, lo que lo hace versátil y adaptable.

Apache se destaca por su capacidad para manejar solicitudes HTTP y servir contenido estático y dinámico a los navegadores web. Puede ejecutar scripts y aplicaciones escritos en varios lenguajes, como PHP, Python, Perl y más. Apache también es altamente configurable y se puede adaptar para diferentes necesidades y requisitos de rendimiento.

Apache es uno de los servidores web más antiguos y populares. Su principal competidor es Nginx, conocido por su eficiencia y bajo consumo de recursos en situaciones de alto tráfico. Nginx tiene una arquitectura asíncrona y multihilo, mientras que Apache maneja solicitudes asignando cada proceso a un hilo separado.

Instalar Apache

Antes de instalar paquetes o actualizar el sistema, es necesario actualizar la lista de paquetes disponibles en los repositorios configurados en el sistema y también actualizar todos los paquetes instalados a su versión más reciente.

Una vez mas te recuerdo que para actualizar la lista de paquetes disponibles en los repositorios, ejecutamos el siguiente comando: sudo apt update y para actualizar todos los paquetes instalados a su versión más reciente, se utiliza el siguiente comando: sudo apt upgrade.

En una sola línea, se puede ejecutar de la siguiente manera:

sudo apt update && sudo apt upgrade -y

Con el sistema puesto al día, ya podemos descargar el paquete para Apache llamado apache2

sudo apt install apache2

Tras esto, ahora tenemos todos los archivos de configuración del servidor web, el servicio activo y una página web de bienvenida visible actualmente desde el localhost. Sin embargo, si el firewall no permite el tráfico en el puerto 80, no podremos acceder a la página desde el exterior.

Desde el propio servidor, con el método más simple de uso del comando curl mostrará el contenido de la web por defecto sobre la ip de loopback de nuestra instancia. (Por el momento, no ponemos la ip pública porque el firewall filtrará los datos.)

curl 127.0.0.1

Esta web predeterminada se encuentra en /var/www/html/index.html

Si no muestra nada, comprueba que el servicio apache2 está en ejecución y prueba de reiniciarlo.

Aquí tienes las sentencias comunes relacionadas con el estado del servicio:

# comprobar servicio
sudo systemctl status apache2
# reiniciar servicio (detiene y reinicia automaticamente)
sudo systemctl status apache2
# detener servicio
sudo systemctl stop apache2
# activar servicio 
sudo systemctl start apache2
Firewall para Apache

Para permitir tráfico HTTP por puerto 80 tendremos que configurar el firewall propio de la instancia y el de infraesctructura de Oracle Cloud. En esta web tienes artículos que muestran y explican con detalle como hacerlo con ufw, firewallD y iptables y ahora no entraremos en grandes detalles.

Si tienes ufw, para abrir el puerto para HTTP de manera permanente:

sudo ufw allow 80
# listar reglas, debe aparecer permitido el 80
sudo ufw status

Si usas iptables, abrir el puerto para HTTP de manera permanente es mucho mas verboso. (Es posible que tengas que cambiar a usuario root para que te permita escribir en el archivo de reglas):

# agregar regla en una posición anterior al REJECT
sudo iptables -I INPUT 1 -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# grabar reglas actuales permanente
sudo /sbin/iptables-save > /etc/iptables/rules.v4

Recuerda que explicamos en el artículo dedicado a ufw que es una interfaz y por debajo está el verdadero firewall, que es iptables. Puede confundir que tengamos reglas definidas desde iptables pero no lo estén en ufw pero igualmente son válidas.

Además, si estas usando una infraestructura compleja tipo Oracle Cloud, AWS, Azure,... deberás crear también las mismas reglas en la consola de tu infraestructura. En esta web, tienes un artículo dedicado a este tema en Oracle Cloud. Puedes agregar las reglas en Listas de seguridad o de la forma recomendada por OCI que es Grupos de Seguridad. En cualquiera de las 2 formas que elijas fija estos valores para abrir puerto HTTP:

Con todo esto, ya tendremos la página por defecto de Apache. Desde cualquier ordenador con conexión a Internet si ponemos la IP pública cargará una web que de bienvenida a Apache que muestra un pequeño resumen de las características del servidor. Conviene leerlo entero. Si tenemos contratado un dominio de internet, ya sería posible acceder a esta web creando un registro DNS de tipo "A" que apunte a la IP del servidor. En esta web tienes un artículo que explica con detalle como hacerlo.

La web por defecto se encuentra en /var/www/html. Esto es suficiente si solo queremos alojar un dominio y una web en el servidor. Es mucho más optimo, preparar el servidor para alojar varios dominios con la técnica de los Host Virtuales. De esta manera conseguerimos hospedar varias páginas web con dominios diferentes en un mismo servidor.

Directorios de configuración

En la página de bienvenida nos muestra resumido el árbol de archivos de apache:

/etc/apache2/
|-- apache2.conf
|       `--  ports.conf
|-- mods-enabled
|       |-- *.load
|       `-- *.conf
|-- conf-enabled
|       `-- *.conf
|-- sites-enabled
|       `-- *.conf
|-- sites-available
|       `-- *.conf

Con el comando tree podemos ver como queda este árbol de archivos en nuestro servidor. tree no viene instalado de manera predeterminada. Si no lo tienes te recomiendo instalarlo.

tree /etc/apache2/

Si has visto con tree el directorio apache2 te habrás dado cuenta de la gran cantidad de archivos y directorios que lo forman. Vamos a comentar los principales.

  • apache2.conf es el punto de entrada que asegura que todas las configuraciones necesarias estén presentes y se apliquen correctamente durante el arranque del servidor web. Es el archivo principal que conecta todas las piezas de configuración en conjunto.
  • ports.conf es el archivo de configuración que te permite especificar los puertos en los que el servidor Apache escuchará las conexiones entrantes, permitiéndote personalizar la configuración de puertos según tus necesidades específicas. Es importante tener en cuenta que al modificar ports.conf, también es necesario ajustar la configuración de otros archivos y servicios relacionados, como los host virtuales (VirtualHosts) o los certificados SSL, si se están utilizando.
  • directorio "mods-enabled" contiene los archivos de configuración de los módulos habilitados en Apache. Cada archivo en este directorio representa un módulo específico y su extensión puede ser ".load" o ".conf". Algunos ejemplos de módulos son: 'mod_php' para la ejecución de scripts PHP dentro de Apache, 'mod_ssl' para habilitar el soporte para conexiones seguras a través del protocolo HTTPS,...
  • directorio "conf-enabled" contiene archivos de configuración específicos que son activados para la funcionalidad global del servidor Apache. Estos archivos suelen ser fragmentos de configuración que controlan aspectos generales del servidor
    Dentro del directorio "conf-enabled", puedes encontrar archivos con extensión ".conf" que contienen configuraciones relacionadas con aspectos como la seguridad, la optimización del rendimiento, la gestión de registros y otras configuraciones globales del servidor.
    Estos archivos de configuración se activan mediante enlaces simbólicos desde el directorio "conf-available". El directorio "conf-available" contiene todos los archivos de configuración disponibles, tanto los que están habilitados como los que no lo están. Al crear un enlace simbólico desde "conf-enabled" hacia un archivo en "conf-available", se activa esa configuración específica.
  • directorio "sites-enabled"directorio "sites-enabled" contiene archivos de configuración de los sitios web activos o habilitados en el servidor Apache. Cada archivo en este directorio representa la configuración de un sitio web específico que se encuentra activo y disponible para los clientes.
    Los archivos de configuración en "sites-enabled" suelen tener una extensión ".conf" y contienen las directivas y configuraciones necesarias para definir cómo se sirve y se accede a un sitio web en particular. Estas configuraciones incluyen información como la ruta de acceso a los archivos del sitio, las opciones de indexación, las restricciones de acceso, los nombres de dominio, los alias de URL y otras configuraciones relacionadas con la funcionalidad del sitio.
    Estos archivos de configuración se habilitan mediante enlaces simbólicos desde el directorio "sites-available". El directorio "sites-available" contiene todos los archivos de configuración disponibles para los sitios web, tanto los que están habilitados como los que no lo están. Al crear un enlace simbólico desde "sites-enabled" hacia un archivo en "sites-available", se activa y habilita ese sitio web específico.
  • directorio "sites-available" contiene archivos de configuración de sitios web disponibles en el servidor Apache. Estos archivos representan configuraciones de sitios web que están disponibles para su uso, pero aún no están habilitados o activos.
    Los archivos en "sites-available" suelen tener una extensión ".conf" y contienen las directivas y configuraciones necesarias para definir la configuración de un sitio web específico. Estas configuraciones incluyen información como la ruta de acceso a los archivos del sitio, las opciones de indexación, las restricciones de acceso, los nombres de dominio, los alias de URL y otras configuraciones relacionadas con la funcionalidad del sitio.
    A diferencia del directorio "sites-enabled", los archivos en "sites-available" no están activos por defecto. Para habilitar un sitio web, se crea un enlace simbólico desde el archivo correspondiente en "sites-available" hacia el directorio "sites-enabled". Esto activa el sitio web y lo hace accesible a través del servidor Apache.
    El directorio "sites-available" permite mantener múltiples configuraciones de sitios web disponibles para su uso, sin activar todos ellos simultáneamente. Esto facilita la administración y el cambio entre diferentes configuraciones de sitios web según sea necesario.
Document Root, o directorio raíz de documentos

El Document Root, o directorio raíz de documentos, se refiere al directorio principal en el cual Apache busca los archivos de un sitio web cuando se accede a través de un navegador web. En el caso de Ubuntu, por defecto, Apache tiene restringido el acceso a través del navegador a cualquier archivo que se encuentre fuera de los directorios /var/www, public_html (cuando está habilitado) y /usr/share (para aplicaciones web). Esto se hace por razones de seguridad, ya que evita que se acceda a archivos sensibles del sistema.

<> En el momento de instalar Apache se crea un archivo index.html en /var/www/html. Lo verificamos desde la terminal:

ubuntu@ubuntusrv2:~$ ls /var/www/html -la
-rw-r--r-- 1 root root 10918 Jun 29 18:11 index.html

Por defecto, tanto el directorio /html como el archivo index.html pertenecen al usurio root y grupo root. Esto debe modificarse a otro usuario/grupo para que los desarrolladores puedan subir los archivos de la web por ftp o scp sin comprometer la seguridad.

Por el momento, dejamos /var/www/html así porque vamos a implementar Host virtuales para poder alojar varias webs con diferentes dominios en el mismo servidor. Cuando llegue el momento de crear el directorio raíz del host virtual (uno o los que sean necesarios), veremos con más detalle qué propietarios y grupos debemos aplicar.

Host Virtuales

En una pila LAMP (Linux, Apache, MySQL, PHP), puedes configurar host virtuales para alojar múltiples sitios web en un solo servidor. Cada host virtual tiene su propio dominio y directorio raíz, lo que permite que varios sitios web funcionen de manera independiente en la misma máquina. A continuación, te mostraré los pasos básicos para configurar host virtuales en una pila LAMP:

Creamos un archivo de configuración en el directorio /etc/apache2/sites-available/. Aquí ya tenemos el archivo de configuración de la página por defecto y una plantilla de ejemplo para crear una configuración para web con SSL. Inicialmente, veremos como crear un host virtual sin SSL para puerto 80 y más adelante crearemos certificados con Let's encrypt.

Sobre su propio directorio, copiamos el archivo 000-default.conf y lo renombramos a nuestro gusto para el nuevo host virtual.

# cambiar al directorio de conf
~$ cd /etc/apache2/sites-available/
# copiar y renombrar archivo .conf
sudo cp 000-default.conf 001-taller.conf

Sobre esta plantilla, personalizamos los datos propios del nuevo dominio editando con nano o tu editor favorito.

sudo nano 001-taller.conf

Dentro del archivo realizaremos varios cambios: descomentaremos las líneas ServerName y ServerAlias, ingresando el dominio y subdominios necesarios, y actualizaremos la raíz del documento del sitio web con la ruta que lo contendrá.

<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.

# NOTA: el ServerAlias normalmente es el subdominio "www". De momento, me interesa reservar www para otra web.
ServerName tallerdeapps.com
ServerAlias cloud2.tallerdeapps.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/cloud2taller
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>

Es recomendable, comprobar que no hay errores de sintaxis con:

sudo apache2ctl configtest

Deberíamos obtener Syntax OK como respuesta si todo está bien. Luego, habilitamos el host virtual ejecutando el siguiente comando:

ubuntu@ubuntusrv2:/etc/apache2/sites-available$ sudo a2ensite 001-taller.conf
Enabling site 001-taller.
To activate the new configuration, you need to run:
  systemctl reload apache2

Esto creará un enlace simbólico desde el directorio /etc/apache2/sites-enabled/ al archivo de configuración del host virtual. En otras palabras, si accedemos al directorio /sites-enabled, encontraremos un "acceso directo" al mismo archivo contenido en sites-available. Sin embargo, esta operación no crea automáticamente el directorio raíz del sitio web, el cual debemos crear manualmente. Además, debemos asegurarnos de establecer los permisos adecuados de lectura/escritura y la propiedad para un usuario y un grupo que no sean root.

Creación del directorio raiz del host virtual

Al crear o subir los archivos y directorios que forman la web, es posible que nos encontremos con el problema de que solo el usuario root o el propietario de la web tenga privilegios para modificar los archivos, dejando fuera a todos los demás usuarios. En un entorno pequeño o personal, quizás esto no sea un gran inconveniente, pero lo correcto es evitar siempre acceder al directorio raíz de la web como root por motivos obvios de seguridad.

Existen varios enfoques para resolver esta situación, dependiendo del entorno en el que nos encontremos:

1- Una forma de abordarlo es creando un usuario específico para los desarrolladores. Este usuario tendría los permisos adecuados en el directorio raíz del sitio web y sería utilizado por el equipo de desarrollo para administrar y actualizar los archivos relacionados con la web.

2- Otra solución es asignar a los desarrolladores un grupo de usuarios común con permisos lo más acotados posible para realizar sus tareas de mantenimiento en la web. Además, el directorio raíz debe ser propiedad de ese grupo y tener permisos totales de edición (rwx o 7 en notación octal).

Hay muchas soluciones, y cada una presenta sus ventajas e inconvenientes en cuanto a la gestión de permisos y seguridad en el servidor web.

En este ejemplo, vamos a desarrollar la opción 2, es decir, asignar a un grupo común los desarrolladores. Cuando se instala Apache, se crea automáticamente el usuario y grupo "www-data" con permisos para la web. Aprovecharemos este grupo especial para que el directorio raíz forme parte de él. Otro cambio necesario es asignar permisos totales para que el grupo de usuarios "www-data" pueda manipular el directorio. De esta forma, cualquier usuario que pertenezca a este grupo tomará el rol de desarrollador web.

Inicialmente, ya tenemos una web por defecto funcionando en /var/www/html, pero como la intención es demostrar host virtuales, crearemos el directorio raíz tal como está definido en el archivo de configuración. Necesitamos crear un directorio llamado "cloud2taller" para que Apache sirva esta web si la URL es "cloud2.tallerdeapps.com".

# crear directorio raiz del sitio web
sudo mkdir /var/www/cloud2taller
# cambiar la propiedad al grupo "www-data" de manera recursiva (todos sus archivos y subdirectorios)
sudo chgrp -R www-data /var/www/cloud2taller

Si ahora listamos el directorio /var/www/, vemos que se ha aplicado el cambio de grupo, pero nos interesa que los permisos sean totales, de manera que los usuarios desarrolladores puedan modificar el directorio web con todos los derechos.

ls /var/www -la
total 16
drwxr-xr-x  4 root root     4096 Jul 26 19:57 .
drwxr-xr-x 14 root root     4096 Jul 25 19:19 ..
drwxr-xr-x  2 root www-data 4096 Jul 26 19:57 cloud2taller # ATENCIÓN: el grupo no tiene permisos de escritura
drwxr-xr-x  2 root root     4096 Jul 25 19:19 html

Falta cambiar algunos permisos: el grupo debe tener permisos totales, y "todos los demás" solamente deben tener permiso de lectura. Por seguridad, les quitaremos los permisos de ejecución y escritura a cualquier grupo o usuario no relacionado con el directorio web.

Una duda que me surgió, y seguramente a quien lea esto le puede pasar lo mismo, es por qué motivo dar permisos de ejecución si con lectura y escritura debería ser suficiente. Pues no. Si damos permisos 664 de lectura y escritura, la web no se carga desde el navegador y, además, necesitamos permisos "sudo" para entrar al directorio.

# permisos totales para usuario y grupo, solo lectura para todos los demás
sudo chmod -R 774 /var/www/cloud2taller

Tras cambiar los permisos, el directorio queda asÍ:

drwxrwxr--  2 root www-data 4096 Jul 26 20:19 cloud2taller

Para poder editar, borrar y crear nuevos archivos en la web, debemos asegurarnos de que los usuarios con rol de desarrollador web pertenezcan al grupo "www-data".

 # añadir el grupo sin eliminar los actuales
sudo usermod -a -G www-data ubuntu

Por último, reiniciamos el servicio de Apache para que los cambios surtan efecto.

# reiniciar servicio de apache
sudo service apache2 restart

Ahora, desde cualquier navegador de Internet, deberíamos poder acceder al sitio web a través de cloud2.tallerdeapps.com. Es importante destacar que previamente, en mi registrador de dominios, he creado el registro DNS necesario para asociar el dominio con la dirección IP de la instancia. Si no tienes un dominio registrado, no podrás crear host virtuales, ya que la única forma de acceder a tu servidor será a través de la dirección IP directamente, y el servidor Apache no podrá redirigir a otro sitio web que no sea el predeterminado por defecto.

Para probar el sitio web, crearemos un archivo web llamado "index.html" dentro de /var/www/cloud2taller, que mostrará un saludo en forma de título como su único contenido. Por simplicidad, utilizaré el comando echo con el operador de redirección > para escribir en un archivo. Si lo prefieres, puedes usar nano o subir un archivo por FTP o SSH.

echo "<h1>Hola desde http://cloud2.tallerdeapps.com</h1>" > /var/www/cloud2taller/index.html

Ahora ya tenemos un host virtual habilitado. Como prueba de ello, escribimos la URL en cualquier navegador desde internet y mostrará la página creada.

Este servidor, a su vez, mostrará la web contenida en /var/www/html si accedemos a través de la IP pública. ¡Hemos conseguido el objetivo de hospedar varias páginas web en un mismo servidor!

Recuerda que con esta configuración, solo los archivos que pertenecen al grupo "www-data" o aquellos que son del grupo "sudo" podrán crear y editar archivos de la web. Sin embargo, puede haber una pequeña incomodidad debido a que al crear o subir un archivo, este no tomará automáticamente el grupo "www-data", y solo el usuario que ha subido ese archivo podrá modificarlo. Para solucionarlo, podemos cambiar el atributo de grupo de todo el directorio raíz de manera recursiva.

sudo chgrp -R www-data /var/www/cloud2taller/

Si, por alguna razón, los permisos de escritura y lectura también están incorrectos, podemos corregirlos de manera recursiva con el mismo comando que ya utilizamos al crear el directorio, aunque en aquel momento, salvo que el directorio ya existiera o tuviera contenido, no tenía importancia.

sudo chmod -R 774 /var/www/cloud2taller/
HTTPS con Let's Encrypt

El uso de HTTPS es esencial para garantizar la seguridad y privacidad de los usuarios en Internet, y cada vez más se ha vuelto una práctica estándar para todos los sitios web y aplicaciones en línea.

Con HTTPS, obtenemos grandes mejoras en el servidor web. Por un lado, la información transmitida entre el navegador web del usuario y el servidor va cifrada, protegiendo datos sensibles como contraseñas o números de tarjeta de crédito. Además, si activamos HTTPS con una entidad de certificación, permite la autenticación del servidor web, garantizando que el sitio web al que el usuario se está conectando es legítimo y no un sitio falso o malicioso que intenta suplantar la identidad de otro.

En este tutorial, vamos a utilizar Let's Encrypt como entidad de certificación, lo cual nos permite obtener certificados TLS/SSL de manera gratuita y darle una capa de protección adicional a nuestra web.

Los requisitos previos los hemos trabajado en el transcurso del tutorial. Previamente hemos registrado al menos un registro tipo A en un registrador de dominios y en Apache hemos configurado un host virtual con su correspondiente archivo de configuración en /etc/apache2/sites-available/.

No hay que olvidar el firewall, el puerto 443 debe estar abierto en la instancia y en el panel de la infraestructura (si la hubiera. Aquí seguimos con Oracle Cloud)

2- Instalar cerbot

Para obtener un certificado SSL con Let’s Encrypt, primero, debemos instalar el software Certbot. Consta de 2 paquetes integrados con Apache para automatizar la obtención de certificados y configurar HTTPS dentro del servidor con un solo comando.

$ sudo apt update && sudo apt upgrade -y
$ sudo apt install certbot python3-certbot-apache
2- Verficar el host virtual de Apache

Para la creación del host virtual, previamente, creamos las directivas ServerName y ServerAlias en el archivo de configuración. En el caso de este ejemplo, en el archivo /etc/apache2/sites-available/001-taller.conf ya las hemos anotado:

...
ServerName tallerdeapps.com
ServerAlias cloud2.tallerdeapps.com
...
3- Crear certificado

La creación del certificado y la modificación de los archivos de configuración está totalmente automatizada y resulta muy sencilla ejecutando el instalador.

$ sudo certbot --apache

El programa solicitará responder una serie de preguntas. Comienza por un email válido usado para la renovación del certificado y avisos de seguridad:

sudo certbot --apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): pedro@tallerdeapps.com

Le sigue una confirmación de las condiciones de uso del servicio de Let's Encrypt.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

Nos solicitan conformidad para compartir el correo electrónico con Electronic Frontier Foundation para recibir noticias y otra información.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

En el siguiente paso, se solicitará sobre los dominios a los cuales queremos activar HTTPS. Certbot obtiene una lista numera del archivo de configuración que nos muestra numerados. Seleccionamos los que nos interesen poniendo el número separado por comas o espacios.

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: tallerdeapps.com
2: cloud2.tallerdeapps.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 2

Ahora, de manera automatizada certbot crea los certificados y habilita los módulos necesarios.

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for cloud2.tallerdeapps.com
Enabled Apache rewrite module
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/001-taller-le-ssl.conf
Enabled Apache socache_shmcb module
Enabled Apache ssl module
Deploying Certificate to VirtualHost /etc/apache2/sites-available/001-taller-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/001-taller-le-ssl.conf

Otro proceso automatizado es la posibilidad de redirigir el tráfico entrante de HTTP a HTTPS. En la práctica esto significa que si alguien accede a la web por http://midominio.com se le redirija a https://midominio.com automaticamente.

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Enabled Apache rewrite module
Redirecting vhost in /etc/apache2/sites-enabled/001-taller.conf to ssl vhost in 
/etc/apache2/sites-available/001-taller-le-ssl.conf

Si todo ha ido bien, obtendremos un mensaje satisfactorio.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://cloud2.tallerdeapps.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=cloud2.tallerdeapps.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

El instalador ha realizado para nosotros un largo trabajo. Por un lado, la creación del archivo de configuración para SSL con sus respectivas rutas a la clave SSL y certificado, y por otro lado, la modificación del archivo de configuración existente para el puerto 80, creando una regla para redirigir el tráfico del puerto 80 al puerto 443.

Esta regla de redirección, la encontraremos en /etc/apache2/sites-available/001-taller.conf, en el final del archivo, redirigiendo cualquier solicitud que llegue a "tallerdeapps.com" o "cloud2.tallerdeapps.com" a la misma URL pero utilizando el protocolo HTTPS, asegurándose así de que todas las solicitudes se realicen de manera segura y utilizando el certificado SSL/TLS configurado en el sitio virtual.

RewriteEngine on
RewriteCond %{SERVER_NAME} =tallerdeapps.com [OR]
RewriteCond %{SERVER_NAME} =cloud2.tallerdeapps.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

La configuración del Host Virtual para el puerto SSL (puerto 443) se ha autocompletado con el script. El archivo /etc/apache2/sites-available/001-taller-le-ssl.conf, con una estructura similar a la del puerto 80, indica las rutas hacia las claves del certificado Let's Encrypt.

$ sudo cat /etc/apache2/sites-available/001-taller-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        # NOTA: el ServerAlias normalmente es el subdominio "www". De momento, me interesa reservar www para otra web.
        ServerName tallerdeapps.com
        ServerAlias cloud2.tallerdeapps.com
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/cloud2taller
        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

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

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf

SSLCertificateFile /etc/letsencrypt/live/cloud2.tallerdeapps.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/cloud2.tallerdeapps.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Gracias al instalador, ahora contamos de manera muy cómoda con el candado activo en el navegador, lo cual siempre añade un valor adicional al generar confianza y seguridad en el sitio web.

MySQL o MariaDB

Continuando con la siguiente letra de la pila LAMP, turno ahora para la 'M', inicial de los motores de bases de datos MySQL y MariaDB.

En la actualidad, MySQL se distribuye con una licencia dual que incluye algunas características de pago, mientras que MariaDB es un software totalmente gratuito y sin limitaciones de código abierto.

Cuando MySQL dejó de ser completamente de código abierto tras ser adquirida por la empresa Oracle, uno de sus principales creadores, por temor a que desapareciera, creó un fork de MySQL garantizando la compatibilidad con las nuevas versiones de MySQL y continuando la filosofía del software libre. Como curiosidad, MariaDB lleva el nombre de su hija.

La elección entre las dos bases de datos dependerá de las necesidades técnicas del proyecto y de nuestras preferencias personales. Sin embargo, las últimas versiones de MariaDB han tenido mejor rendimiento y algunas características que no están presentes en MySQL.

En este artículo veremos cómo instalar MariaDB. Ambas bases de datos utilizan el mismo "Lenguaje de Consulta Estructurado", SQL (del inglés Structured Query Language), por lo que, salvo la línea de instalación del paquete, el resto de comandos y explicaciones son comunes a MySQL.

Instalar MariaDB

Tras actualizar el sistema, podemos instalar la base de datos con el comando:

sudo apt install mariadb-server

Tras la instalación, MariaDB está en ejecución, como comprobamos viendo el estado del servicio.

~$ sudo systemctl status mariadb
● mariadb.service - MariaDB 10.11.4 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/mariadb.service.d
             └─migrated-from-my.cnf-settings.conf
     Active: active (running) since Tue 2023-08-01 17:55:41 UTC; 1h 38min ago
       Docs: man:mariadbd(8)
             https://mariadb.com/kb/en/library/systemd/
   Main PID: 72490 (mariadbd)
     Status: "Taking your SQL requests now..."
      Tasks: 9 (limit: 14238)
     Memory: 90.1M
     CGroup: /system.slice/mariadb.service
             └─72490 /usr/sbin/mariadbd
Mejorando la seguridad de MariaDB/MySQL

Es recomendable ejecutar un script de seguridad para realizar una serie de configuraciones básicas que mejorarán la seguridad de la base de datos. Este script es una herramienta útil para asegurar que el servidor de bases de datos tenga una configuración inicial segura. Se recomienda ejecutarlo después de instalar MySQL o MariaDB.

sudo mysql_secure_installation

Nos hará una serie de preguntas. La primera es sobre la contraseña del usuario root. Si está recién instalado, todavía no tiene contraseña, por lo que simplemente pulsaremos 'INTRO'.

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

La siguiente pregunta la responderemos con 'NO' para evitar posibles incompatibilidades. En Ubuntu, la cuenta root para MariaDB está estrechamente vinculada al mantenimiento automático del sistema, por lo que no haremos cambios en los métodos de autenticación configurados para esa cuenta.

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n
 ... skipping.

A la siguiente pregunta de cambiar la contraseña de 'root', responderemos que 'NO'. Nos dice que la cuenta ya está protegida, pero en realidad no hemos configurado ninguna contraseña. Posteriormente, al terminar de responder todas las cuestiones del script, pondremos una sentencia para establecer una contraseña.

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n]

Ahora nos solicita borrar todos los usuarios anónimos. Evidentemente, responderemos que 'SI'.


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
 ... Success!

Por seguridad, también limitaremos los accesos del usuario root para que solo se acepten desde dentro del propio servidor.

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y
 ... Success!

La base de datos de test puede representar una vulnerabilidad y es conveniente eliminarla.

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Para que finalmente todos los cambios surtan efecto, forzamos una recarga de la base de datos:

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
Firewall para MySQL/MariaDB

El puerto que utiliza MariaDB es el 3306. Me ahorro la explicación de como abrir el puerto desde la insfraestructura de OCI. Es exactamente igual a como acabamos de ver para abrir el 80 en Apache. En la instancia si tienes ufw:

sudo ufw allow 3306/tcp

En iptables, como siempre, mucho más verboso y además con parámetros. En un firewall que te exige consultar el manual cada vez.

# agregar regla en una posición anterior al REJECT
sudo iptables -I INPUT 1 -p tcp --dport 3306 -j ACCEPT
# grabar reglas actuales permanente
sudo /sbin/iptables-save > /etc/iptables/rules.v4
Primera toma de contacto con MariaDB

Para abrir la terminal de MariaDB:

~$ sudo mariadb
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 37
Server version: 10.11.4-MariaDB-1:10.11.4+maria~ubu2004 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

Como primera de toma de contacto, vamos a probar algunos comandos básicos. Por ejemplo, por defecto se crean unas bases de datos. Podemos listarlas con el comando show databases;

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.000 sec)

Con el comando help obtenemos una ayuda básica de los comandos. Investiga por tu cuenta, los comandos principales y como usarlos. Hay muchísima documentación en internet sobre el lenguaje MySQL.

Para salir de la terminal de la base de datos, utilizamos el comando exit y se cerrará la sesión en la base de datos, regresando al prompt del sistema.

Usuarios y contraseñas

En MariaDB el uso de usuarios es muy importante. Tras la instalación tenemos varios usuarios iniciales y podemos crear nuevos con los privilegios necesarios para que gestionen solo lo necesario. Para ver los usuarios existentes al instalar MySQL/MariaDB, ejecutamos esta sentencia:

MariaDB [(none)]> SELECT user,authentication_string,plugin,host FROM mysql.user;
+-------------+-----------------------+-----------------------+-----------+
| User        | authentication_string | plugin                | Host      |
+-------------+-----------------------+-----------------------+-----------+
| mariadb.sys |                       | mysql_native_password | localhost |
| root        | invalid               | mysql_native_password | localhost |
| mysql       | invalid               | mysql_native_password | localhost |
+-------------+-----------------------+-----------------------+-----------+

mariadb.sys: es un usuario interno utilizado por el motor de la base de datos MariaDB para facilitar su funcionamiento. No debe utilizarse ni modificar nada relacionado, a menos que se tenga un conocimiento muy profundo de sus implicaciones.

root: es el superusuario por defecto en MySQL. Este usuario tiene todos los privilegios y acceso completo a la base de datos, lo que significa que puede realizar cualquier operación y modificación en todas las bases de datos y tablas del sistema. Es extremadamente poderoso y, por lo tanto, debe usarse con precaución para evitar cambios accidentales o maliciosos.

mysql: es un usuario interno utilizado por el sistema de gestión de bases de datos para el funcionamiento interno de MySQL. No es necesario asignarle una contraseña ya que este usuario generalmente tiene privilegios limitados y solo se utiliza internamente por el servidor de bases de datos.

En la columna "authentication_string" el valor "invalid" indica que no se ha establecido todavía contraseña o simplemente se debe pulsar INTRO. Es urgente corregir este fallo de seguridad y asignar una contraseña al usuario "root".

CREAR CONTRASEÑA PARA ROOT

En MySQL/MariaDB, los usuarios juegan un papel fundamental en la gestión de la seguridad y el acceso a la base de datos. Es altamente recomendable que el usuario "root" tenga una contraseña segura y que solo se utilice cuando sea absolutamente necesario realizar tareas administrativas que requieran permisos elevados.

Para configurar la contraseña por primera vez o cambiarla (siempre que tengamos los permisos adecuados):

MariaDB [(none)]> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('mi_contraseña');

Y seguidamente para que los cambios surtan efecto:

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.001 sec)

Podemos verificar si el usuario "root" ya tiene una contraseña revisando la misma tabla mencionada anteriormente o afinando la búsqueda para mostrar solo al usuario "root".

MariaDB [(none)]> SELECT user,authentication_string,plugin,host FROM mysql.user WHERE User = 'root';
+------+-------------------------------------------+-----------------------+-----------+
| User | authentication_string                     | plugin                | Host      |
+------+-------------------------------------------+-----------------------+-----------+
| root | *F21CE79C75C0D9399C8B472C6716E1C4AF191540 | mysql_native_password | localhost |
+------+-------------------------------------------+-----------------------+-----------+
1 row in set (0.001 sec)

Ahora, en la columna "authentication_string", el usuario "root" tiene una contraseña almacenada en forma de hash encriptado en la base de datos. Por seguridad, ningún usuario puede ver su propia contraseña, ni mucho menos la de otros usuarios.

A partir de este momento, si iniciamos sesión en "mysql/mariadb", se solicitará una contraseña, salvo en la excepción de que estemos utilizando el usuario "root" del sistema o al anteponer el comando "sudo" si el usuario tiene los privilegios necesarios.

Para iniciar sesión los 3 escenarios posibles son:

  • Si ejecutamos mysql sin usar sudo y sin ser el usuario "root" del sistema, nos dará un error por falta de permisos.
  • ubuntu@ubuntusrv2:~$ mysql
    ERROR 1698 (28000): Access denied for user 'ubuntu'@'localhost'
  • Si abrimos sesión con el usuario "root" de la base de datos (no confundir con el usuario "root" del sistema), se nos pedirá la contraseña y, si es correcta, entraremos. Usaremos el comando con el parámetro -u root para indicar el usuario y -p para que nos pregunte el password.
  • ubuntu@ubuntusrv2:~$ mysql -u root -p
    Enter password:
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
  • Si abrimos sesión con sudo o somos el usuario "root" del sistema, entraremos como el usuario "root" de la base de datos, ya que el usuario "root" del sistema tiene privilegios superiores al usuario "root" de la base de datos.
  • ubuntu@ubuntusrv2:~$ sudo mysql
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
CREAR USUARIO

Para crear un usuario usamos la sentencia:

MariaDB [(none)]> CREATE USER 'usuariodb'@'localhost' IDENTIFIED BY 'contraseña';
Query OK, 0 rows affected (0.002 sec)

La sentencia es bastante clara, como casi siempre en SQL; el lenguaje es muy humano.

Una vez creado el usuario, es necesario asignarle los permisos que tendrá y a qué bases de datos y tablas pertenece. Vamos a crear un usuario que tenga permisos CRUD (Crear, Leer, Actualizar y Eliminar) para una tabla llamada "Deportes" contenida en una base de datos llamada "Tutorial".

Este tutorial no puede abarcar en detalle MySQL; recuerda que la estructura habitual en bases de datos es que las tablas están contenidas en archivos "bases de datos" y que estos pueden contener múltiples tablas.

NUEVA TABLA Y AÑADIR REGISTROS

Con este mínimo conocimiento, ya sabemos que debemos crear la tabla dentro de una base de datos, y por "higiene", será una base de datos nueva, ya que su contenido no guarda relación con las bases de datos que se crean al instalar MySQL.

Como todavía no existe la base de datos ni la tabla, comenzamos creando la base de datos con una sentencia muy sencilla:

MariaDB [(none)]> CREATE DATABASE Tutorial;
Query OK, 1 row affected (0.000 sec)

Seguidamente creamos la tabla. Una tabla tiene una serie de columnas o campos de un tipo de datos acorde a la información que almacenarán.

Como ejemplo, crearemos una tabla llamada "Deportes" con 3 columnas:

CREATE TABLE Tutorial.Deportes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(25),
    numjugadores TINYINT UNSIGNED
);

id es el índice. Este dato se rellena automaticamente cada vez que se crea un nuevo registro. Es autoincremental y único, es decir, no hay 2 registros con el mismo índice.

nombre guarda el nombre del deporte. Es de tipo caracter con una longitud máxima de 25 caracteres.

numjugadores almacena el número de jugadores. Es un tipo de entero pequeño sin signo con valores entre 0 y 255 (un byte de tamaño)

Ahora podemos crear un usuario con los permisos necesarios para administrar esta tabla:

GRANT SELECT, INSERT, UPDATE, DELETE ON Tutorial.Deportes TO 'usuariodb'@'localhost';

Para probar este nuevo usuario, vamos a cerrar sesión de MySQL con exit y abrimos sesión con el nuevo creado "usuariodb":

mysql -u usuariodb -p

Una vez logados con este usuario, con la siguiente sentencia creamos 3 nuevos registros de deportes por equipos y el número de jugadores. Fíjate que no es necesario incluir el valor "id":

INSERT INTO Tutorial.Deportes (nombre, numjugadores) VALUES 
('Futbol', 11),
('Baloncesto', 5),
('Balónmano', 7);

MariaDB [(none)]> SELECT * FROM Tutorial.Deportes;
+----+------------+--------------+
| id | nombre     | numjugadores |
+----+------------+--------------+
|  1 | Futbol     |           11 |
|  2 | Baloncesto |            5 |
|  3 | Balónmano  |            7 |
+----+------------+--------------+
3 rows in set (0.000 sec)
IMPORTAR/EXPORTAR BASES DE DATOS

En Ubuntu y en la mayoría de sistemas Linux, las bases de datos de MySQL y MariaDB se encuentran en el directorio /var/lib/mysql.

En un entorno de producción, se darían los permisos necesarios a un usuario específico, y si fuera necesario, se crearía un usuario dedicado. Para este tutorial, para simplificar, usaremos el usuario "root".

Para importar una base de datos de otro servidor, seguiremos este procedimiento:

1. Importar el archivo .sql a un directorio accesible desde mi usuario. Puedo usar algún cliente FTP, SCP o similar. En mi ejemplo, tengo un archivo llamado "ordenadores_retro.sql" que he subido a "/home/ubuntu".

2. Si queremos que la tabla a importar vaya a una nueva base de datos, desde la shell de MySQL/MariaDB creamos una:

CREATE DATABASE nueva_base_de_datos;

Con el comando USE, seleccionamos la base de datos. A partir de este momento, los comandos se referirán a la nueva base de datos. Fíjate en el detalle de que el prompt de MySQL incluye el nombre de la base de datos.

MariaDB [(none)]> USE nueva_base_de_datos;
Database changed
MariaDB [nueva_base_de_datos]>

Ya tenemos todo preparado para importar los datos. Usaremos esta sentencia que apunta a la ruta donde se encuentra el archivo .sql. Para este tutorial, utilizo una tabla pequeña de 4 registros con un pequeño listado de ordenadores personales clásicos.

MariaDB [nueva_base_de_datos]> SOURCE /home/ubuntu/ordenadores_retro.sql;

Comprobamos la importación de la tabla con la sentencia vista anteriormente:

MariaDB [nueva_base_de_datos]> SHOW TABLES;
+-------------------------------+
| Tables_in_nueva_base_de_datos |
+-------------------------------+
| ordenadores_retro             |
+-------------------------------+

Para finalizar la demostración, listamos las filas de las columnas (ATENCIÓN: el nombre de la tabla no incluye la extensión .sql):

MariaDB [nueva_base_de_datos]> SELECT * FROM ordenadores_retro;
+----+-------------------+-------------+
| ID | MARCA             | MODELO      |
+----+-------------------+-------------+
|  1 | Commodore         | Amiga 500   |
|  2 | Sinclair Research | ZX Spectrum |
|  3 | Atari             | 520 ST      |
|  4 | Amstrad           | CPC 464     |
+----+-------------------+-------------+

La exportación de bases de datos se realiza desde fuera de la propia shell de MySQL/MariaDB. Para copiar una base de datos desde la terminal, utilizaremos el comando mysqldump con un usuario que tenga los permisos necesarios en la base de datos que deseamos exportar. Al ejecutar el comando de exportación, se nos solicitará la contraseña del usuario. La sintaxis es la siguiente:

mysqldump -u usuario -p nombre_de_la_base_de_datos > /ruta/del/archivo.sql

Una aclaración importante sobre esta sentencia que puede ser confusa es que debemos proporcionar únicamente el nombre de la base de datos como parámetro, sin incluir su ubicación, a diferencia de lo que hacemos con el directorio de destino (a menos que deseemos exportar al directorio actual).

También es posible realizar la exportación con un usuario que tenga permisos de superusuario "sudo". En mi ejemplo particular, usaríamos la siguiente sentencia:

sudo mysqldump nombre_de_la_base_de_datos > /home/ubuntu/copia.sql

Con estos comandos, obtendremos la base de datos en formato .sql, lista para ser movida a la ubicación que nos interese.

Con esto, doy por finalizada esta breve introducción a MySQL. Encontrarás muchísima documentación para aprender cómo realizar las tareas habituales, como modificar, consultar, crear y eliminar registros, con sentencias muy sencillas de entender.

En el siguiente apartado, instalaremos PHP y aprenderemos a consultar una base de datos desde la web.

Lenguaje PHP

PHP, que significa "PHP: Hypertext Preprocessor", es un lenguaje de programación ampliamente usado en desarrollo web. Funciona en el servidor y permite crear sitios dinámicos y aplicaciones interactivas. Su principal ventaja es generar contenido en tiempo real a partir de bases de datos y formularios. Es popular para sistemas de gestión de contenido como WordPress y es conocido por su sintaxis sencilla y su adaptabilidad a diversas tareas en línea.

Instalar PHP

La instalación de PHP suele incluir además del paquete base de PHP, algunos módulos dependiendo del uso que le vayamos a dar. De momento, pongo los totalmente necesarios para la pila LAMP:

  1. php: Este es el paquete principal de PHP, que incluye el intérprete de PHP en sí. Es el componente fundamental que permite ejecutar código PHP en el servidor.
  2. libapache2-mod-php: Este módulo permite la integración entre PHP y el servidor web Apache. Apache necesita entender y procesar los scripts PHP, y este módulo facilita esa comunicación.
  3. php-mysql: Este módulo proporciona soporte para la comunicación entre PHP y bases de datos MySQL. Gracias a este módulo, se permite la ejecución de consultas y operaciones en bases de datos desde los scripts PHP.

Para instalar PHP desde la terminal, escribimos el siguiente comando:

sudo apt install php libapache2-mod-php php-mysql

Tras esto ya tenemos PHP plenamente operativo para funcionar en una pila LAMP.

Para verificar la versión que tenemos instalada, utilizamos el comando php -v.

~$ php -v
PHP 8.2.8 (cli) (built: Jul  8 2023 07:09:59) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.8, Copyright (c), by Zend Technologies

El siguiente paso es ejecutar código PHP en una página web del servidor. Utilizaremos el archivo index.html que creamos anteriormente y que está ubicado en el directorio del Host Virtual.

La función phpinfo(); genera una página que muestra una amplia cantidad de información relacionada con la versión de PHP, módulos cargados, configuraciones del servidor, variables de entorno, extensiones instaladas, configuración de bases de datos y más. Presenta una excelente demostración de cómo la web procesa solicitudes PHP.

Recordemos que en este ejemplo, tenemos un Host Virtual en /var/www/cloud2taller donde creamos un simple archivo web que muestra un saludo. Utilizamos el editor nano para editar el archivo index.htm y agregamos al final el código PHP.

Es muy probable que Apache todavía no procese el código PHP, ya que en la configuración por defecto solo lo hace si la extensión es .php. Aunque es posible procesar PHP en archivos con extensión .htm o .html, suele ser muy común que los archivos tengan la extensión PHP para evitar cambios delicados en el archivo .htaccess.

Cambiar la extensión es fácil con el comando mv:

mv /var/www/cloud2taller/index.htm /var/www/cloud2taller/index.php

Después de hacer esto, al ingresar el dominio registrado en un navegador, veremos las tablas de configuración de PHP de nuestro servidor.

Acceder a base de datos desde PHP

La prueba definitiva de que la pila LAMP está funcionando correctamente en el servidor es establecer una conexión a la base de datos desde PHP. Utilizaremos la base de datos "Deportes" que creamos en la sección anterior sobre MariaDB/MySQL. Para lograrlo, utilizaremos un script en PHP que se conectará a la base de datos mediante la "librería" PDO (NOTA: En castellano, lo correcto es decir "biblioteca". "Library" en inglés, pero es tan común usar la palabra "librería" que me resulta difícil decir "biblioteca") y, a través de una iteración, mostraremos todos los registros en una tabla HTML.

<?php
$servername = "localhost";
$username = "usuariodb";
$password = "mi_contraseña";
$dbname = "Tutorial";

try {
    // Establecer la conexión a la base de datos
    $conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Preparar y ejecutar la consulta
    $sql = "SELECT * FROM Deportes";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    // Obtener los resultados de la consulta
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    // Manejar cualquier error que ocurra durante la conexión o la consulta
    echo "Error: " . $e->getMessage();
}
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Tabla Deportes</title>
</head>
<body>
    <h2>Tabla Deportes</h2>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>Nombre</th>
            <th>Número de Jugadores</th>
        </tr>
        <?php
        if ($result) {
            // Iterar sobre los resultados y mostrarlos en una tabla HTML
            foreach ($result as $row) {
                echo "<tr>";
                echo "<td>" . $row["id"] . "</td>";
                echo "<td>" . $row["nombre"] . "</td>";
                echo "<td>" . $row["numjugadores"] . "</td>";
                echo "</tr>";
            }
        } else {
            echo "<tr><td colspan='3'>No se encontraron registros</td></tr>";
        }
        ?>
    </table>
</body>
</html>

<?php
$conn = null; // Cerrar la conexión
?>

Puedes integrar este código en el archivo "index.php" borrando el ejemplo anterior, o también puedes crear un nuevo archivo con extensión ".php". Apache tiene una lista de nombres de archivos que funcionan como índices o páginas de inicio al acceder a un dominio o directorio dentro de ese dominio. Por defecto, la lista se encuentra en el archivo /etc/apache2/mods-available/dir.conf y contiene estos posibles nombres de inicio:

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

En este momento, como "index2.php" no está contemplado como página de inicio, si quiero abrir esta página en el navegador, debo añadir el nombre del archivo a la URL de esta manera: https://cloud2.tallerdeapps.com/index2.php

Ahora, en Internet y disponible para todo el mundo, tenemos un sitio web que demuestra cómo conectar una base de datos en PHP, alojada en un servidor Ubuntu en la nube de Oracle.

DirectoryIndex. La página de inicio

Para modificar las páginas de inicio de las páginas web, podemos hacerlo de manera global para todo el servidor modificando el archivo "dir.conf", o de manera individual para cada Host Virtual agregando la configuración "DirectoryIndex" con el nombre o nombres de página de inicio (con prioridad en orden). Esto se puede hacer en los archivos ".conf" del directorio /etc/apache2/sites-available/ o dentro de un archivo ".htaccess" que debe estar en el directorio raíz de la página web. En cualquier caso, para que los cambios surtan efecto, es necesario reiniciar el servicio "apache2".

El archivo .htaccess es un archivo de configuración que se utiliza en servidores web basados en Apache para aplicar directivas de configuración específicas a un directorio en particular, así como a sus subdirectorios. Estas directivas pueden modificar la forma en que se comporta el servidor web, controlar el acceso a determinados archivos o carpetas, redirigir URLs, entre otras cosas.

En este tutorial, modificaré el archivo /etc/apache2/sites-available/001-taller-le-ssl.conf y agregaré la línea siguiente antes de las rutas de las claves SSL:

DirectoryIndex index2.php

Luego reiniciaré el servicio "apache2" usando el siguiente comando:

sudo systemctl restart apache2

Con estos pasos, al abrir la URL https://cloud2.tallerdeapps.com/, se mostrará la página "index2.php".

Final

Con todo lo que hemos visto en el tutorial, ahora somos capaces de configurar y alojar un sitio web con una base de datos MySQL en un servidor Ubuntu 22.04. Podemos mejorar aún más el servidor instalando phpMyAdmin u otras herramientas con interfaz gráfica para administrar las bases de datos. Ese será el tema de otro artículo.