---
slug: Setting Up a LAMP Stack on Ubuntu 16.04  A Step-by-Step Guide
title: Setting Up a LAMP Stack on Ubuntu 16.04  A Step-by-Step Guide
authors: [slorber, yangshun]
tags: [hola, docusaurus]
---

<!-- truncate -->

import CodeBlock from '@site/src/components/CodeBloack';
import ubuntu from '@site/static/img/small_apache_default.png';
import php_info from '@site/static/img/small_php_info.png';


<div className="head">Introduction</div><br/>
<div className="text">The LAMP stack is a combination of open-source software that works together to turn a computer into a capable server for hosting websites and web applications. Let's break it down:</div>
<div className="text"><ul><li>L is for Linux: Linux is the operating system that our server uses</li><li>A is for Apache: Apache is the web server that helps our computer communicate with the internet and showcase our websites.</li><li>M is for MySQL: MySQL is the database where our server stores all the important data for our websites.</li><li>P is for PHP: PHP is the language that assists our server in processing and displaying dynamic content on our websites.</li></ul></div>

<div className="text">In this guide, we'll install the LAMP stack on an Ubuntu 16.04 server, making our computer a reliable platform for hosting websites. Ubuntu is the operating system that supports Linux in this process. Let's get started on setting up our server!</div>

<div className="head">Before We Start</div><br/>
<div className="text">Before we dive into this guide, make sure you have a special user account set up on your server. This account should have the power to do extra important tasks and we'll call it the "sudo" account.</div><br/>

<div className="text">If you're not sure how to set up this special account, don't worry! We have a beginner-friendly tutorial that'll walk you through it. Just follow steps 1 to 4 in our "initial server setup for Ubuntu 16.04" guide. Once that's done, you'll be all set to continue with this guide. Let's get started!</div>


<div className="head">Setting Up Apache and Securing Your Server</div><br/>

<div className="text">The Apache web server is a popular tool that helps your computer show websites to the world. It's been used for a long time and is known for doing a great job.We can easily get Apache on our computer using something called Ubuntu's "package manager." It's like an organized store where you can find and install software without any trouble. </div> <br/>

<div className="text">We'll also make sure our computer's security is strong by adjusting the firewall. This is like putting up a protective wall around our server to keep it safe from any potential issues on the internet. Don't worry, it's not complicated! We'll guide you through each step. Let's begin!</div><br/>

<div className="text">For what we're doing, you can kick things off by typing in these commands:</div>

<CodeBlock code={`sudo apt-get update
sudo apt-get install apache2`} /><br/>

<div className="text">Because we're using a special command called "sudo," these actions will be carried out with extra permissions, almost like having a superpower. It'll ask for your usual password to make sure you're the one doing it</div> <br/>

<div className="text">After you type your password, your computer will let you know which things it's going to install and how much extra space they'll need. Just type "y" and press ENTER to keep going, and then it'll start installing. Easy, right?</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Configuring ServerName to Avoid Syntax Warnings</div>

<div className="text">Next, we're going to make a quick change in a file called /etc/apache2/apache2.conf to stop a warning message. This warning is not a big deal, but it's like a little reminder from the computer. If you don't set ServerName everywhere it needs to be, the computer might give you a message when it checks for mistakes in how it's set up. We'll fix that with just one line. Let's do it!</div>

<CodeBlock code={`sudo apache2ctl configtest`} /><br/>
<CodeBlock code={`Output
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK
`} /><br/>

<div className="text">Now, let's open up the main configuration file using your text editor.</div>

<CodeBlock code={`sudo nano /etc/apache2/apache2.conf`} /><br/>

<div className="text">Now, scroll to the bottom of the file, and add a line that tells the computer your main web address. If you don't have a special web address yet, don't worry! You can use your computer's public IP address instead. Let's make that small addition.</div><br/>

<div className="note"><strong>Note</strong>:  If you're not sure about your computer's special address on the internet, don't worry. We'll show you how to find it in the next part. Just skip ahead to that section, and we'll get it sorted out.</div>

<CodeBlock code={`. . .
ServerName server_domain_or_IP
`} /><br/>

<div className="text">Once you've added that line, save the changes and close the file. It's like making sure you keep the updates you just did and shutting the door behind you. All set!</div><br/>

<div className="text">Now, let's see if everything looks good by typing:</div>

<CodeBlock code={`sudo apache2ctl configtest`} /><br/>

<div className="text">Now that we've added that special ServerName thing, what you should see is:</div>

<CodeBlock code={`Output
Syntax OK
`} /><br/>


<div className="text">To make everything work with your new settings, let's restart Apache. It's like giving your computer a little refresh so it can use the changes you made. Let's do it!</div>

<CodeBlock code={`sudo systemctl restart apache2`} /><br/>

<div className="text">Now, it's time to make sure our computer's protective wall (firewall) is set up correctly. Think of it like setting up a security guard for your server. Let's get started!</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Configuring the Firewall for Web Traffic</div>
<div className="text">If you've set up the firewall following the initial server setup, now we want to ensure it allows the right kind of traffic for your website. Think of it as making sure the firewall knows to allow visitors.We'll check if the firewall has a specific setting for Apache, the web server we installed earlier, and make sure everything is configured correctly. Let's double-check and make sure everything is good to go!</div>

<CodeBlock code={`sudo ufw app list`} /><br/>

<CodeBlock code={`Output

Available applications:
  Apache
  Apache Full
  Apache Secure
  OpenSSH
`} /><br/>

<div className="text">Check the Apache Full profile, and you should see that it allows traffic to ports 80 and 443.</div>

<CodeBlock code={`sudo ufw app info "Apache Full"`} /><br/>

<CodeBlock code={`Output
Profile: Apache Full
Title: Web Server (HTTP,HTTPS)
Description: Apache v2 is the next generation of the omnipresent Apache web
server.
Ports:
  80,443/tcp
`} /><br/>

<div className="text">Make sure incoming traffic is allowed for this profile.</div>

<CodeBlock code={`sudo ufw allow in "Apache Full"`} /><br/>

<div className="text">You can quickly check to make sure everything is working by opening your web browser and visiting your server's public IP address. If you're not sure what your public IP address is, don't worry, we'll show you how to find it in the next section.</div>

<CodeBlock code={`http://your_server_IP_address`} /><br/>
<div className="text">When you visit your server's public IP address in the web browser, you'll see a basic page that comes with Ubuntu 16.04 and Apache. This page is there to give you information and check if everything is working well. It will look something like this</div><br/>

<img src={ubuntu} alt="small_apache_default" />


<div className="text">If you see this page, it means your web server is set up correctly and can be reached through your firewall. Great job!</div>

<div className="text" style={{ fontSize:'28px' }}>Locating Your Server's Public IP Address</div><br/>

<div className="text">If you're not sure about your server's public IP address, don't worry; we can easily find it. This is the address you use to connect to your server through SSH.</div><br/>

<div className="text">To get this address, you can use a couple of commands from the command line. First, you can type the following to find it:</div>

<CodeBlock code={`ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'`} /><br/>

<div className="text">When you run this command, you'll see two or three lines showing different addresses. They're all correct, but your computer might only be able to use one of them. You can try each one to see which works.</div><br/>

<div className="text">Another way is to use a tool called curl to ask a special server what your IP address is. Here's how you can do that:</div>

<CodeBlock code={`sudo apt-get install curl
curl http://icanhazip.com
`} /><br/>

<div  className="text">No matter how you find your IP address, you can simply type it into your web browser's address bar to access your server.</div><br/>

<div className="head">Setting Up MySQL</div>
<div className="text">Now that our web server is all set, let's get MySQL installed. MySQL is like a really organized system that takes care of storing and managing information for our website.</div><br/>

<div className="text">We'll use the same tool, apt, to easily get and install MySQL. This time, we'll also grab some extra "helper" packages to make sure all our different parts can talk to each other smoothly. Let's get started!</div>

<CodeBlock code={`sudo apt-get install mysql-server`} /><br/>

<div className="note"><strong>Note</strong>: In this situation, you don't need to run a special command called sudo apt-get update before this one. We already did that a little while ago when we installed Apache. So, our computer's list of available software is already fresh and ready to go. No need to do it again!</div> <br/>

<div  className="text">Once again, you'll see a list showing what will be installed and how much space it will take up. Just type 'Y' and press Enter to keep going.</div><br/>

<div className="text">While it's installing, your server will ask you to pick and confirm a password for the MySQL "root" user. This user has special privileges in MySQL. Think of it as an important password, like the main key to the server. Make sure it's a strong and unique password, and don't leave it empty. Let's get that set up!</div><br/>

<div className="text">Once the installation is finished, we need to run a simple security script to make sure everything is safe. This script will fix some potential problems and make our database system a bit more secure. Just run the following command to start the script:</div>

<CodeBlock code={`mysql_secure_installation`} /><br/>

<div className="text">You'll need to enter the password you set for the MySQL root account. Then, it'll ask if you want to set up the VALIDATE PASSWORD PLUGIN.</div><br/>

<div className="warn"><strong>Warning</strong>: Deciding to turn on this feature is a bit like making a choice. If you turn it on, MySQL will reject passwords that don't meet certain rules. However, this can create problems if you use a simple password with software that sets up MySQL credentials automatically, like the Ubuntu packages for phpMyAdmin. It's okay to leave this turned off, but it's really important to always use strong and unique passwords for your database.</div><br/>

<div className="text">Type 'y' if you want to turn it on, or type anything else if you want to continue without enabling it.</div>

<CodeBlock code={`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:
`} /><br/>

<div className="text">Now, it will ask you to choose a level for password validation. If you pick level 2, which is the strongest, keep in mind that you'll get errors if you try to set a password that doesn't have numbers, both uppercase and lowercase letters, special characters, or if it's based on common words. Choose the level that suits your preference and security needs.</div>

<CodeBlock code={`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
`} /><br/>

<div className="text">If you turned on password validation, it will show you how strong your current password is and ask if you want to change it. If you like your current password, just type 'n' for "no" when it asks.</div>

<CodeBlock code={`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
`} /><br/>

<div className="text">For the other questions, just press 'Y' and then hit the Enter key each time it asks. This will get rid of some extra users and a test database, stop remote root logins, and apply these new rules right away so MySQL follows the changes we made.</div> <br/>

<div className="text">Now, your database system is all ready, and we can move on to the next steps.</div>

<div className="head">Configuring PHP</div><br/>

<div className="text">PHP is like the part of our setup that makes things happen on our website. It's the one that takes care of running special codes, talking to our MySQL databases to get information, and then handing over the processed content to our web server so it can show up on the website.</div><br/>

<div className="text">To make it work, we'll use the apt system again to install PHP and some helper packages. These helpers make sure that PHP and the Apache server can work together smoothly and talk to our MySQL database. Let's get it set up!</div>

<CodeBlock code={`sudo apt-get install php libapache2-mod-php php-mcrypt php-mysql`} /><br/>

<div className="text">Installing PHP is usually straightforward. We'll check to make sure everything's okay soon.</div>

<div className="text">Usually, when someone asks for a folder on our server, Apache looks for a file named index.html first. But we want to make Apache look for index.php files instead. It's like telling the server to prefer PHP files over HTML files.</div>

<CodeBlock code={`sudo nano /etc/apache2/mods-enabled/dir.conf
<IfModule mod_dir.c>
    DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
</IfModule>
`} /><br/>

<div className="text">We want to make sure our server looks for PHP files first when someone asks for a folder. To do this, we'll move the PHP index file we talked about earlier to the top of the list after the "DirectoryIndex" instruction. It's like telling the server, "Hey, check for PHP files first!</div>


<CodeBlock code={`<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>
`} /><br/>

<div className="text">When you're done, save and close the file by pressing Ctrl-X. Confirm the save by typing 'Y' and press Enter.</div><br/>

<div className="text">After that, we need to restart the Apache web server so it recognizes the changes we made. You can do this by typing the following command:</div>

<CodeBlock code={`sudo systemctl restart apache2`} /><br/>

<div className="text">We can also see how things are going with the Apache web server by using a command called systemctl.</div>

<CodeBlock code={`sudo systemctl status apache2`} /><br/>


<CodeBlock code={`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
           └─apache2-systemd.conf
   Active: active (running) since Wed 2016-04-13 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
Apr 13 14:28:42 ubuntu-16-lamp systemd[1]: Stopped LSB: Apache2 web server.
Apr 13 14:28:42 ubuntu-16-lamp systemd[1]: Starting LSB: Apache2 web server...
Apr 13 14:28:42 ubuntu-16-lamp apache2[13605]:  * Starting Apache httpd web server apache2
Apr 13 14:28:42 ubuntu-16-lamp apache2[13605]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerNam
Apr 13 14:28:43 ubuntu-16-lamp apache2[13605]:  *
Apr 13 14:28:43 ubuntu-16-lamp systemd[1]: Started LSB: Apache2 web server.
`} /><br/>

<div className="text" style={{ fontSize:'28px' }}>Adding Extra Features to PHP</div>
<div className="text">If you want to make PHP even more powerful, you can choose to install some extra features called modules.</div><br/>

<div className="text">To see what's available, think of it like checking a menu – you can look at all the options using a command called apt-cache search. It's a bit like exploring a menu and then scrolling through it with a tool called less. Let's check it out</div>

<CodeBlock code={`apt-cache search php- | less`} /><br/>

<div className="text">You can use the arrow keys to move up and down, and press 'q' when you're done to exit.</div><br/>

<div className="text">These results show you extra things you can add if you want. Each one has a short description to help you understand what it does.</div>

<CodeBlock code={`libnet-libidn-perl - Perl bindings for GNU Libidn
php-all-dev - package depending on all supported PHP development packages
php-cgi - server-side, HTML-embedded scripting language (CGI binary) (default)
php-cli - command-line interpreter for the PHP scripting language (default)
php-common - Common files for PHP packages
php-curl - CURL module for PHP [default]
php-dev - Files for PHP module development (default)
php-gd - GD module for PHP [default]
php-gmp - GMP module for PHP [default]
…
:
`} /><br/>

<div className="text">To find out more about what each module does, you can either search on the internet or check the detailed description of the package by typing:</div>

<CodeBlock code={`apt-cache show package_name`} /><br/>

<div className="text">When you run this command, you'll see a lot of information. Look for a field called "Description-en" – it has a longer explanation of what each module does.</div>

<div className="text">For instance, if you want to know more about the php-cli module, you can type this:</div>

<CodeBlock code={`apt-cache show php-cli`} /><br/>

<div className="text">Among the information shown, you'll find something that looks like this:</div>

<CodeBlock code={`Output
…
Description-en: 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 Debian's default
 PHP version (currently 7.0).
`} /><br/>

<div className="text">If you've done your research and want to add a package, you can do that using the same command we've used to install other software.</div>

<div className="text">For instance, if you've decided that you need php-cli, you can type:</div>

<CodeBlock code={`sudo apt-get install php-cli`} /><br/>

<div className="text">Now, your LAMP stack is all set up and ready to go. However, let's make sure PHP is working properly by doing a quick test.</div><br/>

<div className="head">Trying Out PHP on Your Website Server</div>

<div className="text">To make sure everything is set up right for PHP, we'll make a simple PHP script.<br/>
Let's name this script info.php. To make sure Apache can find and show it correctly, we need to save it in a special folder called the web root<br/>On Ubuntu 16.04, this folder is at /var/www/html/. We can put the file there by typing:</div>

<CodeBlock code={`sudo nano /var/www/html/info.php`} /><br/>

<div className="text">This will open a new empty file. We'll then add some code into it, which is proper PHP language. Here's what we need to add:</div>

<CodeBlock code={`<?php
phpinfo();
?>
`} /><br/>

<div className="text">Once you're done, save the file and close it.<br/>
Now, let's see if our web server can show what our PHP script generates. To check, we just need to go to a specific page in our web browser. You'll need your server's public IP address again.<br/>
The page you want to go to is:</div>

<CodeBlock code={`http://your_server_IP_address/info.php`} /><br/>

<div className="text">The page you'll see should look a bit like this:</div>

<img src={php_info} alt="small_php_info" /><br/>

<div className="text">This page gives you info about your server using PHP. It's handy for checking things and making sure your settings are right.</div><br/>

<div className="text">If it worked, your PHP is doing what it should.</div><br/>


<div className="text">After this test, it's a good idea to delete this file because it might reveal info about your server to people who shouldn't see it. To delete it, just type:</div>

<CodeBlock code={`sudo rm /var/www/html/info.php`} /><br/>

<div className="text">If you ever need the info again, you can always make this page once more.</div> <br/>

<div className="con">Conclusion:</div>

<div className="text">Now that you've set up a LAMP stack, you're ready to do a lot of cool stuff! Basically, you've got a system that lets you install many different types of websites and web tools on your server. But before you go further, it's important to make sure your website is secure. That means making sure people can connect to it safely using HTTPS. The easiest way to do this is by using Let’s Encrypt. They offer a free TLS/SSL certificate to secure your site.</div><br/>

<div className="text"><strong>Ready to secure your website? Get started with Let’s Encrypt now!</strong></div>