---
title: "Cómo instalar un stack LAMP en Ubuntu 24.04"
description: "Instala Apache, MySQL 8 y PHP 8.3 en Ubuntu 24.04, crea un virtual host con su base de datos, prueba la conexión desde PHP y protege el sitio con HTTPS."
category: "Despliegue de Aplicaciones"
language: es
source: https://cubepath.com/es/docs/despliegue-de-aplicaciones/instalacion-de-stack-lamp-linux-apache-mysql-php
updated: 2026-09-25
---
# Cómo instalar un stack LAMP en Ubuntu 24.04
LAMP es la combinación clásica para servir aplicaciones PHP: Linux como sistema operativo, Apache como servidor web, MySQL como base de datos y PHP como lenguaje. En este tutorial instalarás los tres componentes desde los repositorios de Ubuntu 24.04 (Apache 2.4, MySQL 8.0 y PHP 8.3), crearás un virtual host para tu dominio, comprobarás que PHP lee datos de MySQL y activarás HTTPS con un certificado gratuito de Let's Encrypt.
## Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 1 GB de RAM (2 GB recomendados si vas a alojar WordPress u otro CMS).
- Un usuario no root con privilegios `sudo`.
- Un dominio con un registro `A` apuntando a la IP pública del servidor, necesario para el paso de HTTPS. En la guía se usa `your_domain`: sustitúyelo por el tuyo.
## Paso 1: Instalar Apache y abrir el firewall
Actualiza el índice de paquetes e instala Apache:
```bash
sudo apt update
sudo apt install -y apache2
```
En Ubuntu el servicio queda arrancado y habilitado al instalarlo. Compruébalo:
```bash
sudo systemctl status apache2 --no-pager
```
```output
● apache2.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-24 10:12:03 UTC; 15s ago
```
Apache registra perfiles en UFW. Permite SSH antes de nada (si activas el firewall sin esta regla perderás la conexión) y después el perfil `Apache Full`, que abre los puertos 80 y 443:
```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
sudo ufw enable
sudo ufw status
```
```output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Apache Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Apache Full (v6) ALLOW Anywhere (v6)
```
Abre `http://your_server_ip` en el navegador. Deberías ver la página "Apache2 Default Page". Desde la propia terminal puedes comprobarlo con:
```bash
curl -sI http://localhost | head -n 1
```
```output
HTTP/1.1 200 OK
```
## Paso 2: Instalar MySQL
Instala el servidor MySQL:
```bash
sudo apt install -y mysql-server
```
Comprueba que está en marcha y qué versión tienes:
```bash
sudo systemctl status mysql --no-pager
mysql --version
```
```output
mysql Ver 8.0.43-0ubuntu0.24.04.1 for Linux on x86_64 ((Ubuntu))
```
Ejecuta el asistente de seguridad, que elimina los usuarios anónimos, la base de datos de prueba y el acceso remoto de root:
```bash
sudo mysql_secure_installation
```
Responde `Y` a todas las preguntas. Si activas el componente de validación de contraseñas, elige el nivel `1` (MEDIUM) o `2` (STRONG). En Ubuntu, el usuario `root` de MySQL se autentica con el plugin `auth_socket`: no usa contraseña, sino que solo permite entrar al usuario root del sistema. Por eso el asistente puede saltarse el paso de la contraseña de root, y es el comportamiento deseado.
Comprueba que puedes entrar a la consola de MySQL:
```bash
sudo mysql
```
Sal con `exit`. Las aplicaciones nunca deben usar la cuenta `root`: en el paso 5 crearás un usuario propio.
## Paso 3: Instalar PHP
Instala PHP 8.3 junto con el módulo de Apache (`libapache2-mod-php`), el conector de MySQL y las extensiones que piden la mayoría de aplicaciones:
```bash
sudo apt install -y php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl
```
Comprueba la versión:
```bash
php -v
```
```output
PHP 8.3.6 (cli) (built: Jul 14 2025 18:30:55) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.6, Copyright (c) Zend Technologies
with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies
```
El módulo de PHP se activa automáticamente en Apache. Compruébalo:
```bash
sudo apache2ctl -M | grep php
```
```output
php_module (shared)
```
OPcache, que guarda en memoria el código PHP ya compilado, viene activado por defecto.
## Paso 4: Crear un virtual host para tu dominio
Un virtual host permite servir varios sitios desde el mismo Apache, cada uno con su dominio y su directorio. Crea el directorio del sitio y asígnalo a tu usuario para poder editar los archivos sin `sudo`:
```bash
sudo mkdir -p /var/www/your_domain
sudo chown -R $USER:$USER /var/www/your_domain
```
Crea el archivo de configuración del virtual host:
```bash
sudo nano /etc/apache2/sites-available/your_domain.conf
```
```apache
PHP ' . PHP_VERSION . '
'; ``` Pídela desde la terminal (o abre `http://your_domain/prueba.php` en el navegador): ```bash curl -s -H "Host: your_domain" http://localhost/prueba.php ``` ```outputPHP 8.3.6
``` Si ves la lista, Apache ejecuta PHP y PHP se conecta a MySQL: el stack funciona. Borra el archivo, porque contiene la contraseña de la base de datos: ```bash rm /var/www/your_domain/prueba.php ``` ## Paso 7: Ajustar PHP y ocultar las versiones Los valores por defecto de PHP limitan las subidas a 2 MB, poco para la mayoría de aplicaciones. Edita el `php.ini` que usa Apache: ```bash sudo nano /etc/php/8.3/apache2/php.ini ``` Busca estas directivas (con `Ctrl+W` en nano) y ajústalas: ```ini upload_max_filesize = 64M post_max_size = 64M memory_limit = 256M expose_php = Off date.timezone = Europe/Madrid ``` `expose_php = Off` quita la cabecera `X-Powered-By` que revela la versión de PHP. Cambia la zona horaria por la tuya. `display_errors` ya viene desactivado en este archivo, que es lo correcto en producción. Haz lo mismo con Apache, que por defecto anuncia su versión y el sistema operativo en las cabeceras y en las páginas de error: ```bash sudo nano /etc/apache2/conf-available/security.conf ``` ```apache ServerTokens Prod ServerSignature Off ``` Reinicia Apache para aplicar ambos cambios y verifica la cabecera: ```bash sudo systemctl restart apache2 curl -sI -H "Host: your_domain" http://localhost | grep -i '^server' ``` ```output Server: Apache ``` ## Paso 8: Activar HTTPS con Let's Encrypt Certbot obtiene un certificado gratuito de Let's Encrypt y configura Apache para usarlo. Instálalo con su plugin de Apache: ```bash sudo apt install -y certbot python3-certbot-apache ``` Comprueba que tu dominio resuelve a la IP del servidor y solicita el certificado para las dos variantes del dominio: ```bash dig +short your_domain sudo certbot --apache -d your_domain -d www.your_domain ``` Certbot te pedirá un correo para avisos de caducidad y que aceptes los términos. Al terminar crea el virtual host `your_domain-le-ssl.conf` en el puerto 443 y añade al del puerto 80 una redirección a HTTPS. ```output Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem ... Congratulations! You have successfully enabled HTTPS on https://your_domain and https://www.your_domain ``` Los certificados se renuevan solos gracias al temporizador de systemd que instala el paquete. Compruébalo y simula una renovación: ```bash systemctl list-timers certbot.timer sudo certbot renew --dry-run ``` Abre `https://your_domain` en el navegador y verifica que aparece el candado. ## Paso 9: Programar copias de seguridad de la base de datos Un script sencillo, ejecutado a diario por cron, basta para tener copias de la base de datos con rotación. Crea el directorio de destino y el script: ```bash sudo mkdir -p /var/backups/mysql sudo nano /usr/local/bin/mysql-backup.sh ``` ```bash #!/usr/bin/env bash set -euo pipefail BACKUP_DIR="/var/backups/mysql" DB_NAME="app_db" RETENTION_DAYS=7 TIMESTAMP="$(date +%Y%m%d-%H%M%S)" mysqldump --single-transaction --routines --triggers "$DB_NAME" \ | gzip > "$BACKUP_DIR/${DB_NAME}-${TIMESTAMP}.sql.gz" find "$BACKUP_DIR" -name "${DB_NAME}-*.sql.gz" -mtime +"$RETENTION_DAYS" -delete ``` El script se ejecuta como root, así que `mysqldump` se autentica por `auth_socket` sin guardar contraseñas en ningún archivo, y `--single-transaction` hace una copia coherente de las tablas InnoDB sin bloquearlas. Dale permisos de ejecución y pruébalo: ```bash sudo chmod 750 /usr/local/bin/mysql-backup.sh sudo /usr/local/bin/mysql-backup.sh ls -lh /var/backups/mysql ``` ```output -rw-r--r-- 1 root root 1.2K Sep 24 10:40 app_db-20260924-104012.sql.gz ``` Prográmalo cada noche a las 3:00 creando un archivo en `/etc/cron.d`: ```bash echo '0 3 * * * root /usr/local/bin/mysql-backup.sh' | sudo tee /etc/cron.d/mysql-backup ``` Para restaurar una copia: `gunzip < archivo.sql.gz | sudo mysql app_db`. Guarda también copias fuera del servidor, por ejemplo en un almacenamiento de objetos. ## Solución de problemas - **El navegador descarga el archivo `.php` en lugar de ejecutarlo**: el módulo de PHP no está cargado. Comprueba con `sudo apache2ctl -M | grep php`; si no aparece, actívalo con `sudo a2enmod php8.3` y reinicia Apache. - **Apache no arranca tras un cambio**: ejecuta `sudo apache2ctl configtest` para ver la línea con el error y revisa `sudo journalctl -u apache2 -n 50`. - **`403 Forbidden`**: el directorio no tiene índice (`Options -Indexes` impide el listado) o Apache no puede leer los archivos. Comprueba que existe `index.php` o `index.html` y que los permisos permiten la lectura (`ls -l /var/www/your_domain`). - **`SQLSTATE[HY000] [1045] Access denied`**: usuario, contraseña o host incorrectos. Recuerda que `'app_user'@'localhost'` solo puede conectarse desde el propio servidor. - **Certbot falla con un error de validación**: el registro DNS no apunta al servidor o el puerto 80 está cerrado. Verifica `dig +short your_domain` y `sudo ufw status`. ## Conclusión Tienes un stack LAMP funcionando en Ubuntu 24.04: Apache sirve tu dominio por HTTPS con un certificado que se renueva solo, PHP 8.3 se conecta a MySQL con un usuario propio y la base de datos se copia cada noche. A partir de aquí puedes instalar una aplicación como WordPress en `/var/www/your_domain`, pasar de `mod_php` a PHP-FPM para ajustar mejor el consumo de memoria, o comparar este montaje con un stack LEMP basado en Nginx.