Setting up a LAMP Stack on Ubuntu 20.04 (And Raspberry Pi)

LAMP Stack on Ubuntu

This tutorial covers setting up a full LAMP (Linux, Apache, MySQL, PHP) web stack, including HTTP server, MySQL database, and PHP for app logic.

This is commonly called a LAMP server – Linux, Apache, MySQL, PHP.

Linux rules the web server world – the operating system powers the vast majority of web servers worldwide.

Apache is a popular web server – the software with which web browsers connect to receive content.

MySQL is a popular database server – it stores information in rows and columns inside tables. There is also a drop-in replacement called MariaDB, which offers compatible functionality.

Finally, PHP is a programming language commonly used in web development. It lets you write application logic, which then generates web pages.

Apache runs on Linux, serving content generated by PHP, which stores user data in MySQL databases.

Here’s how to set it all up and get it working together.

Installing Ubuntu Linux

First up, the Linux bit. You’ll need to install Ubuntu Linux for this tutorial. 20.04 is the latest release with Long Term Support recommended for servers. Ubuntu was chosen as it is popular, stable, and its software repositories already contain everything needed.

You can download the Server or Desktop variations – either will work for setting up a LAMP server, which you choose depends on whether you plan on using it for local development on a desktop computer with a GUI and development tools or whether you’re deploying a server which will live in the cupboard, or on a cloud host.

Here’s how to Install Ubuntu Desktop

And Here’s How To Install Ubuntu MATE on a Raspberry Pi

If you’re deploying Ubuntu Server to a cloud host, the OS install is taken care of for you.

Once you’ve got Ubuntu installed, make sure it’s up-to-date by running the following commands in succession:

sudo apt update
sudo apt upgrade

You may be more familiar with using the apt-get command – see this article on the difference to the apt command.

Setting a Static IP

If you plan on running your LAMP server on your local network, it might be useful to set a static IP address so you always know where to find it – click here to check out how.

Setting up Remote Access with SSH

Whether you’re developing on a local machine with a desktop or on a headless server in the cloud, remote access will come in useful. Most cloud-hosted servers will already be set up with SSH and a user account. If not, here’s how to install it:

sudo apt install openssh-server

See this article for more on connecting to your Raspberry Pi or Linux computer via SSH, including finding the IP address.

Setting up the Firewall with UFW

UFW (Uncomplicated Firewall) is a simple firewall that will help keep your server safe. Leaving a server wide-open to internet traffic is a certified bad idea. Even if you are running a server on your home network, it’s a good idea to have a firewall set up so you’re familiar with the process.

Install UFW:

sudo apt install ufw

Allow SSH through the firewall:

sudo ufw allow OpenSSH

This will allow both incoming and outgoing traffic to SSH from the server while the firewall is enabled. Enable the firewall by running:

sudo ufw enable

sudo ufw enable

Don’t enable the firewall until you’ve allowed SSH through! Otherwise, you might block your own remote session and be forever locked out!

Preventing Brute-Force Attacks with Fail2ban

Fail2ban blocks all internet traffic from IP addresses, which repeatedly fail to log in to services running on your server (Like SSH, Apache, and Mysql). It’s a good start to securing your internet-facing Linux computers but is not a stop-all – it just helps prevent automated attacks.

Once installed, it’ll do its thing without any further configuration:

sudo apt install fail2ban

Installing the Apache Web Server

To install the Apache Web Server, run:

sudo apt install apache2

Apache will be installed and set to automatically start on boot.

Allow Apache Through the Firewall

Apache is a web server, so it will also need to be allowed through the firewall. You can list the available firewall profiles by running:

sudo ufw app list

sudo ufw app listIn the screenshot, you can see the programs that are registered for the firewall – including SSH, which we allowed previously. Allow incoming traffic only for Apache by running:

sudo ufw allow in "Apache Full"

Check the status to make sure Apache is allowed by running:

sudo ufw status

sudo ufw status

Checking Apache is Running

If you’re setting up LAMP on a desktop computer with a web browser, navigate to

In your browser – you should see the below page confirming Apache is up and running:

Checking Apache is Running is the address for localhost – it’s the address that a computer uses to access itself on a network.

If you are on a different computer, you can connect using your LAMP server’s IP address – there’s a link further up in this article about setting a static IP address.

Apache’s Web Files

By default, apache stores the HTML (and soon PHP) files that run your website at:


Installing the MySQL Database Server

Next up, install the MySQL server:

sudo apt install mysql-server

Like Apache, it will be set to start automatically on boot.

Secure MySQL

MySQL should be secured before you continue. There’s a built-in tool that will do all of this for you, which can be run by entering:

sudo mysql_secure_installation

You’ll be asked some questions about how you want MySQL secured:

Would you like to setup VALIDATE PASSWORD component?

Yes – enforcing some password complexity will make the system more secure.

You’ll then be prompted to set password complexity and enter a new password for the MySQL root (administrator) user. The MySQL root user is completely separate from the Linux root user.

Remove anonymous users?

Also, answer yes – the default anonymous users do not have passwords, which is insecure.

Disallow root login remotely?

Again, answer yes. There is no need for remote users to perform administrative tasks on MySQL.

We will also not be allowing MySQL through the firewall. It will be accessible from within the server but not externally. There’s no need for it to be.

Remove test database and access to it?


Reload privilege table now?

Answer yes to complete securing the server and reload the remaining users’ privileges.

Done!sudo mysql_secure_installation

Check MySQL is Running

To confirm that MySQL is running run:

sudo mysql

When the MySQL command is run as root (or using sudo), it automatically tries to connect to the local server as the root user.

If this succeeds, run the following to list the databases present to confirm everything works correctly:





To exit the MySQL command line.

Installing PHP

Install PHP with the following familiar-looking command:

sudo apt install php

Check PHP is Installed

To check PHP has installed successfully, run:

php -v

php -v

Install PHP Modules

PHP needs to be able to talk with Apache and Mysql. For this to happen, Apache needs its PHP module installed, and PHP needs its MySQL module installed:

sudo apt install libapache2-mod-php php-mysql

These Apache and PHP modules will be enabled automatically once installed.

Checking phpinfo()

phpinfo() is a PHP function that outputs all of your PHP environment details, including configuration and which modules are enabled. It’s a good way to check that Apache and PHP are configured.

Create a new PHP file to run this in the Apache HTML directory, which holds the files your web server serves:

sudo nano /var/www/html/info.php

This will open the nano text editor with an empty file called info.php. Enter the code:



And press CTRL + X to save and quit and Y to confirm.

If you navigate to /info.php on your new LAMP server, you should see the following:info.php

Testing it All Together

Everything that makes a LAMP server a LAMP server is now installed. Congratulations!

To confirm that everything is working as it should be, ready to start hosting existing apps or developing new ones, here are some steps for building a test PHP script that reads from a MySQL database.

Creating a Database and User

Open the MySQL command line as the root user:

sudo mysql

Create a database called db_example:


Next, a user is created with the username usr_example, which will have access from localhost using the supplied password:

CREATE USER 'usr_example'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MyPassword1!';

With the database and user-created, grant the user ALL privileges for that database:

GRANT ALL ON db_example TO 'usr_example'@'localhost';

You can confirm that the database was created by running:



Create a Table and Records

The database and user with access rights to the database are ready to go – now we need to create a table with some data in it to test with.

Switch to the db_example database by running:

USE db_example;

You must switch to the database before creating tables – otherwise, MySQL won’t know which database to put the table in.

Create a table called fruit – it will be created in db_example:


The line above tells MySQL to create a fruit table with two columns – id and name.

id is an INTeger column that will auto-increment – each record will have a unique id number, which is an increment of 1 over the previous.

name is a VARCHAR column, which is a short string with a maximum length given as 255 characters.

The final part of the statement tells MySQL that the primary key will be the id column. The primary key is the column used to uniquely identify each record.

You’ve probably noticed that I capitalize all MySQL commands in the above statements – this is optional, but it is a convention as it makes it easy to see what words are MySQL statements and what words refer to table names, etc.

Now, insert some test data. A list of fruit! Only the name needs to be supplied – the id column is calculated and entered automatically:

INSERT INTO fruit(name) VALUES ('apples'), ('bananas'), ('pears'), ('grapes');

Whenever MySQL does something right, you’ll get a response with:

Query OK

And whenever something goes wrong, you’ll get an error.

Check the records were entered correctly into the fruit table by running:

SELECT * from fruit;

SELECT * from fruit;And exit MySQL:


PHP Script to Read Database, Table, and Records

Use the nano text editor to create a new PHP file to list the contents of the fruit table we just created in the db_example database:

sudo nano /var/www/html/db_test.php

And enter the following code:


ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);

$db_user = "usr_example";
$db_password = "MyPassword1!";
$db_host = "localhost";
$db_database = "db_example";
$db_table =  "fruit";

$connection = new mysqli($db_host, $db_user, $db_password, $db_database);

if ($connection->connect_errno) {
    printf("Connection failed: %s\n", $connection->connect_error);

$test_query = "SELECT * FROM $db_database.$db_table;";
$result = $connection->query($test_query);

while( $row = $result->fetch_array() )
    echo $row["name"];
    echo "<br />";



Save it by pressing CTRL + X and Y to confirm, then point your web browser to /db_test.php on your new LAMP server:

lamp php test 1

Looks good! All of the components of your LAMP server are working together!

Real-World Usage for your LAMP Server.

Linux, Apache, MySQL, and PHP are all versatile tools. You can build pretty much whatever you want on this platform. There are hordes of helpers, libraries, tutorials, articles, and helpful people on the Internet ready to help you start building your next project.

PHP Frameworks are useful for providing the foundation of a project if you want a leg up rather than starting from scratch.

WordPress provides a blogging platform that can be extended with thousands of themes and packages that add functionality from online stores to social network functionality. It works out of the box and can be extended with your own code if you’re feeling adventurous.

Laravel provides a bare framework for building literally anything – APIs, chat apps, online calendars, doorbells, whatever you can think of.

Click here to check out our other PHP articles.

If you’re looking for real-world code examples, subscribe to LinuxScrew on Twitter – I’ll be posting various projects, some of which will include PHP code.


Brad Morton

I'm Brad, and I'm nearing 20 years of experience with Linux. I've worked in just about every IT role there is before taking the leap into software development. Currently, I'm building desktop and web-based solutions with NodeJS and PHP hosted on Linux infrastructure. Visit my blog or find me on Twitter to see what I'm up to.

Leave a Reply

Your email address will not be published. Required fields are marked *