Página propia en Wordpress, con Apache2, MySQL, PHP y phpMyAdmin (Stack LAMP) - perfeccion-ar/infraestructura-clasica-y-avanzada GitHub Wiki

Documento mantenido en
- https://github.com/perfeccion-ar/infraestructura-clasica-y-avanzada/wiki
- https://github.com/perfeccion-ar/infraestructura-clasica-y-avanzada/wiki/P%C3%A1gina-propia-en-Wordpress,-con-Apache2,-MySQL,-PHP-y-phpMyAdmin-(Stack-LAMP)
Relacionado:
- Configuración de VPS de Oscar
- HTTPS, Let's Encrypt y Cloudflare
- Nginx Proxy Manager GUI con servicios bajo Docker
sudo apt-get install language-pack-es language-pack-en -y
sudo locale-gen es_AR.UTF-8
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure tzdata
Estas líneas de comandos están destinadas a configurar el idioma y la zona horaria en un sistema operativo basado en Debian, como Ubuntu. Aquí está el propósito de cada línea:
sudo apt-get install language-pack-es language-pack-en -y:
Instala los paquetes de idioma para español e inglés. La opción -y automatiza la respuesta afirmativa a las preguntas que normalmente se hacen durante la instalación.
sudo locale-gen es_AR.UTF-8:
Genera la configuración regional para el idioma español en Argentina, con codificación UTF-8. sudo dpkg-reconfigure locales:
Reconfigura las configuraciones regionales del sistema. Esto permite seleccionar y activar las configuraciones regionales que se utilizarán.
sudo dpkg-reconfigure tzdata:
Reconfigura la zona horaria del sistema. Esto abre un asistente que permite seleccionar la zona horaria correcta para el sistema. Estas líneas se utilizan para asegurar que el sistema operativo esté configurado para usar el idioma y la zona horaria deseados.
Para no repetir mac, cuando se clone o se restaure, cuidar de borrar las placas de red anteriores

Ojo si había Maria (Debian y Arch por defecto)- dejarla. Sino instalar MySQL (se lleva bien con Ubuntu)
Osea, no forzar MySQL en Debian, ni MariaDB en Ubuntu. El comando mysql dice cual de las está instalada
apt install mysql-server
sudo mysql_secure_installation
Eso dispara el asistente de MySQL
Es posible que pregunte por el nivel de password:

Por ser un server de prueba, puede escoger 0 simplemente, para no complicar a phpMyAdmin u a otros clientes.
Luego, conteste Yes a todas las otras preguntas, y a partir de ahora, use contraseñas complejas, con Mayúsculas, minúsculas, números, signos, etc. Y recuerde que MySQL tiende a fallar en sus instrucciones sin explicar que la verdadera razón es que su contraseña no ha sido suficientemente fuerte. De modo que hágalo bien de entrada. Aquí usaremos dos contraseñas de ejemplo que son bastante cortas y fuertes.
Ahora define una contraseña al root de MySQL/MariaDB. Entre al motor simplemente con
El root de MySQL no es el root del equipo, ni del container. Es un root aparte.
$ sudo mysql
Anote los plugins de validación instalados para cada usuario. Puede necesitarlos mas tarde para coordinar con phpMyAdmin
mysql> select user,plugin from mysql.user;
+------------------+-----------------------+
| user | plugin |
+------------------+-----------------------+
| debian-sys-maint | caching_sha2_password |
| mysql.infoschema | caching_sha2_password |
| mysql.session | caching_sha2_password |
| mysql.sys | caching_sha2_password |
| root | mysql_native_password |
+------------------+-----------------------+
Puede también que la última línea diga
| root | auth_socket |
+------------------+-----------------------+
Esto quiere decir que el comando mysql
, ncesario para administrar el motor, puede ser llamado desde consola, sin usuario ni contraseña, solo por estar logueado en el equipo, y trabajar desde allí. Es una opción muy cómoda: tan solo escribe mysql
y empieza crear bases, administrar, etc.
Pero auth_socket no permite conexiones conexiones remotas, por ejemplo desde ayudantes como DBeaver, HeidiSQL, phpMyAdmin, mysql_workbench, etc.
Si decide cambiar ese plugin auth_socket
a mysql_native_password
, y dotar al root de MySQL de una contraseña, indique los siguientes comandos.
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Pepelepu1.';
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
Puede cambiar también a un plugin de autenticación mas exigente y robusto, de mysql_native_password
a caching_sha2_password
, manualmente
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'Pepelepu1.';
Vea que hemos indicado localhost, para permitir paso local por ejemplo a phpMyAdmin. Pero si desea conectarse ademas desde esos otros clientes mencionados, debe crear "un nuevo root de mysql"con permisos desde para entrar desde cualquier ip. Es decir:
CREATE USER 'root'@'%' IDENTIFIED BY 'Pepelepu1.';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
Y cuando me refiero a que habrán dos root, me refiero exactamente a eso:
mysql> SELECT user, host, plugin FROM mysql.user WHERE user='root';
+------+-----------+-----------------------+
| user | host | plugin |
+------+-----------+-----------------------+
| root | % | caching_sha2_password |
| root | localhost | caching_sha2_password |
+------+-----------+-----------------------+
2 rows in set (0.00 sec)
Por cierto, para que MySQL exhiba su puerto, requiere ademas de cambiar el
bind-address
a 0.0.0.0 en/etc/mysql/mysql.conf.d/mysqld.cnf
, y reiniciar consudo systemctl mysql restart
Avanzado: si está realizando esta instalación en container LXD, o adentro de una red local, y quiere conectarse a MySQL desde algún bonito cliente como DBeaver, es posible que no tenga "vista desde afuera" al puerto. Los containers LXD trabajan por defecto protegidos en su red local. En tal caso lea este otro artículo: Túneles aplicados a MySQL
Pruebe conectarse:
$ mysql -u root -p'Pepelepu1.'

Ahora hay que crear una base solo para Wordpress, con un usuario aparte. Recordar usar los caracteres backsticks
(necesarios para escapar símbolos).
Si usamos nombres con signos en la base, onda "wordpress-base" hay que rodearlo de backsticks, como
wordpress-base
.*
CREATE DATABASE `wordpress-base`;
SHOW DATABASES;
USE mysql;
CREATE USER 'userwordpress'@'localhost' IDENTIFIED WITH mysql_native_password BY 'P@ssW0rd';
GRANT ALL ON `wordpress-base`.* TO 'userwordpress'@'localhost';
O si queremos ser más específicos:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, TRIGGER, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `wordpress-base`.* TO 'userwordpress'@'localhost';
No olvidar en Mysql 8.0 esto:
ALTER USER 'userwordpress'@'localhost' ;
FLUSH PRIVILEGES;
Salimos con exit al shell, y COMPROBAMOS: tratamos de entrar SOLO CON EL USUARIO QUE HEMOS CREADO a la base que le corresponde
mysql -u userwordpress -p'P@ssW0rd' wordpress-base
sudo apt-get update && sudo apt install apache2 php-intl php-json php-curl php-gd php-mbstring php-xml php-xmlrpc php php-mysql libapache2-mod-php
Activar antes de empezar a pelearse con los permalinks (urls amigables)
sudo a2enmod rewrite
sudo systemctl restart apache2
Si desea tener una amable interface gráfica para manejar sus bases de datos, siga este enlace.
Apuntar (registro A) a la ip del server, desde algún Nameserver público como Hurricane (dns.he.net). En ese DNS buscar sus NS1, NS2, etc, y ponerlos en el registrar. Osea, "delegar".
- Si es Argentina, el registrar será nic.ar, unos 8 dolares al año.
- Si es afuera: .com, .online, .mondongo, habrá que hacer lo mismo con alguna empresa tercerizada, ejemplo GoDaddy
- Alternativa gratis: sacarse un subdominio gratis en duckdns.org, y pegarle desde ahi directamente a la ip del server
Entonces la ruta de resolución será
Máquina clienta → nic.ar (Ahi se pusieron los registros NS de Hurricane) → Hurricane (dns.he.net), ahi se pone un registro A con la ip del server → Server → Apache2 "balanceador" con Proxies Reversos (si lo hubiera, apuntando al container LXD/Docker) → Apache2 del container → /var/www/wordpress
Truco cuando no se tiene dominio en internet, cuando se quieren hacer pruebas, o cuando es un sitio interno de la compañía: obligar a las maquinas a ir adonde diga /etc/hosts
¡Ya falta poco!

Apache2 es capaz de gestionar múltiples sitios. Cada sitio se corresponde con un dominio (juan.com, casa.pepe.com.ar, un-alumno.duckdns.org, etc)
También necesita saber en que carpeta estan los archivos de cada sitio. En ocasiones, incluso puede reenviar el tráfico hacia otro servidor, o hacia un container. Ésto último, especialmente cuando se trabaja con otro lenguaje de backend que no sea PHP o Perl.
A todo esto se le llama Virtualhost
Para comenzar se debe entrar a las carpetas /etc/apache2/sites-available/
, /etc/apache2/sites-enabled/
y limpiar todo lo que haya allí, para no confundir al Apache.
Luego creamos un virtualhost.
Ejemplo: /etc/apache2/sites-available/fmayer.com.ar.conf
<VirtualHost *:80>
ServerAdmin [email protected]
DocumentRoot /var/www/wordpress
ServerName fmayer.net.ar
ServerAlias *.fmayer.net.ar
<Directory /var/www/wordpress/>
AllowOverride All
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
También conviene sacar el index.html genérico de Apache y poner Wordpress en su lugar
rm /var/www/html/index.html
cd /var/www/html
wget https://es.wordpress.org/latest-es_ES.tar.gz (la versión que ya viene en español)
tar xvzf latest-es_ES.tar.gz
Por si hemos estado trabajando como root, Apache necesita poder escribir en su home, es decir /var/www:
sudo chown www-data:www-data /var/www/* -R
sudo chmod ug+rw /var/www -R
Luego active el virtualhost.
sudo a2ensite fmayer.com.ar.conf
Tras ello:
- El /etc/apache2/sites-available/fmayer.com.ar.conf debería aparecer linkeado en /etc/apache2/sites-enabled/fmayer.com.ar.conf
Comprobar con ls -l /etc/apache2/sites-enabled/
sudo systemctl restart apache2
Ya puede poner la dirección del sitio en el navegador por primera vez y empezar el autodeploy.
Método clásico, no recomendado, muy retorcido, que expone el puerto 21 del FTP.
sudo apt-get install proftpd-server
Luego se crea un usuario con adduser, y lo agrega al grupo Apache. Ejemplo,
sudo adduser pirulo
sudo adduser pirulo www-data
sudo chown www-data:www-data /var/www
sudo chmod ug+rw /var/www
Ahora puede permitirle al Wordpress, usando el usuario pirulo, "salir", y subir cosas al wordpress, en esta pantalla.

En el wp-config.php, para facilitar la instalacion de plugins y subida de multimedia, sin necesidad de FTP
define('FS_METHOD', 'direct');
Problema de https cuando ingresamos al sitio, /wp-admin

Puede deberse a muchas causas. Hay de hecho varios artículos sobre ese error en Internet. En nuestro escenario, se soluciona usualmente agregando como segunda línea en el archivo wp-config.php (es decir, luego del encabezado), estas tres líneas:
$_SERVER['HTTPS']='on';
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);
La falta de .htaccess puede ser motivo de rutas no encontradas. Controle que tenga así el archivo /var/www/html/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Estas limitaciones existen para que no hayan abusos o ataques DoS en el servidor. Pero también pueden complicar al CMS.
Ejemplos:
- Un mp4 no sube a la galería del Wordpress ni al curso del Moodle
- Moodle necesita autodesplegarse, pero como se demora mucho, el Apache lo mata antes mientras está creando su propia base.
En el ejemplo de los archivos grandes, revise el archivo php.ini. Puede variar la ubicación del archivo si es php 5, php 7, php 8, php 9, etc
Entonces, en el archivo /etc/php/*/apache2/php.ini, aumente los valores en
post_max_size
upload_max_filesized
Un buen valor es 20M - no exagere, para prevenir un DoS. Ej: si un hacker quiere tumbarle el sitio, solo necesitar obtener una cuenta para realizar un posteo, y luego subir una imagen gigante como avatar
Si va a usar Moodle, o necesita agregar plugins más pesados a Wordpress como Divi, o Elementor, considere tambien aumentar memory_limit
de la RAM a 512M.
El archivo wp_config.php necesitará por su parte también una línea
define( 'WP_MEMORY_LIMIT', '512M' );
También considere aumentar en php.ini, pero no demasiado, max_execution_time. Ejemplo: max_execution_time = 60
. Esto permite a un archivo php que se ejecute mas tiempo, antes de que Apache o Nginx le corten el hilo. A veces de hecho es necesario aumentar este valor, cuando un CMS, o un plugin se está auto desplegando, y necesita trabajar en forma sostenida por muchos segundos sin que lo "maten".
Tras cambiar esos valores, luego reinicie el servidor web. En el caso de Apache, es sudo systemctl restart apache2
