How To Install LAMP Stack On Ubuntu 16.04

In this tutorial, we are going to learn how to install LAMP stack on Ubuntu 16.04 server. If we explain LAMP, that would be like Linux, Apache, MySQL, and PHP. Let start with following steps.

Four separate pieces of software that happen to work well together. Linux underneath, Apache answering HTTP, MySQL holding the data, PHP generating the pages. Nothing about the combination is special beyond the fact that it has been used together for so long that almost every problem you can hit has already been written up somewhere.

The install order matters slightly. Apache first so there is something serving, MySQL next, PHP last, because the PHP packages want Apache already present in order to wire the module into it.

Install Apache Web

To install Apache, put the below command in terminal.

sudo apt-get install apache2

Now start the service.

sudo systemctl enable apache2
sudo systemctl start apache2
sudo systemctl status apache2

Three commands doing three different things, and the distinction catches people out. enable sets it to come up at boot. start runs it now. status tells you whether that worked. Enable without start means nothing is running until you reboot, and start without enable means it disappears the next time the server restarts.

Go to browser and navigate to localhost or server-ip-address.

If nothing loads and the service reports active, the firewall is the usual reason. Apache is listening, the packets are being dropped before they reach it.

Apache default welcome page confirming the web server is running on Ubuntu 16.04
Apache Web Page

Install MySQL

MySQL is an open source relational database management system. Data lives in tables, tables relate to one another, and you query the whole thing with SQL. It is the piece of the stack that actually remembers anything, and the piece worth spending the most time securing.

sudo apt-get install mysql-server mysql-client

Enter the root password twice in the prompt during installation. Start the MySQL service after successful installation.

Worth saying plainly that this root account has nothing to do with the Linux root account. Different system, different password, and the two are not connected in any way.

sudo systemctl status mysql

Sample Output:

$ sudo systemctl status mysql
[sudo] password for asif:
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: en
   Active: active (running) since Sun 2016-09-25 07:40:44 PDT; 36min ago
  Process: 944 ExecStartPost=/usr/share/mysql/mysql-systemd-start post (code=exi
  Process: 920 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exite
 Main PID: 943 (mysqld)
    Tasks: 28 (limit: 512)
   CGroup: /system.slice/mysql.service
           └─943 /usr/sbin/mysqld

Sep 25 07:40:30 ubuntu systemd[1]: Starting MySQL Community Server...
Sep 25 07:40:44 ubuntu systemd[1]: Started MySQL Community Server.

Two things to read there. Active: running is the obvious one. Loaded ending in enabled is the one people miss, and it is what tells you the service will come back after a reboot.

After that, set database administrative “root” user password using below command with the default settings.

mysql_secure_installation

Do not skip this. A default MySQL install carries an anonymous account that can connect without credentials, a sample test database anyone can reach, and permission for root to log in from other machines. The script walks through removing all three and takes about two minutes. Answer yes to everything it offers.

Install PHP7

PHP is an interpreted scripting language, and on Linux web servers it is the thing turning a request into a page. The name started out meaning Personal Home Page Tools and now stands for PHP: Hypertext Preprocessor, which is the sort of recursive joke programmers find funnier than everyone else does.

Install PHP7 with below command:

sudo apt-get install php7.0-mysql php7.0-curl php7.0-json php7.0-cgi  php7.0 libapache2-mod-php7.0

PHP arrives in pieces rather than as one package, which is why that line is so long. php7.0 is the language itself. libapache2-mod-php7.0 is what plugs it into Apache, and without it Apache serves the raw source of your scripts instead of running them. php7.0-mysql is the database driver, and its absence is behind a great many connection errors that look like database problems and are not.

Check your PHP version in terminal.

$ php -v
PHP 7.0.8-0ubuntu0.16.04.2 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.8-0ubuntu0.16.04.2, Copyright (c) 1999-2016, by Zend Technologies

Note the cli in that output. This is the command-line PHP, which can be a different version and a different configuration from the one Apache uses. When behaviour differs between a script run from the terminal and the same script over HTTP, that gap is very often the reason.

Now create a sample “test.php” file in Apache document root folder.

sudo vim /var/www/html/test.php

Add the following lines:

<?php
phpinfo();
?>

Restart apache2 service.

sudo systemctl restart apache2

Navigate to localhost/test.php in the browser. Now you can see the PHP details such as version, build date and other modules.

phpinfo output page confirming PHP 7 is installed and working
PHP Info Page

Delete that file once you have confirmed it works. phpinfo publishes your full configuration: extensions, paths, versions, environment variables. It is exactly the reconnaissance an attacker would otherwise have to guess at, and a test.php sitting in a document root is one of the more common things scanners look for.

Worth being clear about the versions here as well. Ubuntu 16.04 passed its standard support window in 2021 and PHP 7.0 stopped receiving security fixes long before that, so neither should be carrying a public site today. The install steps themselves have barely changed on newer releases, and the package names are the part that moves: a current Ubuntu wants a newer PHP version number in place of 7.0 throughout that install line.

Avatar photo

Asif Khan

I have spent over 10 years working across IT systems, open source software, DevOps, Linux administration and cloud operations. Three things drive most of what I do: automation, security and resilience. Much of that work involves planning and building the platforms that sit behind services people rely on daily, which means designing for failure just as carefully as for load. Cloud computing held my attention early on, largely for its flexibility. Being able to scale up and then back down again means far less guessing about how much capacity you will need. Across projects I work with the full DevOps toolchain, from provisioning, orchestration and configuration management through to release management and microservices architecture.