Instalación del Stack LAMP (Linux, Apache, MySQL, PHP): Guía Completa para Producción
Introducción
El stack LAMP (Linux, Apache, MySQL, PHP) es una de las plataformas de desarrollo web más populares y probadas para alojar sitios web dinámicos y aplicaciones web. Este conjunto de software de código abierto ha impulsado millones de sitios web en todo el mundo, desde blogs pequeños hasta aplicaciones empresariales. El stack LAMP proporciona una solución robusta, flexible y rentable para alojamiento web que combina la estabilidad de Linux, la confiabilidad de Apache, el poder de MySQL/MariaDB y la versatilidad de PHP.
En esta guía completa, aprenderás cómo instalar y configurar un stack LAMP listo para producción en servidores Linux (Ubuntu/Debian y CentOS/Rocky Linux). Cubriremos el endurecimiento de seguridad, optimización de rendimiento, mejores prácticas y resolución de problemas para asegurar que tus aplicaciones web funcionen de manera eficiente y segura.
Lo que Aprenderás
- Instalación completa del stack LAMP en Ubuntu/Debian y CentOS/Rocky Linux
- Configuración del servidor web Apache y configuración de hosts virtuales
- Instalación de MySQL/MariaDB, configuración de seguridad y optimización
- Instalación de PHP con soporte para múltiples versiones
- Técnicas de endurecimiento de seguridad y configuración de certificados SSL/TLS
- Estrategias de ajuste y optimización de rendimiento
- Monitoreo y resolución de problemas comunes
- Configuraciones listas para producción y mejores prácticas
¿Por Qué Elegir el Stack LAMP?
El stack LAMP ofrece varias ventajas convincentes:
- Maduro y Estable: Décadas de desarrollo y pruebas
- Amplio Soporte Comunitario: Gran comunidad con abundantes recursos
- Rentable: Todos los componentes son gratuitos y de código abierto
- Flexibilidad: Fácilmente personalizable para varios casos de uso
- Amplia Compatibilidad: Soporta la mayoría de aplicaciones PHP incluyendo WordPress, Drupal, Magento
- Bien Documentado: Documentación extensa y tutoriales disponibles
- Listo para Empresas: Utilizado por organizaciones importantes en todo el mundo
Requisitos Previos
Antes de comenzar la instalación del stack LAMP, asegúrate de tener:
Requisitos del Sistema
- Sistema Operativo: Ubuntu 20.04/22.04 LTS, Debian 10/11, CentOS 7/8, o Rocky Linux 8/9
- RAM: Mínimo 1GB (2GB+ recomendado para producción)
- Espacio en Disco: Al menos 10GB de espacio libre (20GB+ recomendado)
- CPU: 1+ núcleos (2+ núcleos recomendados para producción)
- Red: Conexión a internet activa para descargas de paquetes
Requisitos de Acceso
- Acceso root o sudo al servidor
- Acceso SSH al servidor
- Conocimientos básicos de línea de comandos de Linux
- Comprensión de conceptos de redes (direcciones IP, DNS, puertos)
Lista de Verificación Pre-Instalación
- Actualizar paquetes del sistema a las últimas versiones
- Configurar reglas de firewall para permitir HTTP (80) y HTTPS (443)
- Configurar registros DNS apuntando a tu servidor
- Preparar nombres de dominio para hosts virtuales
- Planificar tu estructura de directorios para aplicaciones web
Instalación
Paso 1: Actualización y Preparación del Sistema
Primero, actualiza los paquetes de tu sistema para asegurar que tienes los últimos parches de seguridad y versiones de software.
Para Ubuntu/Debian:
# Actualizar caché del repositorio de paquetes
sudo apt update
# Actualizar todos los paquetes instalados
sudo apt upgrade -y
# Instalar utilidades esenciales
sudo apt install -y curl wget vim git unzip software-properties-common
Para CentOS/Rocky Linux:
# Actualizar caché del repositorio de paquetes
sudo dnf update -y
# Instalar repositorio EPEL (Paquetes Extra para Enterprise Linux)
sudo dnf install -y epel-release
# Instalar utilidades esenciales
sudo dnf install -y curl wget vim git unzip
Paso 2: Instalación del Servidor Web Apache
Apache HTTP Server es la A en LAMP, proporcionando las capacidades de servicio web.
Instalación Ubuntu/Debian:
# Instalar servidor web Apache
sudo apt install -y apache2
# Habilitar Apache para que inicie al arrancar
sudo systemctl enable apache2
# Iniciar servicio Apache
sudo systemctl start apache2
# Verificar que Apache esté ejecutándose
sudo systemctl status apache2
Instalación CentOS/Rocky Linux:
# Instalar Apache (paquete httpd)
sudo dnf install -y httpd
# Habilitar Apache para que inicie al arrancar
sudo systemctl enable httpd
# Iniciar servicio Apache
sudo systemctl start httpd
# Verificar que Apache esté ejecutándose
sudo systemctl status httpd
Configurar Firewall para Apache:
Ubuntu/Debian (UFW):
# Permitir Apache a través del firewall
sudo ufw allow 'Apache Full'
# Verificar reglas del firewall
sudo ufw status
CentOS/Rocky Linux (firewalld):
# Permitir tráfico HTTP
sudo firewall-cmd --permanent --add-service=http
# Permitir tráfico HTTPS
sudo firewall-cmd --permanent --add-service=https
# Recargar reglas del firewall
sudo firewall-cmd --reload
# Verificar reglas del firewall
sudo firewall-cmd --list-all
Verificar Instalación de Apache:
Abre tu navegador web y navega a la dirección IP de tu servidor:
http://tu_ip_del_servidor
Deberías ver la página de bienvenida predeterminada de Apache.
Paso 3: Instalación de MySQL/MariaDB
MySQL (o MariaDB) proporciona el sistema de gestión de bases de datos para el stack LAMP.
Instalación Ubuntu/Debian:
# Instalar servidor MariaDB (recomendado sobre MySQL)
sudo apt install -y mariadb-server mariadb-client
# Habilitar MariaDB para que inicie al arrancar
sudo systemctl enable mariadb
# Iniciar servicio MariaDB
sudo systemctl start mariadb
# Verificar que MariaDB esté ejecutándose
sudo systemctl status mariadb
Instalación CentOS/Rocky Linux:
# Instalar servidor MariaDB
sudo dnf install -y mariadb-server mariadb
# Habilitar MariaDB para que inicie al arrancar
sudo systemctl enable mariadb
# Iniciar servicio MariaDB
sudo systemctl start mariadb
# Verificar que MariaDB esté ejecutándose
sudo systemctl status mariadb
Asegurar Instalación de MySQL/MariaDB:
Ejecuta el script de seguridad para eliminar configuraciones predeterminadas inseguras:
sudo mysql_secure_installation
Sigue las indicaciones:
- Establecer contraseña de root: Elige una contraseña fuerte
- Eliminar usuarios anónimos: Sí
- Deshabilitar inicio de sesión de root remotamente: Sí (por seguridad)
- Eliminar base de datos de prueba: Sí
- Recargar tablas de privilegios: Sí
Probar Conexión a MySQL/MariaDB:
# Iniciar sesión en MySQL como root
sudo mysql -u root -p
# Una vez iniciado sesión, verificar versión
SELECT VERSION();
# Salir de MySQL
EXIT;
Paso 4: Instalación de PHP
PHP es el lenguaje de scripting que procesa contenido dinámico en el stack LAMP.
Instalación Ubuntu/Debian:
# Instalar PHP y módulos comunes
sudo apt install -y php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-xmlrpc php-zip php-intl php-bcmath php-json php-soap
# Reiniciar Apache para cargar el módulo PHP
sudo systemctl restart apache2
# Verificar versión de PHP
php -v
Instalación CentOS/Rocky Linux:
# Instalar PHP y módulos comunes
sudo dnf install -y php php-mysqlnd php-cli php-curl php-gd php-mbstring php-xml php-xmlrpc php-zip php-intl php-bcmath php-json php-soap
# Reiniciar Apache para cargar el módulo PHP
sudo systemctl restart httpd
# Verificar versión de PHP
php -v
Probar Instalación de PHP:
Crea un archivo de información PHP para verificar que PHP está funcionando:
# Crear archivo de información PHP
sudo bash -c 'cat > /var/www/html/info.php <<EOF
<?php
phpinfo();
?>
EOF'
# Establecer permisos adecuados
sudo chmod 644 /var/www/html/info.php
Accede a la página de información de PHP en tu navegador:
http://tu_ip_del_servidor/info.php
Deberías ver información detallada de configuración de PHP.
Importante: Elimina el archivo info.php después de la verificación por seguridad:
sudo rm /var/www/html/info.php
Paso 5: Verificar Instalación del Stack LAMP
Crea un script PHP simple que se conecte a MySQL para verificar que todos los componentes funcionan juntos:
sudo bash -c 'cat > /var/www/html/test_db.php <<EOF
<?php
\$servername = "localhost";
\$username = "root";
\$password = "tu_contraseña_root_mysql";
// Crear conexión
\$conn = new mysqli(\$servername, \$username, \$password);
// Verificar conexión
if (\$conn->connect_error) {
die("Conexión fallida: " . \$conn->connect_error);
}
echo "El Stack LAMP está funcionando! PHP se conectó exitosamente a MySQL.";
\$conn->close();
?>
EOF'
Accede al script de prueba:
http://tu_ip_del_servidor/test_db.php
Importante: Elimina este archivo de prueba después de la verificación:
sudo rm /var/www/html/test_db.php
Configuración
Configuración de Apache
Archivos de Configuración Principales:
- Ubuntu/Debian:
/etc/apache2/apache2.conf - CentOS/Rocky:
/etc/httpd/conf/httpd.conf
Configurar Hosts Virtuales de Apache:
Los hosts virtuales te permiten alojar múltiples sitios web en un solo servidor.
Host Virtual Ubuntu/Debian:
# Crear directorio para tu sitio web
sudo mkdir -p /var/www/example.com/public_html
# Establecer propiedad
sudo chown -R $USER:$USER /var/www/example.com/public_html
# Establecer permisos
sudo chmod -R 755 /var/www/example.com
# Crear página de índice de muestra
cat > /var/www/example.com/public_html/index.html <<EOF
<!DOCTYPE html>
<html>
<head>
<title>Bienvenido a Example.com</title>
</head>
<body>
<h1>¡Éxito! ¡El host virtual de example.com está funcionando!</h1>
</body>
</html>
EOF
# Crear configuración de host virtual
sudo bash -c 'cat > /etc/apache2/sites-available/example.com.conf <<EOF
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin [email protected]
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog \${APACHE_LOG_DIR}/example.com-error.log
CustomLog \${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
EOF'
# Habilitar el host virtual
sudo a2ensite example.com.conf
# Habilitar mod_rewrite (para reescritura de URL)
sudo a2enmod rewrite
# Probar configuración de Apache
sudo apache2ctl configtest
# Reiniciar Apache
sudo systemctl restart apache2
Host Virtual CentOS/Rocky:
# Crear directorio para tu sitio web
sudo mkdir -p /var/www/example.com/public_html
# Establecer propiedad
sudo chown -R apache:apache /var/www/example.com/public_html
# Establecer permisos
sudo chmod -R 755 /var/www/example.com
# Crear página de índice de muestra
sudo bash -c 'cat > /var/www/example.com/public_html/index.html <<EOF
<!DOCTYPE html>
<html>
<head>
<title>Bienvenido a Example.com</title>
</head>
<body>
<h1>¡Éxito! ¡El host virtual de example.com está funcionando!</h1>
</body>
</html>
EOF'
# Crear configuración de host virtual
sudo bash -c 'cat > /etc/httpd/conf.d/example.com.conf <<EOF
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin [email protected]
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/httpd/example.com-error.log
CustomLog /var/log/httpd/example.com-access.log combined
</VirtualHost>
EOF'
# Probar configuración de Apache
sudo httpd -t
# Reiniciar Apache
sudo systemctl restart httpd
Ajuste de Rendimiento de Apache:
Edita la configuración del MPM (Módulo de Multiprocesamiento):
Ubuntu/Debian:
sudo vim /etc/apache2/mods-available/mpm_prefork.conf
CentOS/Rocky:
sudo vim /etc/httpd/conf.modules.d/00-mpm.conf
Configuración recomendada de MPM Prefork para un servidor con 2GB RAM:
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 3000
</IfModule>
Configuración de MySQL/MariaDB
Archivo de Configuración Principal:
- Ubuntu/Debian:
/etc/mysql/mariadb.conf.d/50-server.cnf - CentOS/Rocky:
/etc/my.cnf.d/mariadb-server.cnf
Crear Base de Datos y Usuario:
# Iniciar sesión en MySQL
sudo mysql -u root -p
# Crear base de datos
CREATE DATABASE myapp_db;
# Crear usuario con contraseña
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'contraseña_fuerte_aquí';
# Otorgar privilegios
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
# Actualizar privilegios
FLUSH PRIVILEGES;
# Salir
EXIT;
Ajuste de Rendimiento de MySQL:
Edita el archivo de configuración de MySQL y agrega estas optimizaciones:
[mysqld]
# Configuraciones básicas
max_connections = 100
connect_timeout = 10
wait_timeout = 600
max_allowed_packet = 64M
thread_cache_size = 128
sort_buffer_size = 4M
bulk_insert_buffer_size = 16M
tmp_table_size = 32M
max_heap_table_size = 32M
# Configuraciones InnoDB (para servidor con 2GB RAM)
innodb_buffer_pool_size = 512M
innodb_log_file_size = 128M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
# Caché de consultas (obsoleto en versiones más nuevas)
query_cache_limit = 2M
query_cache_size = 64M
# Logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
Reinicia MySQL para aplicar cambios:
sudo systemctl restart mariadb
Configuración de PHP
Archivo de Configuración Principal:
- Ubuntu/Debian:
/etc/php/8.x/apache2/php.ini - CentOS/Rocky:
/etc/php.ini
Configuraciones PHP Recomendadas:
Edita el archivo php.ini y ajusta estas configuraciones:
# Límites de memoria y ejecución
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
post_max_size = 64M
upload_max_filesize = 64M
# Reporte de errores (para producción)
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
log_errors = On
error_log = /var/log/php_errors.log
# Configuraciones de seguridad
expose_php = Off
allow_url_fopen = On
allow_url_include = Off
# Configuraciones de sesión
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
# Zona horaria
date.timezone = America/New_York
# Configuraciones OPcache (rendimiento)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1
Reinicia Apache para aplicar cambios de PHP:
# Ubuntu/Debian
sudo systemctl restart apache2
# CentOS/Rocky
sudo systemctl restart httpd
Despliegue
Despliegue de una Aplicación PHP
Método 1: Despliegue Manual
# Crear directorio de aplicación
sudo mkdir -p /var/www/myapp.com/public_html
# Subir archivos de tu aplicación usando SCP
scp -r /ruta/a/app/local/* user@ip_servidor:/var/www/myapp.com/public_html/
# O usar rsync para actualizaciones incrementales
rsync -avz --progress /ruta/a/app/local/ user@ip_servidor:/var/www/myapp.com/public_html/
# Establecer propiedad adecuada
sudo chown -R www-data:www-data /var/www/myapp.com/public_html # Ubuntu/Debian
sudo chown -R apache:apache /var/www/myapp.com/public_html # CentOS/Rocky
# Establecer permisos adecuados
sudo find /var/www/myapp.com/public_html -type d -exec chmod 755 {} \;
sudo find /var/www/myapp.com/public_html -type f -exec chmod 644 {} \;
Método 2: Despliegue Basado en Git
# Instalar git si no está ya instalado
sudo apt install git -y # Ubuntu/Debian
sudo dnf install git -y # CentOS/Rocky
# Clonar repositorio
cd /var/www/myapp.com
sudo git clone https://github.com/usuario/myapp.git public_html
# Establecer propiedad adecuada
sudo chown -R www-data:www-data /var/www/myapp.com/public_html # Ubuntu/Debian
# Configurar actualizaciones automáticas (opcional)
cd /var/www/myapp.com/public_html
sudo git config --global --add safe.directory /var/www/myapp.com/public_html
Ejemplo de Despliegue de WordPress:
# Descargar WordPress
cd /tmp
wget https://wordpress.org/latest.tar.gz
# Extraer WordPress
tar -xzf latest.tar.gz
# Mover al directorio web
sudo mv wordpress/* /var/www/myapp.com/public_html/
# Crear wp-config.php
sudo cp /var/www/myapp.com/public_html/wp-config-sample.php /var/www/myapp.com/public_html/wp-config.php
# Editar wp-config.php con credenciales de base de datos
sudo vim /var/www/myapp.com/public_html/wp-config.php
# Establecer propiedad adecuada
sudo chown -R www-data:www-data /var/www/myapp.com/public_html
# Establecer permisos adecuados
sudo find /var/www/myapp.com/public_html -type d -exec chmod 755 {} \;
sudo find /var/www/myapp.com/public_html -type f -exec chmod 644 {} \;
Instalación de Certificado SSL/TLS
Asegura tu sitio con certificados SSL gratuitos de Let's Encrypt:
Ubuntu/Debian:
# Instalar Certbot
sudo apt install -y certbot python3-certbot-apache
# Obtener e instalar certificado
sudo certbot --apache -d example.com -d www.example.com
# Probar renovación automática
sudo certbot renew --dry-run
CentOS/Rocky:
# Instalar Certbot
sudo dnf install -y certbot python3-certbot-apache
# Obtener e instalar certificado
sudo certbot --apache -d example.com -d www.example.com
# Probar renovación automática
sudo certbot renew --dry-run
Certbot configurará automáticamente Apache para HTTPS y establecerá la renovación automática.
Monitoreo
Monitoreo de Apache
Habilitar Módulo de Estado de Apache:
Ubuntu/Debian:
# Habilitar módulo de estado
sudo a2enmod status
# Reiniciar Apache
sudo systemctl restart apache2
CentOS/Rocky:
# Agregar a configuración de Apache
sudo bash -c 'cat >> /etc/httpd/conf.d/status.conf <<EOF
<Location "/server-status">
SetHandler server-status
Require local
</Location>
EOF'
# Reiniciar Apache
sudo systemctl restart httpd
Acceder al estado del servidor:
http://localhost/server-status
Monitorear Logs de Apache:
# Monitoreo en tiempo real del log de acceso
sudo tail -f /var/log/apache2/access.log # Ubuntu/Debian
sudo tail -f /var/log/httpd/access_log # CentOS/Rocky
# Monitoreo en tiempo real del log de errores
sudo tail -f /var/log/apache2/error.log # Ubuntu/Debian
sudo tail -f /var/log/httpd/error_log # CentOS/Rocky
# Analizar URLs más solicitadas
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
# Analizar códigos de estado HTTP
awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -rn
# Analizar IPs visitantes principales
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
Monitoreo de MySQL/MariaDB
Monitorear Rendimiento de Base de Datos:
# Iniciar sesión en MySQL
sudo mysql -u root -p
# Mostrar procesos actuales
SHOW PROCESSLIST;
# Mostrar estado de base de datos
SHOW STATUS;
# Mostrar estado de InnoDB
SHOW ENGINE INNODB STATUS\G
# Mostrar consultas lentas
SHOW VARIABLES LIKE 'slow_query_log%';
# Monitorear conexiones de base de datos
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';
Monitorear Logs de MySQL:
# Ver log de errores de MySQL
sudo tail -f /var/log/mysql/error.log
# Ver log de consultas lentas
sudo tail -f /var/log/mysql/slow-query.log
# Analizar consultas lentas con mysqldumpslow
sudo mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
Monitoreo de PHP
Monitorear Errores de PHP:
# Ver log de errores de PHP
sudo tail -f /var/log/php_errors.log
# Monitorear estado de PHP-FPM (si se usa PHP-FPM)
sudo systemctl status php7.4-fpm # Ubuntu/Debian
sudo systemctl status php-fpm # CentOS/Rocky
Verificar Estado de OPcache de PHP:
Crea un script de estado simple:
sudo bash -c 'cat > /var/www/html/opcache-status.php <<EOF
<?php
if (function_exists("opcache_get_status")) {
\$status = opcache_get_status();
echo "<pre>";
print_r(\$status);
echo "</pre>";
} else {
echo "OPcache no está habilitado";
}
?>
EOF'
Acceder: http://tu_ip_del_servidor/opcache-status.php
Recuerda eliminar este archivo después de verificar:
sudo rm /var/www/html/opcache-status.php
Monitoreo de Recursos del Sistema
# Monitorear uso de CPU y memoria
htop
# Monitorear uso de disco
df -h
# Monitorear E/S de disco
iostat -x 1
# Monitorear conexiones de red
netstat -tunlp
# Monitorear conexiones de Apache
netstat -an | grep :80 | wc -l
# Monitorear conexiones de MySQL
netstat -an | grep :3306 | wc -l
Script de Monitoreo Automatizado
Crea un script de monitoreo:
sudo bash -c 'cat > /usr/local/bin/lamp-monitor.sh <<EOF
#!/bin/bash
echo "=== Reporte de Monitoreo del Stack LAMP ==="
echo "Fecha: \$(date)"
echo ""
echo "=== Estado de Apache ==="
systemctl status apache2 | head -3 || systemctl status httpd | head -3
echo "Conexiones activas: \$(netstat -an | grep :80 | wc -l)"
echo ""
echo "=== Estado de MySQL ==="
systemctl status mariadb | head -3
echo "Conexiones activas: \$(netstat -an | grep :3306 | wc -l)"
echo ""
echo "=== Uso de Disco ==="
df -h | grep -E "Filesystem|/dev/|/var"
echo ""
echo "=== Uso de Memoria ==="
free -h
echo ""
echo "=== Procesos Principales por CPU ==="
ps aux --sort=-%cpu | head -6
echo ""
echo "=== Procesos Principales por Memoria ==="
ps aux --sort=-%mem | head -6
EOF'
# Hacer ejecutable
sudo chmod +x /usr/local/bin/lamp-monitor.sh
# Ejecutar el script
sudo /usr/local/bin/lamp-monitor.sh
Resolución de Problemas
Apache No Inicia
Problema: Apache falla al iniciar
Verificar logs de error:
# Ubuntu/Debian
sudo journalctl -u apache2 -n 50
sudo tail -n 50 /var/log/apache2/error.log
# CentOS/Rocky
sudo journalctl -u httpd -n 50
sudo tail -n 50 /var/log/httpd/error_log
Soluciones comunes:
- Puerto ya en uso:
# Verificar qué está usando el puerto 80
sudo lsof -i :80
sudo netstat -tunlp | grep :80
# Matar el proceso conflictivo o cambiar puerto de Apache
- Error de sintaxis de configuración:
# Probar configuración
sudo apache2ctl configtest # Ubuntu/Debian
sudo httpd -t # CentOS/Rocky
# Corregir errores de sintaxis mostrados en la salida
- Certificado SSL faltante:
# Si falta certificado SSL, deshabilitar temporalmente host virtual SSL
sudo a2dissite example.com-ssl.conf # Ubuntu/Debian
# O comentar host virtual SSL en CentOS/Rocky
Errores de Conexión MySQL
Problema: "No se puede conectar al servidor MySQL"
Soluciones:
- Verificar si MySQL está ejecutándose:
sudo systemctl status mariadb
sudo systemctl start mariadb
- Verificar archivo de socket de MySQL:
# Encontrar ubicación del archivo de socket
mysql_config --socket
# Verificar que el archivo de socket existe
ls -l /var/run/mysqld/mysqld.sock
# Si falta, reiniciar MySQL
sudo systemctl restart mariadb
- Verificar firewall y bind-address:
# Editar configuración de MySQL
sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
# Asegurar que bind-address está configurado correctamente
bind-address = 127.0.0.1 # Solo para conexiones locales
# o
bind-address = 0.0.0.0 # Para conexiones remotas (menos seguro)
# Reiniciar MySQL
sudo systemctl restart mariadb
- Verificar credenciales de usuario:
# Iniciar sesión en MySQL
sudo mysql -u root -p
# Verificar que el usuario existe
SELECT User, Host FROM mysql.user;
# Otorgar privilegios adecuados
GRANT ALL PRIVILEGES ON nombre_base_datos.* TO 'usuario'@'localhost';
FLUSH PRIVILEGES;
PHP No se Ejecuta
Problema: Los archivos PHP se descargan en lugar de ejecutarse
Soluciones:
- Verificar que el módulo PHP está cargado:
# Ubuntu/Debian
apache2ctl -M | grep php
# CentOS/Rocky
httpd -M | grep php
# Si no está cargado, habilitar módulo PHP
sudo a2enmod php7.4 # Ubuntu/Debian
# Reiniciar Apache
sudo systemctl restart apache2 # Ubuntu/Debian
sudo systemctl restart httpd # CentOS/Rocky
- Verificar configuración de Apache:
# Asegurar que DirectoryIndex incluye archivos PHP
# Agregar a configuración de Apache o .htaccess:
DirectoryIndex index.php index.html
# Agregar manejador PHP
AddHandler application/x-httpd-php .php
- Verificar instalación de PHP:
php -v
php -m # Listar módulos PHP
Errores de Permisos
Problema: Errores "403 Forbidden" o de permisos denegados
Soluciones:
- Establecer propiedad adecuada:
# Ubuntu/Debian
sudo chown -R www-data:www-data /var/www/tu_sitio
# CentOS/Rocky
sudo chown -R apache:apache /var/www/tu_sitio
- Establecer permisos adecuados:
# Directorios: 755
sudo find /var/www/tu_sitio -type d -exec chmod 755 {} \;
# Archivos: 644
sudo find /var/www/tu_sitio -type f -exec chmod 644 {} \;
# Directorios con permisos de escritura (uploads, cache): 775
sudo chmod 775 /var/www/tu_sitio/uploads
- Verificar SELinux (CentOS/Rocky):
# Verificar estado de SELinux
getenforce
# Establecer contexto correcto de SELinux
sudo chcon -R -t httpd_sys_content_t /var/www/tu_sitio
sudo chcon -R -t httpd_sys_rw_content_t /var/www/tu_sitio/uploads
# O deshabilitar SELinux temporalmente para pruebas
sudo setenforce 0
# Para hacer permanente, editar /etc/selinux/config
Alto Uso de Memoria
Problema: El servidor se está quedando sin memoria
Soluciones:
- Optimizar configuraciones MPM de Apache:
# Reducir MaxRequestWorkers en configuración MPM
# Ver sección de Ajuste de Rendimiento de Apache arriba
- Optimizar uso de memoria de MySQL:
# Reducir tamaño del buffer pool en configuración MySQL
innodb_buffer_pool_size = 256M # En lugar de 512M
# Reiniciar MySQL
sudo systemctl restart mariadb
- Habilitar OPcache de PHP:
# Verificar que OPcache está habilitado en php.ini
opcache.enable = 1
opcache.memory_consumption = 128
# Reiniciar Apache
sudo systemctl restart apache2 # Ubuntu/Debian
sudo systemctl restart httpd # CentOS/Rocky
- Monitorear y matar procesos con alto uso de memoria:
# Encontrar procesos que consumen mucha memoria
ps aux --sort=-%mem | head -10
# Matar proceso específico si es necesario
sudo kill -9 PID
Rendimiento Lento del Sitio Web
Problema: El sitio web carga lentamente
Pasos de diagnóstico:
- Verificar carga del servidor:
uptime
top
htop
- Analizar logs de acceso de Apache:
# Encontrar solicitudes lentas
awk '$NF > 1000 {print $0}' /var/log/apache2/access.log | tail -20
- Identificar consultas lentas de MySQL:
# Habilitar log de consultas lentas
sudo mysql -u root -p
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
# Verificar log de consultas lentas
sudo tail -f /var/log/mysql/slow-query.log
- Verificar tiempo de ejecución de PHP:
# Agregar a script PHP para depuración
ini_set('display_errors', 1);
error_reporting(E_ALL);
$start = microtime(true);
// Tu código aquí
$end = microtime(true);
echo "Tiempo de ejecución: " . ($end - $start) . " segundos";
Optimización de rendimiento:
- Habilitar caché (ver sección de Ajuste de Rendimiento)
- Optimizar consultas de base de datos y agregar índices
- Habilitar compresión (Gzip/Brotli)
- Usar un CDN para contenido estático
- Optimizar imágenes y recursos
- Implementar OPcache de PHP
- Usar Redis o Memcached para almacenamiento de sesiones
Mejores Prácticas de Seguridad
Endurecimiento de Seguridad de Apache
- Ocultar información de versión de Apache:
# Editar configuración de Apache
sudo vim /etc/apache2/conf-available/security.conf # Ubuntu/Debian
sudo vim /etc/httpd/conf/httpd.conf # CentOS/Rocky
# Agregar o modificar estas líneas
ServerTokens Prod
ServerSignature Off
- Deshabilitar listado de directorios:
# En configuración de host virtual
Options -Indexes +FollowSymLinks
- Restringir acceso por IP (si es necesario):
<Directory /var/www/admin>
Require ip 192.168.1.0/24
Require ip 10.0.0.5
</Directory>
- Habilitar ModSecurity (Firewall de Aplicación Web):
# Ubuntu/Debian
sudo apt install -y libapache2-mod-security2
# Habilitar módulo
sudo a2enmod security2
# Reiniciar Apache
sudo systemctl restart apache2
Endurecimiento de Seguridad de MySQL
- Deshabilitar inicio de sesión remoto de root:
sudo mysql -u root -p
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
FLUSH PRIVILEGES;
- Usar contraseñas fuertes:
# Establecer política de contraseñas
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
- Respaldos regulares:
# Crear script de respaldo
sudo bash -c 'cat > /usr/local/bin/mysql-backup.sh <<EOF
#!/bin/bash
DATE=\$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/mysql"
mkdir -p \$BACKUP_DIR
mysqldump -u root -p\$MYSQL_ROOT_PASSWORD --all-databases | gzip > \$BACKUP_DIR/all_databases_\$DATE.sql.gz
find \$BACKUP_DIR -type f -mtime +7 -delete
EOF'
sudo chmod +x /usr/local/bin/mysql-backup.sh
- Limitar privilegios de usuario de base de datos:
# Otorgar solo privilegios necesarios
GRANT SELECT, INSERT, UPDATE, DELETE ON nombre_base_datos.* TO 'usuario'@'localhost';
# Evitar usar GRANT ALL a menos que sea necesario
Endurecimiento de Seguridad de PHP
- Deshabilitar funciones peligrosas:
# Agregar a php.ini
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
- Configurar seguridad de subida de archivos:
# Agregar a php.ini
file_uploads = On
upload_max_filesize = 10M
max_file_uploads = 5
# En tu aplicación PHP, validar tipos de archivo
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['file']['type'], $allowed_types)) {
die('Tipo de archivo inválido');
}
- Usar sentencias preparadas para consultas de base de datos:
// Mal (vulnerable a inyección SQL)
$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";
// Bien (usando sentencias preparadas)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $_POST['username']]);
- Habilitar restricción open_basedir:
# Agregar a php.ini o configuración de host virtual
open_basedir = /var/www/tu_sitio:/tmp
Configuración de Firewall
- Configurar UFW (Ubuntu/Debian):
# Habilitar firewall
sudo ufw enable
# Permitir SSH
sudo ufw allow 22/tcp
# Permitir HTTP y HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Permitir MySQL solo desde IP específica (si es necesario)
sudo ufw allow from 192.168.1.100 to any port 3306
# Ver reglas
sudo ufw status verbose
- Configurar firewalld (CentOS/Rocky):
# Habilitar firewall
sudo systemctl enable firewalld
sudo systemctl start firewalld
# Permitir HTTP y HTTPS
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Permitir MySQL solo desde IP específica (si es necesario)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="3306" protocol="tcp" accept'
# Recargar firewall
sudo firewall-cmd --reload
# Ver reglas
sudo firewall-cmd --list-all
Fail2Ban para Protección contra Fuerza Bruta
# Instalar Fail2Ban
sudo apt install -y fail2ban # Ubuntu/Debian
sudo dnf install -y fail2ban # CentOS/Rocky
# Crear configuración local
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Editar configuración
sudo vim /etc/fail2ban/jail.local
# Agregar protección para Apache
[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log
maxretry = 3
bantime = 3600
# Habilitar e iniciar Fail2Ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Verificar estado
sudo fail2ban-client status
Optimización de Rendimiento
Habilitar Caché de Apache
- Habilitar mod_cache:
# Ubuntu/Debian
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod expires
sudo a2enmod headers
# Reiniciar Apache
sudo systemctl restart apache2
- Configurar caché en host virtual:
<VirtualHost *:80>
# ... otra configuración ...
# Habilitar caché
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_cache_disk
CacheDefaultExpire 3600
CacheMaxExpire 86400
# Caché del navegador
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType text/html "access plus 1 hour"
</IfModule>
</VirtualHost>
Habilitar Compresión Gzip
# Ubuntu/Debian
sudo a2enmod deflate
# Agregar a host virtual o .htaccess
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
# Reiniciar Apache
sudo systemctl restart apache2
Optimización de Consultas MySQL
- Habilitar caché de consultas:
# Agregar a configuración MySQL
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M
- Agregar índices a columnas consultadas frecuentemente:
# Analizar consultas lentas
EXPLAIN SELECT * FROM tabla WHERE columna = 'valor';
# Agregar índice si es necesario
CREATE INDEX idx_columna ON tabla(columna);
# Ver índices existentes
SHOW INDEX FROM tabla;
- Optimizar tablas regularmente:
# Ejecutar optimización
sudo mysql -u root -p
OPTIMIZE TABLE nombre_tabla;
# O optimizar todas las tablas en una base de datos
mysqlcheck -u root -p --optimize nombre_base_datos
Configuración de OPcache de PHP
OPcache almacena en caché código PHP compilado en memoria, mejorando significativamente el rendimiento:
# Verificar que OPcache está habilitado
php -i | grep opcache
# Configuraciones recomendadas de OPcache en php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=0
# Reiniciar Apache
sudo systemctl restart apache2 # Ubuntu/Debian
sudo systemctl restart httpd # CentOS/Rocky
Usar Redis para Almacenamiento de Sesiones
Instalar Redis para almacenamiento de sesiones PHP mejora el rendimiento:
# Instalar Redis
sudo apt install -y redis-server php-redis # Ubuntu/Debian
sudo dnf install -y redis php-redis # CentOS/Rocky
# Configurar PHP para usar Redis para sesiones
sudo vim /etc/php/8.x/apache2/php.ini
# Agregar estas líneas
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
# Reiniciar servicios
sudo systemctl restart redis
sudo systemctl restart apache2 # Ubuntu/Debian
sudo systemctl restart httpd # CentOS/Rocky
Conclusión
Ahora tienes un stack LAMP completamente funcional y listo para producción, configurado con endurecimiento de seguridad, optimizaciones de rendimiento y herramientas de monitoreo. Esta configuración integral proporciona una base sólida para alojar aplicaciones web basadas en PHP que van desde sitios web simples hasta plataformas web complejas.
Puntos Clave
- Seguridad Primero: Siempre implementa mejores prácticas de seguridad incluyendo SSL/TLS, contraseñas fuertes, reglas de firewall y actualizaciones regulares
- El Rendimiento Importa: Habilita caché, compresión y optimiza consultas de base de datos para mejor rendimiento
- Monitoreo Regular: Configura herramientas de monitoreo y revisa logs regularmente para detectar problemas temprano
- Respalda Todo: Implementa estrategias de respaldo automatizado para archivos y bases de datos
- Mantén Actualizado: Actualiza regularmente todos los componentes (Linux, Apache, MySQL, PHP) para parches de seguridad
- Documentación: Documenta tu configuración y personalizaciones para referencia futura
Próximos Pasos
- Implementar Respaldos Automatizados: Configura respaldos diarios automatizados de tus bases de datos y archivos web
- Configurar Monitoreo: Instala herramientas de monitoreo como Nagios, Zabbix, o usa soluciones basadas en la nube
- Configurar Entorno de Staging: Crea un entorno de staging para probar cambios antes de producción
- Implementar CI/CD: Automatiza el despliegue con herramientas como Jenkins, GitLab CI o GitHub Actions
- Considerar Alta Disponibilidad: Para aplicaciones críticas, implementa balanceo de carga y replicación de base de datos
- Pruebas de Rendimiento: Realiza regularmente pruebas de carga para identificar cuellos de botella
- Auditorías de Seguridad: Realiza auditorías de seguridad regulares y escaneos de vulnerabilidades
Recursos Adicionales
- Documentación de Apache: https://httpd.apache.org/docs/
- Documentación de MySQL: https://dev.mysql.com/doc/
- Documentación de MariaDB: https://mariadb.org/documentation/
- Documentación de PHP: https://www.php.net/docs.php
- Let's Encrypt: https://letsencrypt.org/docs/
- Tutoriales de DigitalOcean: https://www.digitalocean.com/community/tutorials
- Linux Academy: https://linuxacademy.com/
Soporte y Comunidad
Si encuentras problemas o necesitas ayuda:
- Stack Overflow: Busca o haz preguntas sobre problemas específicos
- Server Fault: Para preguntas de administración de sistemas
- Lista de Correo de Usuarios de Apache: Para problemas específicos de Apache
- Foros de MySQL: Para preguntas relacionadas con bases de datos
- Comunidad PHP: PHP.net y varios foros de PHP
El stack LAMP sigue siendo una de las soluciones de alojamiento web más confiables y ampliamente adoptadas. Con la configuración adecuada, medidas de seguridad y mantenimiento continuo, tu stack LAMP proporcionará años de servicio confiable para tus aplicaciones web.
¡Feliz despliegue!


