How to Install Apache, MySQL, PHP (LAMP Stack) on Ubuntu 26.04

LAMP is a web application stack consisting of Linux, Apache, MySQL, and PHP. Apache serves as the HTTP web server, MySQL provides the relational database backend, and PHP processes server-side scripts to generate dynamic content. Together, these components form a widely used platform for hosting content management systems, e-commerce applications, and custom web services.
This article explains how to install the LAMP stack on an Ubuntu 26.04 server, configure Apache to process PHP requests through PHP-FPM, secure the server with firewall rules and a Let's Encrypt SSL certificate, and test the stack with a sample PHP application that queries a MySQL database.
Prerequisites
Before you begin, you need to:
- Have access to an Ubuntu 26.04 server instance as a non-root user with sudo privileges.
- Have a domain A record pointing to the server's public IP address. For example,
app.example.com.
Install Apache
The default Ubuntu 26.04 APT repositories include the Apache web server package. The following steps install Apache and verify that the service is running.
Update the APT package index.
console$ sudo apt update
Install Apache.
console$ sudo apt install apache2 -y
Enable Apache to start automatically at boot time.
console$ sudo systemctl enable apache2
Start the Apache service.
console$ sudo systemctl start apache2
Verify that Apache is active and running.
console$ sudo systemctl status apache2
The output should display
active (running), confirming that the Apache web server is operational.
Install MySQL
MySQL is included in the default Ubuntu 26.04 repositories. The following steps install the database server, enable the service, and run the secure installation script to harden the default configuration.
Install the MySQL server package.
console$ sudo apt install mysql-server -y
Enable MySQL to start automatically at boot time.
console$ sudo systemctl enable mysql
Start the MySQL service.
console$ sudo systemctl start mysql
Verify that MySQL is active and running.
console$ sudo systemctl status mysql
The output should display
active (running), confirming that the MySQL server is operational.Run the MySQL secure installation script to remove insecure defaults.
console$ sudo mysql_secure_installation
Respond to each prompt as described below:
- VALIDATE PASSWORD COMPONENT: Enter Y and press Enter to activate password validation.
- Password Validation Policy: Enter 2 to require strong passwords.
- Remove anonymous users?: Enter Y to delete anonymous database accounts.
- Disallow root login remotely?: Enter Y to restrict root access to the local server.
- Remove test database and access to it?: Enter Y to drop the default test database.
- Reload privilege tables now?: Enter Y to refresh the privilege tables and apply all changes.
Open the MySQL server configuration file.
console$ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Add the following directive under the
[mysqld]section to activate themysql_native_passwordauthentication plugin.inimysql_native_password=ON
Save and close the file.
Restart MySQL to load the updated configuration.
console$ sudo systemctl restart mysql
Access the MySQL console as the
rootsystem user.console$ sudo mysql
Set a strong password for the root account. Replace
your_strong_passwordwith a secure password that meets your validation policy.sqlmysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password';
Reload the privilege tables.
sqlmysql> FLUSH PRIVILEGES;
Exit the MySQL console.
sqlmysql> EXIT;
Install PHP
PHP-FPM (FastCGI Process Manager) enables Apache to process PHP scripts by forwarding requests through a Unix socket. The following steps install PHP, PHP-FPM, and essential modules for the LAMP stack.
Install PHP, PHP-FPM, and common extensions.
console$ sudo apt install php php-fpm php-mysql php-cli libapache2-mod-php -y
The command installs the following packages:
php-fpm: Manages PHP worker processes for handling web server requests.php-mysql: Enables PHP to connect to MySQL databases.php-opcache: Caches precompiled PHP scripts in memory for faster execution.php-cli: Provides the PHP command-line interpreter.libapache2-mod-php: Enables Apache to process PHP scripts directly.
Confirm the installed PHP version.
console$ php -v
Your output should be similar to the one below:
PHP 8.5.2 (cli) (built: Jan 21 2026 17:35:28) (NTS) Copyright (c) The PHP Group Built by Ubuntu Zend Engine v4.5.2, Copyright (c) Zend Technologies with Zend OPcache v8.5.2, Copyright (c), by Zend TechnologiesEnable PHP-FPM to start automatically at boot time.
console$ sudo systemctl enable php8.5-fpm
Start the PHP-FPM service.
console$ sudo systemctl start php8.5-fpm
Verify that PHP-FPM is active and running.
console$ sudo systemctl status php8.5-fpm
The output should display
active (running), confirming that PHP-FPM is operational.
Configure Apache with PHP-FPM
Apache requires additional modules to forward PHP requests to PHP-FPM. The following steps enable the required modules and activate the PHP-FPM configuration.
Enable the Apache proxy and environment modules.
console$ sudo a2enmod proxy_fcgi setenvif
Enable the PHP-FPM configuration for Apache.
console$ sudo a2enconf php8.5-fpm
Restart Apache to apply the module changes.
console$ sudo systemctl restart apache2
Set Up Firewall Rules
Uncomplicated Firewall (UFW) is active by default on Ubuntu 26.04. The following steps open ports for HTTP and HTTPS traffic.
Allow HTTP traffic on port
80.console$ sudo ufw allow 80/tcp
Allow HTTPS traffic on port
443.console$ sudo ufw allow 443/tcp
Configure Apache Virtual Host
Apache uses virtual host configurations to serve content based on the requested domain name. The following steps remove the default configuration, create a virtual host for your domain, and connect it to PHP-FPM.
Unlink the default Apache virtual host configuration.
console$ sudo a2dissite 000-default.conf
Create a new virtual host configuration file. Replace
app.example.comwith your actual domain.console$ sudo nano /etc/apache2/sites-available/app.example.com.conf
Add the following configuration to the file. Replace
app.example.comwith your actual domain.ini<VirtualHost *:80> ServerAdmin webmaster@app.example.com ServerName app.example.com DocumentRoot /var/www/app.example.com <Directory /var/www/app.example.com> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> <FilesMatch \.php$> SetHandler "proxy:unix:/var/run/php/php8.5-fpm.sock|fcgi://localhost/" </FilesMatch> ErrorLog ${APACHE_LOG_DIR}/app.example.com_error.log CustomLog ${APACHE_LOG_DIR}/app.example.com_access.log combined </VirtualHost>
Save and close the file.
Within the configuration:
ServerName: Defines the domain that triggers this virtual host.DocumentRoot: Sets the directory from which Apache serves files.<FilesMatch \.php$>: Forwards all PHP file requests to the PHP-FPM socket for processing.ErrorLogandCustomLog: Store virtual host-specific error and access logs.
Create the web root directory for the virtual host.
console$ sudo mkdir -p /var/www/app.example.com
Enable the new virtual host configuration.
console$ sudo a2ensite app.example.com.conf
Test the Apache configuration for syntax errors.
console$ sudo apache2ctl configtest
The output should display
Syntax OK.Restart Apache to activate the virtual host.
console$ sudo systemctl restart apache2
Secure the Server with SSL
SSL certificates encrypt communication between the client browser and the Apache web server over HTTPS. The following steps install Certbot and generate a trusted Let's Encrypt SSL certificate for your domain.
Install the Certbot Let's Encrypt client and the Apache plugin.
console$ sudo apt install certbot python3-certbot-apache -y
Generate an SSL certificate for your domain. Replace
app.example.comwith your actual domain.console$ sudo certbot --apache -d app.example.com --agree-tos
Follow the on-screen prompts to complete the certificate generation. Certbot automatically updates the Apache virtual host configuration to enable HTTPS.
Verify that the automatic renewal process is configured correctly.
console$ sudo certbot renew --dry-run
Test the LAMP Stack
A working LAMP stack allows PHP to query data from MySQL and return dynamic content through Apache. The following steps create a sample database, insert a test record, and build a PHP application that retrieves and displays the data in a web browser.
Log in to the MySQL console as the
rootuser.console$ mysql -u root -p
Enter the root password you configured earlier.
Create a new database named
example_db.sqlmysql> CREATE DATABASE example_db;
Create a database user named
example_userwith a strong password. Replacestrong_passwordwith your desired password.sqlmysql> CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'strong_password';
Grant the user full privileges on the
example_dbdatabase.sqlmysql> GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost';
Reload the privilege tables.
sqlmysql> FLUSH PRIVILEGES;
Switch to the
example_dbdatabase.sqlmysql> USE example_db;
Create a table named
messageswith an auto-incrementing ID and a text column.sqlmysql> CREATE TABLE messages ( id INT AUTO_INCREMENT PRIMARY KEY, content VARCHAR(255) NOT NULL );
Insert a sample record into the table.
sqlmysql> INSERT INTO messages (content) VALUES ('Hello World from LAMP Stack');
Verify that the record exists.
sqlmysql> SELECT * FROM messages;
Your output should be similar to the one below:
+----+-----------------------------+ | id | content | +----+-----------------------------+ | 1 | Hello World from LAMP Stack | +----+-----------------------------+ 1 row in set (0.00 sec)Exit the MySQL console.
sqlmysql> EXIT;
Create a PHP test file in the web root directory.
console$ sudo nano /var/www/app.example.com/test.php
Add the following PHP code to the file. Replace
strong_passwordwith theexample_userpassword you set earlier.php<?php $servername = "localhost"; $username = "example_user"; $password = "strong_password"; $dbname = "example_db"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Database connection failed: " . $conn->connect_error); } $sql = "SELECT content FROM messages"; $result = $conn->query($sql); if ($result->num_rows > 0) { $row = $result->fetch_assoc(); echo "<h1>" . htmlspecialchars($row["content"]) . "</h1>"; } else { echo "<h1>No records found.</h1>"; } $conn->close(); ?>
Save and close the file.
This script connects to the
example_dbdatabase, queries themessagestable, and displays the result as an HTML heading.Access the test page in a web browser. Replace
app.example.comwith your actual domain.https://app.example.com/test.phpThe browser displays the message Hello World from LAMP Stack, confirming that Apache, MySQL, and PHP are working together.
Conclusion
You have deployed and secured the LAMP stack on an Ubuntu 26.04 server. Apache serves web requests, PHP-FPM processes dynamic content, and MySQL manages the application data. This stack supports multiple virtual hosts and integrates with frameworks such as Laravel and WordPress. For more configuration options, refer to the following resources: