Configurar servidor para Magento 2 e instalarlo

¡Seguimos la serie de servidores! Esta vez me voy a adentrar en algo que se me escapa un poco… no conozco muy bien ni ElasticSeach ni Redis, pero quiero tener un servidor con todo lo que Adobe (Magento) nos recomienda y requiere para que funcione:

  • Servido web Nginx/Apache: usaremos Nginx
  • PHP
  • MySQL
  • Composer
  • ElasticSearch
  • Redis (no es obligatorio pero digamos que sin Redis las caches no son lo mismo…)

NOTA tras acabar el post -> Y para no mentir, entre que voy de a ratitos, tuve que investigar algo tan sencillo como «cómo instalar una versión concreta de Redis», etc… esto me ha llevado la vida jeje pero lo he acabado con mucho gusto la verdad. He de decirlo también, me esperaba que fuera algo más sencillo… pero oye, había que hacerlo, no puedo estar trabajando con Magento y no tener ni idea de la configuración del servidor que lo sostiene no?

¿De qué punto partimos?

Tengo mi VPS de pruebas con Nginx, PHP (phpfpm) v8.1 qeu ya veremos si me toca hacer un downgrade, MySQL v8.0 que también ya veremos si me toca hacer otro downgrade.

Me falta instalar Composer, ElasticSearch y Redis… y no sé si necesitaré aprender algo básico antes de poder realizar las configuraciones pertinentes.

Vamos a confiar en la documentación de Magento para guiarnos en todo el proceso (crucemos los dedos).

Requerimientos Magento versión actual

La versión en el momento de probar y escribir esto es Magento v2.4.5. Y los requerimientos son (https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/system-requirements.html?lang=en):

  • PHP v8.1
  • Composer v2.2
  • Nginx v1.18
  • MySQL 8.0 (MariaDB 10.4)
  • ElasticSearch v7.17 (OpenSearch v 1.2)
  • Redis v6.2

PHP

Bueno… no me hace falta downgrade. La 8.1 está ok. Pero me faltan un montón de extensiones listadas en https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/php-settings.html?lang=en y seguiremos luego con el resto de pasos

Extensiones

Para comprobar las extensiones

php -m

Las extensiones se instalan con (siendo mi versión de PHP la 8.1):

apt install php8.1-[extension-name]

Así que instalo todas las que me faltan de la lista del link de antes con el comando:

apt install php8.1-bcmath php8.1-ctype php8.1-curl php8.1-dom php8.1-gd php8.1-intl php8.1-mbstring php8.1-simplexml php8.1-soap php8.1-xmlwriter php8.1-xsl php8.1-zip 

(creo que hay una forma de instalar PHP con estos módulos también, pero no me voy a meter ahora en probarlo…)

Cambios en el php.ini, que saco la ruta haciendo un phpinfo(). No hagas un php –ini | grep «Loaded Configuration File» porque te dará la versión del CLI y nosotros estamos usando phpfpm… no serán iguales y te dará una ruta para configurar php en el CLI.

vim /etc/php/8.1/fpm/php.ini

# buscamos, descomentamos y dejamos estas líneas así
date.timezone = Europe/Madrid
memory_limit = 1G 
realpath_cache_size=10M y realpath_cache_ttl=7200
opcache.save_comments=1
max_execution_time = 1800
zlib.output_compression = On

Finalmente reiniciamos Nginx para que surta todo efecto:

service nginx restart

MySQL

Tenemos este link https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/database-server/mysql.html?lang=en

Habilitar el modo STRICT_ALL_TABLES SQL y el row based replication:

mysql> SET sql_mode = 'STRICT_ALL_TABLES';
mysql> SET GLOBAL binlog_format = 'ROW';

Aumentar: max_allowed_packet, tmp_table_size, max_heap_table_size y innodb_buffer_pool_size

NOTA: la documentación no aclara a cuánto subirlo

# vim /etc/mysql/mysql.conf.d/mysql.cnf 

max_allowed_packet = 512M
tmp_table_size = 64M
max_heap_table_size = 64M
innodb_buffer_pool_size = 2147483648

Crear base de datos para magento y su usuario:

create database magento;
create user 'magento'@'localhost' IDENTIFIED BY 'magento';
GRANT ALL ON magento.* TO 'magento'@'localhost';
flush privileges;

Por tanto deberíamos ahora poder acceder a las bases de datos desde

mysql -u magento -p

Nginx

En otra entrada (ésta de aquí) analizo e intento (aclaro… intento jeje) entender desde mi escaso conocimiento de estos temas, qué hace y como se configura un Nginx correctamente para Magento 2, así que muchas cosas me remito a esa sección de esa entrada.

Para nginx tenemos esta página https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/web-server/nginx.html?lang=en.

Lo primero que nos recomiendan es seguir el fichero de configuración de ejemplo que nos trae Magento en su raíz, el nginx.conf.sample. Hay que crear un nuevo virtual host con el contenido que indican. Y ello hace:

  • utiliza un upstream para conectarse al socket de phpfpm (esto va fuera del bloque server, porque debe ir dentro del bloque http de Nginx)
  • dentro del bloque server principal, 2 cosas
    • define la variable $MAGE_ROOT a lo que sería el root de virtual host
      • como explico en el post que comento más arriba, en el include hace root $MAGE_ROOT/pub; definiendo que el document root de la aplicación sea pub
    • toda el resto de la configuración va con un include al nginx.conf.sample de la raíz de la instalación que me remito al post anterior (éste de aquí)
  • Yo ya tenía instalado con Certbot un SSL, así que esa parte no la he quitado (ni las líneas que hacen referencia a la configuración de los archivos del certificado en el servidor, ni el bloque server adicional que hace la redirección de todo el tráfico del puerto 80 al 443, así que al final los pasos fueron:
    • poner antes del bloque server principal el bloque upstream
    • borrar el contenido del bloque server principal a excepción de lo relacionado con el SSL metido por Certbot
    • poner las líneas que indica magento (server_name, set $MAGE_ROOT, el include al nginx.conf.sample)

Motor de búsquedas (ElasticSearch)

Desde Magento v2.4, se ha hecho obligatorio que instalar ElasticSearch como motor de búsquedas. Y desde la v2.4.4 han añadido soporte para OpenSearch.

En este link https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/search-engine/overview.html?lang=en#installation-location nos hablan de tener ElasticSearch en otro servidor, cosa que no voy a hacer, así que no seguiré exactamente los pasos. En la propia documentación de ElasticSearch también lo recomiendan, que se da por hecho que será lo único instalado en ese servidor que consuma muchos recursos ya que algunas características funcionan de esta manera… siendo todo de pruebas, en el mismo servidor.

Aquí https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/search-engine/configure-nginx.html?lang=en también nos dicen cómo configurar de «forma segura» Nginx… montan un password para que solo pueda usarse el motor de búsquedas desde este servidor y con ese password, montando un proxy, etc. Demasiado me parece por ahora así que no lo haré tampoco.

NOTA: el tema del riesgo en seguridad, por lo que he leído, tampoco es un riesgo si lo tenemos en el mismo servidor porque ElasticSearch escucha en 9200 del loopback (localhost)… ahora, si lo usamos en servidores diferentes, cualquiera con acceso a la API HTTP podría usarlo pero esto tiene fácil solución con un pequeño firewall que permita conexiones solo entre estos dos servidores y listo.

Instalar JDK

apt-get -y update
apt-get install -y openjdk-8-jdk

Al terminar la instalación me ha pedido reiniciar el server por una versión diferente del kernel.

Instalar ElasticSearch

Instalación

Aquí Magento nos redirige a la documentación oficial. Elijo las instrucciones para Ubuntu (Debian) https://www.elastic.co/guide/en/elasticsearch/reference/7.17/deb.html

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg

sudo apt-get install apt-transport-https

echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list

sudo apt-get update && sudo apt-get install elasticsearch

Arrancar servicios

Al terminar la instalación, recibimos unos avisos de que el serviciono se inicia automáticamente, entiendo que esto ya detecta si estamos usando un administrador de servicios u otro (systemd o sysV)

### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd
 sudo systemctl daemon-reload
 sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
 sudo systemctl start elasticsearch.service

De esta manera, arrancará el servicio automáticamente si se reinicia la máquina (con systemctl enable) y luego arrancamos el servicio manualmente por primera vez con systemctl start.

Podemos comprobar que tenemos el servicio activo con

service --status-all

Comprobaciones

¿Funciona el servicio? Desde la máquina donde se ha instalado el servicio:

curl -X GET 'http://localhost:9200'

Deberíamos obtener un json con información del servicio.

Configuraciones

Aquí explican la configuración de nginx recomendada para elasticsearch https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/search-engine/configure-nginx.html?lang=en es la forma «insegura», aunque hay otra segura no vamos a hacer porque excede lo que busco aprender ahora mismo (habla de hacer un proxy con Nginx creando un BasiAuth, etc, etc, y que sea solo este server el que pueda comunicarse con el servciio de Elastic pero vamos… ahora mismo lo veo demasiado)

NOTA: realmente no entiendo muy bien en este punto el motivo de que recomienden esto… ¿no sería más sencillo simplemente configurar el firewall para que no atienda a nada externo en el puerto 9200? He visto algunos tutoriales de Elastic que lo hacen así, pero sus motivos tendrán los de Magento

Como nociones generales de configurar ElasticSearch:

  • Fichero principal de configuración: /etc/elasticsearch/elasticsearch.yml, donde podremos cambiar:
    • definir nombre del Cluster y del Node
    • añadir atributos al Node
    • definir Paths (directorio donde se guarda la información /var/lib/elasticsearch y directorio de los logs /var/logs/elasticsearch)
    • exponer una IP concreta para usar en conexiones remoto
    • definir puerto y host

Composer

Instalación

Seguimos las instrucciones de https://getcomposer.org/download/ para instalar la versión 2.2 que es la que tenemos como requisito.

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

php composer-setup.php --2.2

php -r "unlink('composer-setup.php');"

sudo mv composer.phar /usr/local/bin/composer

Con la útlima línea hacemos que el comando composer esté disponible en nuesto PATH.

Redis

Como punto de partida tenemos este link https://experienceleague.adobe.com/docs/commerce-operations/configuration-guide/cache/redis/config-redis.html?lang=en

Instalación

Para la instalación seguiremos la documentación oficial en este link https://redis.io/docs/getting-started/installation/install-redis-on-linux/

curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list

sudo apt-get update

# comento esta línea porque me falló, explico más abajo
# sudo apt-get install redis=6:6.2.8-1rl1~jammy1

Bueno… pues no funciona. La versión la saco haciendo sudo list -a redis. Me dice que necesita la versión de redis-server que vaya con lo que quiero (¿no me resuelve automáticamente las dependencias? Raro…)

Pues al tirar un sudo apt-get install redis-server=6:6.2.8-1rl1~jammy1 me vuelve a poner lo mismo pero del paquete redis-tools.

Finalmente, la parte de instalación quedaría así, yendo manualmente con cada dependencia:

sudo apt-get install redis-tools=6:6.2.8-1rl1~jammy1

sudo apt-get install redis-server=6:6.2.8-1rl1~jammy1

sudo apt-get install redis=6:6.2.8-1rl1~jammy1

Habrá una forma más elegante SEGURO, pero oye… Hago lo que puedo, y ha funcionado que es lo importante.

Configuración

En este link que Magento nos facilita https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-22-04 destaco esto:

  • Principal archivo de configuración: /etc/redis/redis.conf
    • por defecto se conecta al host 127.0.0.1 en el puerto 6379
  • Nos dice que cambiemos la directiva supervised de no a systemd porque estamos usando ubuntu. Pero como veo que por defecto pone auto como valor, lo dejo así.

Para comprobar que funciona:

redis-cli ping

Nos recomiendan:

  • activar save para las RDB (Redis Database Backup). No estoy muy seguro de esta parte, en teoría está activado
  • activar lo siguiente:
    • lazyfree-lazy-eviction yes
    • lazyfree-lazy-expire yes
    • lazyfree-lazy-server-del yes
    • replica-lazy-flush yes
    • lazyfree-lazy-user-del yes

Magento

Composer packages

Lo vamos a instalar por Composer siguiendo este link https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/composer.html?lang=en

Nos sacamos las claves (username y password de repo.magento.com) como indican: en https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/prerequisites/authentication-keys.html?lang=en

composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.4.5

# nos pide username y password de repo.magento.com 

Permisos correctos

find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} +

find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} +

chown -R :www-data . # Ubuntu

chmod u+x bin/magento

Instalación

Finalmente usamos el comando que nos da Magento y ponemos nuestros datos

php bin/magento setup:install \
--base-url=https://midominio.com \
--db-host=localhost \
--db-name=magento \
--db-user=magento \
--db-password=magento \
--admin-firstname=admin \
--admin-lastname=admin \
--admin-email=admin@admin.com \
--admin-user=admin \
--admin-password=admin123 \
--backend-frontname="admin" \
--language=en_US \
--currency=EUR \
--timezone=Europe/Madrid \
--use-rewrites=1 \
--search-engine=elasticsearch7 \
--elasticsearch-host=localhost \
--elasticsearch-port=9200 \
--elasticsearch-index-prefix=magento2 \
--elasticsearch-timeout=15

Con lo cual debería tener mi Magento 2.4.5 instalado en https://midominio.com/admin, user: admin, password: admin123 (muy seguro todo).

Como paso final (porque lo he ejecutado con user root… muy listo yo, cosa que puede ocurrir): sudo chown -R www-data:www-data .

Y….. !!!! nunca me había producido tanto gozo ver la home de la Luma 🙂

Pero si te das cuenta, no hemos configurado Redis… Hagámoslo. Desconozco ahora mismo si con el magento setup:install y sus 300 argumentos habrá alguno que ya lo configure, así que lo hacemos a posteriori y nos quedamos tan tranquilos.

Configuración de cachés

Como nos lo explican aquí https://experienceleague.adobe.com/docs/commerce-operations/configuration-guide/cache/redis/redis-pg-cache.html y aquí https://experienceleague.adobe.com/docs/commerce-operations/configuration-guide/cache/redis/redis-session.html

Caché predeterminado en Redis

php bin/magento setup:config:set --cache-backend=redis --cache-backend-redis-server=127.0.0.1 --cache-backend-redis-db=0
  • server es localhost
  • la db usada de las 16 disponibles por defecto es la 0
  • resto de opciones por defecto

Caché de páginas en Redis

php bin/magento setup:config:set --page-cache=redis --page-cache-redis-server=127.0.0.1 --page-cache-redis-db=1
  • server es localhost
  • la db usada es la 1
  • resto de opciones por defecto

Cache de sesión en Redis

php bin/magento setup:config:set --session-save=redis --session-save-redis-host=127.0.0.1 --session-save-redis-log-level=4 --session-save-redis-db=2
  • server es localhost
  • la db usada es la 2
  • nivel de logs de redis es 4 (deja fuera los niveles notice, info y debug)
  • resto de opciones por defecto

Y el admin tambíen funciona así que me voy a dormir contento jeje