The LAMP stack (Linux, Apache, MySQL, PHP) is a collection of software used to serve dynamic web pages and PHP applications.
It consists of a Linux operating system, the Apache web server, a MySQL database for data storage, and PHP for handling dynamic content.
This guide will walk you through setting up a LAMP stack on a server running Ubuntu 22.04. With Ubuntu managing the Linux component, we’ll cover how to configure each of the remaining parts of the stack.
Prerequisites #
- A server with Ubuntu installed. I will use Ubuntu 22.04
- A user account with admin or sudo access
Step 1: Installing the Apache Web Server #
Apache is a popular, efficient web server that we’ll use to serve pages to our visitors. Begin by updating your server’s package index:
sudo dnf update -y

You might get an error relating to GPG keys when you try to run the command above. Fix it using the command below;
rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux
Then install apache:
sudo dnf install httpd -y

Check if Apache installed correctly by starting, enabling and checking the httpd service status
sudo systemctl enable httpd
sudo systemctl start httpd
sudo systemctl status httpd

Allowing Apache Through the Firewall #
If you’re using Firewalld, you’ll need to allow HTTP traffic through it.
Start the firewall
systemctl start firewalld
Then allow traffic through it
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

To verify that Apache is running, open your server’s public IP or domain in a web browser. If unsure about your public IP, run one of the following commands to see it.
ip addr show
hostname -I
In your browser, navigate to:
http://server_domain_or_ip_address
This should display the Almalinux default landing page.

Step 2: Installing MySQL #
With Apache installed, we’ll move on to installing MySQL, which will manage and store site data.
You can also use MariaDB. Please refer to these steps on how to install MariaDB database on Almalinux
For MySQL, run:
sudo dnf install mysql-server -y
Start and enable MySQL
systemctl start mysqld
systemctl enable mysqld

After installing MySQL, it is a good idea to run a security script included with it
sudo mysql_secure_installation
You’ll be prompted to configure the VALIDATE PASSWORD PLUGIN—type Y for yes or any other key to continue without enabling it.
If you select “yes,” you’ll be prompted to choose a level of password validation. I prefer that you choose level 1.
It is fine to select yes fort he rest of the prompts, but then you can also choose differently according to your preference.

Once done, check if you can log in to the MySQL console:
sudo mysql
This command connects to the MySQL server using the administrative database user root, indicated by sudo. The expected output is as follows:

You may then run the command below to exit the console;
exit

Ensure both Apache and MySQL are enabled to start on boot.
sudo systemctl enable httpd
sudo systemctl enable mysqld
Step 3: Installing PHP #
Next, install PHP to generate dynamic content. Apache uses PHP-FPM (FastCGI Process Manager) for this purpose. Install PHP and the PHP MySQL extension with:
sudo dnf install php php-mysqlnd php-fpm php-cli -y
Restart Apache to load PHP:
sudo systemctl restart httpd
Step 4: Configuring Apache to Use PHP #
In most cases, Apache is configured to use PHP automatically. However, if you need custom configuration, modify the /etc/httpd/conf.d/php.conf
file to ensure PHP scripts are parsed correctly.
Also, we’ll create a new directory for our website and set up a configuration file.
In the steps below, remember to replace your_domain with your actual domain or subdomain. I will use doll.tke.co.ke
- Create the web root directory:
sudo mkdir /var/www/doll.tke.co.ke
2. Assign ownership of the directory to the current user:
sudo chown -R $USER:$USER /var/www/doll.tke.co.ke
3. Open a new configuration file in the sites-available directory:
sudo vi /etc/httpd/conf.d/doll.tke.co.ke.conf
4. Add the following configuration:
<VirtualHost *:80>
ServerName doll.tke.co.ke
ServerAlias www.doll.tke.co.ke
DocumentRoot /var/www/doll.tke.co.ke
<Directory /var/www/doll.tke.co.ke>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
DirectoryIndex index.php index.html index.htm
ErrorLog /var/log/httpd/doll.tke.co.ke_error.log
CustomLog /var/log/httpd/doll.tke.co.ke_access.log combined
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
# Deny access to .htaccess files
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
</VirtualHost>

Below is what each of the directives do
- ServerName and ServerAlias: Define the domain names for this virtual host.
- DocumentRoot: Points to the directory where your website files are stored.
- Directory Directive: Sets permissions for the document root.
- DirectoryIndex: Specifies which files to serve when a directory is requested.
- ErrorLog and CustomLog: Directives to log errors and access requests.
- FilesMatch: Applies a handler for PHP files.
- Deny access to .htaccess files: Prevents access to
.ht
files for security.
5. Save and close the file (in vi, press Esc, type :wq
, and press Enter).
6. Test your configuration for syntax errors:
sudo apachectl configtest

7. Add a sample index.html file to verify that your new server block works:
vi /var/www/doll.tke.co.ke/index.html

8. Restart Apache to apply the changes:
systemctl restart httpd
9. Visit http://doll.tke.co.ke
in your browser to confirm.

Step 5: Testing PHP with Apache #
To test PHP, create a file called info.php in your document root:
vi /var/www/doll.tke.co.ke/info.php
Add the following code:
<?php
phpinfo();
?>
Access this page by navigating to:
http://doll.tke.co.ke/info.php

After confirming, delete the file to avoid exposing sensitive information:
sudo rm /var/www/doll.tke.co.ke/info.php
Step 6: Testing Database Connection from PHP #
Create a test database and user in MySQL:
Log in to MySQL:
sudo mysql
Create a new database:
- Replace test_db with your preferred database name
CREATE DATABASE test_db;

Add a new user:
- Replace test_user with your preferred user name
CREATE USER 'test_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';

Note:
When running the command you may get this error ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
In that case, just ensure that your password has a mixture of special characters, numbers, uppercase and lowercase characters, then re-run it.
Grant the user privileges on the new database:
GRANT ALL ON test_db.* TO 'test_user'@'%';

Exit MySQL:
exit
To confirm that the new user has the correct permissions, log into the MySQL console again using the custom user credentials.
Be sure to include the -p
flag in the command, as it will prompt for the password set when creating the “test_user” user.
mysql -u test_user -p
Enter your password and confirm to access test_DB.
You can then check the databases available;
SHOW DATABASES;

Let’s now create a test table named “tech_list.” Execute the following statement from the MySQL console:
CREATE TABLE test_db.tech_list (tech_id INT AUTO_INCREMENT,technology VARCHAR(255),PRIMARY KEY(tech_id));

You may now insert values into the table by running multiple inatances of the command below
INSERT INTO test_db.tech_list (technology) VALUES ("IOT");
INSERT INTO test_db.tech_list (technology) VALUES ("Cloud");
INSERT INTO test_db.tech_list (technology) VALUES ("DevOPs");
INSERT INTO test_db.tech_list (technology) VALUES ("ML");
INSERT INTO test_db.tech_list (technology) VALUES ("Networking");

You could check the entries using the command below;
SELECT * FROM test_db.tech_list;

You may exit the MySQL console using the exit command.
Test MySQL Connection #
To test, create a PHP script to connect to MySQL:
Open a file called testlist.php:
vi /var/www/doll.tke.co.ke/testlist.php
Add PHP code to connect and query. In the code below, remember to replace the dummy database details with your own.
<?php
$conn = new mysqli("localhost", "test_user", "password", "test_db");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT * FROM tech_list";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo $row["tech_id"] . ": Technology: " . $row["technology"] . "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>

Access this script:
http://doll.tke.co.ke/testlist.php

Author’s final word #
Congratulations! You’ve successfully set up a LAMP stack on Ubuntu 20.04, creating a powerful foundation to host PHP-based applications. This configuration, combining Apache and MySQL, is optimized for speed and security in dynamic web hosting environments.