For one of my projects I am developing now (an online POS) I have to get some proper hosting for the application to be running online. In order to do this i have decided to host this on a virtual private server, meaning that i got all admin privileges that i need.

LAMP is an acronym which represents a Linux operating system with an installed Apache web server. When making use of a LAMP stack you install open-source software on the server in order to host dynamic websites or web applications. The data for the application is then stored in a MySQL database and the pages are processed by PHP. Using a LAMP stack for my project is perfect since it’s built on PHP with Laravel.

In this guide, i will be installing a LAMP stack on a virtual private server with an Ubuntu 18.04 operating system.


In order to complete the steps in this article, you would have to install Ubuntu 18.04 on your own server wit a non root (sudo) enabled user as well as a basic firewall. I will not be showing how you install Ubuntu in this article on, how you configure it.

Step 1 — Install Apache and Update our Firewall on The Server

Apache is one of the most popular web servers in the world and it is open-source. Because of its popularity and it’s open-source a lot of people have helped in the making and further development of Apache. This has resulted in good documentation and great compatibility with linux operating systems. For my project it’s a great choice for hosting.

First thing we have to do is installing Apache using the built in package manager in Ubuntu “apt”.

sudo apt update
sudo apt install apache2

As you might have noticed these two commands are executed as sudo meaning that we got root privileges. When executing a sudo command, you would have to enter your password, to verify that you really wan’t to do this operation.

Okay, so now you have entered the password and the package manager will execute with root privileges. This will now tell you what packages it wil pull and install and how much space it will occupy. You only have to enter Y and hit the ENTER button to continue the installation. The installation will then proceed as planned.

Adjusting the Firewall to Allow Web Traffic Through

Allright, next thing we have to do is allowing requests on HTTP and HTTPS for our web application. Assuming that you have enabled the UFW firewall, this will be easy to configure. You can easily check that UFW has an application profile for Apache by entering the following command:

sudo ufw app list
OutputAvailable applications:
  Apache Full
  Apache Secure

Taking a quick look at the Apache Full profile, should show us that traffic at port 80 (HTTP) and 443 (HTTPS) is enabled.

sudo ufw app info "Apache Full"
OutputProfile: Apache Full
Title: Web Server (HTTP,HTTPS)
Description: Apache v2 is the next generation of the omnipresent Apache web server.


We are going to allow traffic to pass through on these ports, which means visitors can connect on HTTP and HTTPS.

sudo ufw allow in "Apache Full"

Lets check if this is working as we wan’t it to. The way to do this is by entering the IP address of your server into a browser. It has to be your servers public address and not the local one. If you can’t find your public IP address at your hosting provider, you can enter this command:

dig +short

This will tell you the public IP of the server, which you then can enter into your browser like i have made an example of below:


This should return a default Ubuntu 18.04 Apache web page in your browser. The page is only showing up for testing purpose. It would look like the the page I have inserted an image of below:

Apache2 Ubuntu Default Page

If you see this page, then your web server is now correctly installed and accessible through your firewall. Congrats! ????

Step 2 — Installing MySQL

MySQL is a database management system. What is does is organizing and providing access to databases, where all the information on my web application will be stored. Let’s go ahead and install MySQL, now that we got a running web server.

One more time, we have to use the package manager to install the software:

sudo apt install mysql-server

Note: You don’t have to run the update command prior to the install command. The reason is that we recently ran that command and the package index on our server should be 100% up-to-date.

Again Ubuntu will present you with a list of packages that would have to be installed. You would also get information about how much disk space would be needed for the installation. You just have to press Y to continue the installation.

MySQL got a pre-installed security script that we can execute. This will remove some risks and lock down access to the database system. You only have to enter the following command to get the script running:

sudo mysql_secure_installation

You will be asked if you want to configure the VALIDATE PASSWORD PLUGIN.

Note: If enabled, passwords which don’t match the specified criteria will be rejected by MySQL with an error. This will cause issues if you use a weak password in conjunction with software which automatically configures MySQL user credentials, such as the Ubuntu packages for phpMyAdmin. I always recommend to use strong passwords!

Answer Y for yes, or simply anything else for continuing without enabling the feature.

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No:

Answering yes will take you to the configuration for the MySQL passwords standard. If you enter 2 as the strongest level, you will be receiving errors when trying to enter a password which does not contain the following:

  • Numbers.
  • Uppercase letters.
  • Lowercase letters.
  • Special characters
  • The password is based on common dictionary words.
There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 1

Regardless of whether you chose to set up the VALIDATE PASSWORD PLUGIN, your server will ask you to select and confirm a password for the MySQL root user.

The root user is an administrative account in MySQL that has increased privileges. Think of it as being similar to the root account for the server itself (although the one you are configuring now is a MySQL-specific account). Again I always recommend choosing a strong and unique password.

If you enabled the password validation, you would be shown the strength of the root password. If you are unhappy with the current password, you are free to enter N for no at the prompt. Then you can change it.

Using existing password for root.

Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n

The rest of the questions in the prompts can be answered with a Y and ENTER each time. This will:

  • Remove anonymous users
  • Remove the test database
  • Disable remote root logins
  • Load new rules so MySQL immediately will make use of the changes you made in the configuration.

When connecting to MySQL as root, you will by default not be prompted for a password. You you would like to enter a password each time, you have to switch the authentication method from auth_socket to mysql_native_password. In order to do this, you have to open the MySQL terminal from your server terminal like so:

sudo mysql

Now we have to check what the current authentication method is. Do this by entering the following command in the terminal:

SELECT user,authentication_string,plugin,host FROM mysql.user;
| user             | authentication_string                     | plugin                | host      |
| root             |                                           | auth_socket           | localhost |
| mysql.session    | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| debian-sys-maint | *CC744277A401A7D25BE1CA89AFF17BF607F876FF | mysql_native_password | localhost |
4 rows in set (0.00 sec)

In the output, you can see that the root user does authenticate using the auth_socket plugin. If you wish to authenticate using a password, you just have to enter the following ALTER USER command. Again (can’t say it enough times) remember that it should be a strong password.

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password_here';

When you are done hit ENTER and enter the following command to flush the privileges. This will reload the server grant tables and then use the authentication settings you just made.


Again, we can check the authentication for each user in the database system. The reason doing this is that we would like to confirm that the root user no longer authenticate using the auth_socket plugin:

SELECT user,authentication_string,plugin,host FROM mysql.user;
| user             | authentication_string                     | plugin                | host      |
| root             | *3636DACC8616D997782ADD0839F92C1571D6D78F | mysql_native_password | localhost |
| mysql.session    | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| debian-sys-maint | *CC744277A401A7D25BE1CA89AFF17BF607F876FF | mysql_native_password | localhost |
4 rows in set (0.00 sec)

As you can see in my example above, the root MySQL user not authenticates using a native password. Okay, the MySQL system is now configured and ready to use! Let’s exit out of that:


Now we got a running web server and a database system. Let’s move on and install PHP, which is the final component before we can say the server is a LAMP server.

Step 3 — Installing PHP on The Server

In order to handle, process and display dynamic content on our website, we need PHP. PHP is capable of running scripts, connecting to our MySQL database for storing / retrieving data and handing over rendered HTML webpages that our server can display to the visitor.

Again we will make use of apt (the package manager) to install PHP on the server. At the same time we will be installing some helper packages for PHP. The helper packages allows PHP code to run under our Apache server and talking to the MySQL database for handling data.

sudo apt install php libapache2-mod-php php-mysql

The command above will install PHP on your server and we can test that it’s working a moment.

By default Apache will serve html files first. Because we most of the time will be serving PHP pages, we would have to change the order of file types, that Apache looks in our directory for.

We would like to tell our web server that it should serve PHP files before serving any other files, this will make a index.php file load before an index.html file.

In order to configure Apache to do this, we need to open and modify dir.conf in a text editor in Ubuntu. I prefer to use nano, but you can use the one you like the most.

sudo nano /etc/apache2/mods-enabled/dir.conf

The config should look like what I have entered below in the example:

<IfModule mod_dir.c>  
   DirectoryIndex index.html index.cgi index.php index.xhtml index.htm 

Okay, so we have to change the order. Just move the PHP filetype to the first position in the config file.

<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.xhtml index.htm

When you are done editing, you just have to save and close the file. This can be done by hitting CTRL + X. Confirm that you wan’t to save the file by typing Y and hit ENTER.

For the changes to take effect, we have to restart our Apache web server. You can restart Apache by entering the following command:

sudo systemctl restart apache2

If you wan’t to, you can also check the status of the service by using systemctl:

sudo systemctl status apache2
Sample Output● apache2.service - LSB: Apache2 web server
   Loaded: loaded (/etc/init.d/apache2; bad; vendor preset: enabled)
  Drop-In: /lib/systemd/system/apache2.service.d
   Active: active (running) since Tue 2018-04-23 14:28:43 EDT; 45s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 13581 ExecStop=/etc/init.d/apache2 stop (code=exited, status=0/SUCCESS)
  Process: 13605 ExecStart=/etc/init.d/apache2 start (code=exited, status=0/SUCCESS)
    Tasks: 6 (limit: 512)
   CGroup: /system.slice/apache2.service
           ├─13623 /usr/sbin/apache2 -k start
           ├─13626 /usr/sbin/apache2 -k start
           ├─13627 /usr/sbin/apache2 -k start
           ├─13628 /usr/sbin/apache2 -k start
           ├─13629 /usr/sbin/apache2 -k start
           └─13630 /usr/sbin/apache2 -k start

Hit Q to exit the status output again.

If your application require specific functionality of PHP, you are free to install som additional modules in your server. If you would like to see a list with all options (modules). Just enter the following command:

apt search php- | less

You can use the UP and DOWN arrow keys on your keyboard to scroll and Q to quit.

All these modules and libraries are optional. You don’t have to install them, only if you need them. At the same time, you will get a short description of each module or library.

bandwidthd-pgsql/bionic 2.0.1+cvs20090917-10ubuntu1 amd64
  Tracks usage of TCP/IP and builds html files with graphs

bluefish/bionic 2.2.10-1 amd64
  advanced Gtk+ text editor for web and software development

cacti/bionic 1.1.38+ds1-1 all
  web interface for graphing of monitoring systems

ganglia-webfrontend/bionic 3.6.1-3 all
  cluster monitoring toolkit - web front-end

golang-github-unknwon-cae-dev/bionic 0.0~git20160715.0.c6aac99-4 all
  PHP-like Compression and Archive Extensions in Go

haserl/bionic 0.9.35-2 amd64
  CGI scripting program for embedded environments

kdevelop-php-docs/bionic 5.2.1-1ubuntu2 all
  transitional package for kdevelop-php

kdevelop-php-docs-l10n/bionic 5.2.1-1ubuntu2 all
  transitional package for kdevelop-php-l10n

If you are curious about a specific module, you can either search the internet for more information about the module. You can also use a built in function, that will return a long description of the package.

This can be achieved by entering the following command in your terminal:

apt show package_name

You will get a lot of output, and you will notice that there is a field called “Description”. This will give you a longer explanation of what functionality is included in the module.

For example, to find out what the php-cli module does, you could type this:

apt show php-cli

Along with a large amount of other information, you’ll find something that looks like this:

Description: command-line interpreter for the PHP scripting language (default)
 This package provides the /usr/bin/php command interpreter, useful for
 testing PHP scripts from a shell or performing general shell scripting tasks.
 PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used
 open source general-purpose scripting language that is especially suited
 for web development and can be embedded into HTML.
 This package is a dependency package, which depends on Ubuntu's default
 PHP version (currently 7.2).

When you done some research and finds out that you need the specific functionality, you would have to install that specific package. Again you can use te built in package manager.

If you decided that php-cli is a module that you need, you just enter:

sudo apt install php-cli

Well, now we got a LAMP stack installed and configured on our server. Before you deploy an application onto the server I would recommend you to test you PHP configuration. This is a good way to figure out, if you got any issues that should be solved before the actual app.

Step 4 — Testing PHP Processing on our Web Server

Luckily for us the developers of PHP made it easy to test the functionality. Apache will automatically find a file called info.php (created by us) placed the correct place.

In order for Apache to find the file, we have to place it in our web root folder. When using Ubuntu 18.04, this directory is located at /var/www/html/. We will be creating a file in that directory and enter the needed code, for it to show the PHP configuration.

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

This will open a blank file. Add the following code to it. This is valid PHP code, returning information about the configuration.


When you are done, save and close the file. CTRL + X -> Y -> ENTER. You know the drill.

Now we a ready to test our web server. The test will tell us if our server can display content generated by PHP. The only thing you have to do is enter the following in your browser, where you specify your public ip instead of “your_server_ip”.

Then go visit this address in your browser:


The page that should be presented for you should look something like this:

PHP info

As you might have noticed, this page provides you with basic information about your server. It is very useful, if you have to debug the application and to ensure that your settings are applied correctly on the server.

If you get a page like the one i showed above in the image, you know that PHP is working correctly.

Due to all the information in this file, you might wan’t to remove it again. You can simply enter this command in your terminal, which will remove it for good.

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

You can always recreate the info page if you need to access the information again for debugging or when installing new packages.

Final words

Now we got a LAMP stack installed ready to server our web application. In other words – we have installed and configured a platform that will allow us to install and run most kinds of websites and web applications (written in PHP) on our server.

No one likes an unsecure website. Therefore i recommend you to secure the connections between your server and your visitors. This can be done by using Let’s Encrypt – a free and easy way to secure a website with a TLS / SSL certificate encrypting data sent between the visitor and the server.

Leave a Reply