---
slug: Ubuntu 18.04 LAMP Stack Setup Step-by-Step Guide
title: Ubuntu 18.04 LAMP Stack Setup 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 lamp from '@site/static/img/LampStack.jpg';

<div className="head">Introduction</div>
<div className="text">Think of a 'LAMP' stack like a group of helpful computer tools that work together to create awesome websites. Let's meet the team:</div>
<div className="text"><ol><li>L for Linux: This is like the computer's main system.</li><li>A for Apache: Meet the web server, it helps people see your website.</li><li>M for MySQL: Imagine this as a smart storage space where your website keeps important things.</li><li>P for PHP: This is the creative part that makes your website do cool and interesting stuff.</li></ol></div>

<div className="text">Now, we're going to set up this friendly team on a computer using Ubuntu 18.04. Ready to get started?</div><br/>

<div className="head">What You Need Before We Begin</div>
<div className="text">Before we start, make sure you have a special kind of computer called an 'Ubuntu 18.04 server.' Also, you'll need a special account on that computer that can do important things, like installing stuff. We'll guide you on how to set this up in an easy way. Let's get started!</div><br/>


<div className="text" style={{ fontSize:'28px' }}>Step 1: Installing Apache and Setting Up the Firewall</div>

<div className="text">Apache is a common web server used to host websites. It works great with PHP to make dynamic websites. Let's get it installed and make sure our computer's security is set up.</div>

<div className="text">Start by making sure your computer has the latest updates by typing:</div>
<CodeBlock code={`sudo apt update`} /><br/>

<div className="text">If it's your first time using 'sudo' today, it might ask for your usual computer password to make sure you're allowed to do special things.</div>

<div className="text">After updating, let's get Apache installed. Just type:</div>

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

<div className="text">After typing the command, your computer will tell you about some things it wants to add. It will also say how much space it needs. Just press 'Y' and then 'ENTER' to say 'Yes,' and it will start adding everything.</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Making Sure Your Firewall Welcomes Web Traffic</div>
<div className="text">Now, let's make sure the security system on your computer is ready to let in web visitors. If you followed our setup guide before, we want to tell it to allow people to see our website.</div><br/>

<div className="text">Check if the firewall knows about Apache by typing:</div>

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

<CodeBlock code={`Output
Available applications:
  Apache
  Apache Full
  Apache Secure
  OpenSSH
`} /><br/>

<div className="text">If you check the details of the Apache Full profile, you'll find that it allows visitors to come in through 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">To let people visit your website, type the following to allow incoming traffic for both regular websites and secure websites:</div>

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

<div className="text">To make sure everything is working, open your web browser and visit your computer's special address. If you're not sure what it is, we'll show you how to find it in the next part.</div>

<CodeBlock code={`http://your_server_ip`} /><br/>

<div className="text">When you open the web browser, you might see a page that comes with Ubuntu 18.04 and Apache. Don't worry, it's just there to show things are working fine. It should look a bit like this:</div>

<img src={ubuntu} alt="small_apache_default" />
<div className="text">If this page shows up, it means your web server is set up properly and can be reached through the firewall.</div><br/>


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

<div className="text">If you're not sure about your server's special address that everyone can use to connect to it, don't worry. We'll show you a few easy ways to find it. This address is usually what you use to talk to your server through SSH.</div><br/>

<div className="text">One way to find it is by using some simple commands. Let's start with this one:</div>

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

<div className="text">After typing the command, you'll get a couple of lines. Each line is a correct address, but your computer might only use one of them. You can try each one to see which works.</div><br/>

<div className="text">Another way is to use a special tool called 'curl' to ask an external friend what address it sees for your server. It's like getting a second opinion. Let's try this:</div>

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

<div className="text">No matter how you found your special address, just type it into the top bar of your web browser. This will show you the default Apache page and confirm everything is working fine.</div><br/>


<CodeBlock code={`Step 2: Setting Up MySQL`} /><br/>

<div className="text">Now that your web server is ready, let's add MySQL. It's like a smart organizer for your website's information. It stores and helps manage all the data your site needs.</div> <br/>

<div className="text">Just like before, we'll use 'apt' to get and install MySQL. Ready?</div>

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

<div className="note"><strong>Note</strong>: No need to run 'sudo apt update' again before this command. You already did it earlier when installing Apache. Your computer's list of available software is already updated and ready to go.</div><br/>

<div className="text">After typing the command, it will show you a list of things it's going to add and how much space they'll take up. Just type 'Y' to keep going.</div><br/>

<div className="text">Once it's finished installing, let's run a security script that's already included with MySQL. This script helps keep your database safe by fixing some risky settings and making sure only authorized users can access it.</div><br/>

<div className="text">To start the security script, type:</div>

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

<div className="text">It will ask if you want to set up a password-checking tool. This tool helps make sure your passwords are strong and secure.</div>

<div className="text"> Deciding to turn on this feature is a personal choice. If you enable it, MySQL will reject passwords that aren't very strong, which is good for security. However, it might cause problems if you use certain software, like phpMyAdmin. If you're not sure, it's okay to leave this off. Just make sure to always use strong and unique passwords for your database.</div>

<CodeBlock code={`Type 'Y' if you want to turn it on, or type anything else if you'd rather continue without enabling it.
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">If you say 'yes,' it will ask you to pick how strict you want the password rules. If you choose the strongest level (entering '2'), it will give you errors if your password doesn't have numbers, both uppercase and lowercase letters, and special characters. So, choose carefully based on how strong you want your passwords to be.</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">Whether you chose the password-checking tool or not, your computer will now ask you to pick and confirm a password for the main user of your database (MySQL root user). This user has full control over everything in the database.Even though this user doesn't always need a password, it's a good idea to give one for extra safety. We'll discuss this in a bit.</div><br/>

<div className="text">If you turned on password checking, it will tell you how strong your password is. Then, it will ask if you want to change it. If you like your password, just type 'N' for 'no' and keep it.</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 press the ENTER key. This will do a few things like removing some users and a test database, and making sure remote logins aren't allowed for the main user.</div><br/>

<div className="text">Once you're done, let's check if you can get into the MySQL console by typing:</div>
<CodeBlock code={`sudo mysql`} /><br/>

<div className="text">This will let you into the MySQL server as the main user, which is called 'root.' We're using 'sudo' to do this. You should see something like this after typing the command:</div>
<CodeBlock code={`Output
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.34-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.


Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
`} /><br/>

<CodeBlock code={`To leave the MySQL console, just type:`} /><br/>

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

<div className="text">Even though you set a password during setup, you didn't need to type it here. That's because the way your computer checks passwords is a bit different for the main user.This might seem odd, but it actually makes things safer. Only users with special access, like you using the console or certain applications, can log in as the main MySQL user. In everyday terms, this means you won't use this user for your regular website. Having a password is still a good idea, just in case things change in the future.</div><br/>

<div className="text">For better security, it's a good idea to create separate user accounts with limited access for each database you have, especially if you'll have more than one database on your server. You can learn how to do this in our guide: 'Creating a New User and Setting Permissions in MySQL'. It has step-by-step instructions to help you set up MySQL users and manage who can access your databases.</div><br/>

<div className="text">Now that your MySQL server is set up and safe, let's move on to installing PHP, the last part of the LAMP stack.</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Step 3: Adding PHP</div>
<div className="text">PHP is like the brain that makes your website do things. It processes code, connects to your databases, and shows dynamic content to visitors.</div><br/>

<div className="text">Let's use 'apt' again to add PHP. We need three packages: 'php' for PHP itself, 'libapache2-mod-php' to connect PHP with Apache, and 'php-mysql' so PHP can talk to MySQL. Type this command to get them all:</div>

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

<div className="text">PHP should install smoothly. We'll check it shortly to make sure everything's working.</div><br/>


<div className="text" style={{ fontSize:'28px' }}>Changing How Apache Shows Directory Contents (Optional)</div>
<div className="text">Sometimes, you might want Apache to prioritize certain files when someone visits a directory on your website. By default, Apache looks for an 'index.html' file first. But if you want it to look for 'index.php' files first, we can change that.</div><br/>

<div className="text">To do this, we'll edit a configuration file called 'dir.conf.' We'll use a simple text editor called 'nano.</div>

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

<div className="text">You'll see something like this:</div>

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

<div className="text">Now, take the highlighted 'index.php' and move it to the top of the list, like this:</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, press CTRL+X to save and close the file. Confirm by typing 'Y' and pressing ENTER.<br/><br/>
Then, restart the Apache web server so it can apply your changes. Just use this command:</div>

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

<div className="text">To see if Apache is running okay, you can use the following command:</div>

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

<CodeBlock code={`Sample Output
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
  Drop-In: /lib/systemd/system/apache2.service.d
           └─apache2-systemd.conf
   Active: active (running) since Thu 2021-07-15 09:22:59 UTC; 1h 3min ago
 Main PID: 3719 (apache2)
    Tasks: 55 (limit: 2361)
   CGroup: /system.slice/apache2.service
           ├─3719 /usr/sbin/apache2 -k start
           ├─3721 /usr/sbin/apache2 -k start
           └─3722 /usr/sbin/apache2 -k start
Jul 15 09:22:59 ubuntu1804 systemd[1]: Starting The Apache HTTP Server...
Jul 15 09:22:59 ubuntu1804 apachectl[3694]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' di
Jul 15 09:22:59 ubuntu1804 systemd[1]: Started The Apache HTTP Server.
`} /><br/>

<div className="text">To exit this status display, simply press the 'Q' key.</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Adding Extra Features to PHP (Optional)</div>
<div className="text">If you want to do more with PHP, you can add extra modules. To see what's available, use this command:</div>
<CodeBlock code={`apt search php- | less`} /><br/>

<div className="text">You can use the arrow keys to move up and down, and press 'Q' to exit.<br/><br/>
These results show extra things you can add to PHP. Each one has a brief explanation.</div>

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

<div className="text">If you want to know more about what a module does, you can search online for information about it. Or, you can see a detailed description of the package by typing:</div>
<CodeBlock code={`apt show package_name`} /><br/>

<div className="text">You'll see a bunch of information. Look for the 'Description' field; it gives a detailed explanation of what each module does.<br/><br/>
For instance, to understand the php-cli module, you can type</div>

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

<div className="text">Among other details, you'll see something like this:</div>
<CodeBlock code={`Output
…
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).
…
`} /><br/>

<div className="text">If you find a package you want to install after researching, you can use the 'apt install' command just like before.<br/><br/>
For example, if you want to install php-cli, you would type:</div>

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

<div className="text">If you need to install multiple modules, you can list them all after the 'apt install' command, separated by spaces, like this:</div>

<CodeBlock code={`sudo apt install package1 package2 ...`} /><br/>

<div className="text">Now that your LAMP stack is set up, it's a good idea to create an Apache virtual host to store your server's configuration details. This helps in managing your website.</div><br/>

<div className="text" style={{ fontSize:'28px' }}>Step 4 — Setting Up a Virtual Host for Multiple Domains on Apache</div>
<div className="text">Let's create a virtual host to manage configuration details and host multiple domains on your Apache web server. In this guide, we'll use a domain called 'your_domain,' but make sure to replace it with your actual domain name. If you're not sure how to set up a domain with Cloudtopiaa, check our Introduction to Cloudtopiaa DNS guide</div><br/>

<div className="text">By default, Ubuntu 18.04 comes with one server block that serves content from /var/www/html. While this is fine for a single site, managing multiple sites can get messy. To keep things neat, let’s make a new space for your_domain within /var/www, leaving /var/www/html as the default if no specific site is requested.</div><br/>

<div className="text">Create the directory for your_domain like this:</div>

<CodeBlock code={`sudo mkdir /var/www/your_domain`} /><br/>

<div className="text">Now, let’s make sure the directory is owned by the current user. This is done with the $USER variable, which represents the user currently logged in:</div>

<CodeBlock code={`sudo chown -R $USER:$USER /var/www/your_domain`} /><br/>
<div className="text">To verify the permissions of your web root directory, you can use the following command:</div>

<CodeBlock code={`sudo chmod -R 755 /var/www/your_domain`} /><br/>

<div className="text">Then, let's create a simple index.html page using the nano text editor or any other editor you prefer:</div>

<CodeBlock code={`nano /var/www/your_domain/index.html`} /><br/>

<div className="text">Inside the file, paste the following example HTML code:</div>

<CodeBlock code={`<html>
    <head>
        <title>Welcome to Your_domain!</title>
    </head>
    <body>
        <h1>Success!  The your_domain server block is working!</h1>
    </body>
</html>
`} /><br/>

<div className="text">After you've added the HTML, save the file and close it.</div><br/>
<div className="text">To make sure Apache serves this page correctly, we need to create a virtual host configuration file. Instead of changing the default configuration file directly, we'll create a new one specifically for your domain. We'll save it as /etc/apache2/sites-available/your_domain.conf.</div>

<CodeBlock code={`sudo nano /etc/apache2/sites-available/your_domain.conf`} /><br/>
<div className="text">Next, copy and paste the following configuration block into the file. This block is similar to the default one, but it's tailored for our new directory and domain name.</div>

<CodeBlock code={`<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName your_domain
    ServerAlias www.your_domain
    DocumentRoot /var/www/your_domain
    ErrorLog $ {APACHE_LOG_DIR}/error.log
    CustomLog $ {APACHE_LOG_DIR}/access.log combined
</VirtualHost>
`} /><br/>

<div className="text">Also, note that we've changed the DocumentRoot to our new directory and the ServerAdmin to an email address accessible by the administrator of the your_domain site. Additionally, we've included two directives: ServerName, which sets the base domain for this virtual host, and ServerAlias, which specifies additional names that should match as if they were the base name.</div><br/>

<div className="text">Once you're done, save and close the file.</div><br/>

<div className="text">To enable the file, use the command: a2ensite your_domain.conf"</div>

<CodeBlock code={`sudo a2ensite your_domain.conf`} /><br/>

<div className="text">Next, let's turn off the default site configuration defined in 000-default.conf:</div>

<CodeBlock code={`sudo a2dissite 000-default.conf`} /><br/>

<div className="text">You'll see the following result:</div>
<CodeBlock code={`Output
Syntax OK
`} /><br/>

<div className="text">Restart Apache to make your changes take effect:</div>
<CodeBlock code={`sudo systemctl restart apache2`} /><br/>

<div className="text">You can check if Apache is working with your domain by visiting http://your_domain. If everything is set up correctly, you'll see a page like this:<br/><br/>
Now that your virtual host is ready, it's a good idea to test your PHP configuration to ensure everything works smoothly before making further changes or deploying an application.</div><br/>


<div className="head">Testing PHP Setup on Your Web Server</div>
<div className="text">To check if PHP is set up correctly, let's create a PHP script called info.php. This file needs to be saved in the web root directory we set up earlier.<br/><br/>
Create the file in the web root directory by running:</div>

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

<div className="text">Create a new file by running the command below. This will open a blank file. Copy and paste the following text into the file. This text contains valid PHP code:</div>

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

<div className="text">After saving and closing the file, it's time to check if your web server can display content generated by the PHP script. To do this, open your web browser and enter the following address into the address bar. You'll need to use your server's public IP address or domain name again.</div><br/>

<div className="text">Here's the address you should visit:</div>

<CodeBlock code={`http://your_domain/info.php`} /><br/>
<div className="text">The page you'll see should look like this:</div><br/>

<img src={lamp} alt="LAMP" />

<div className="text">This page gives you some simple information about your server using PHP. It's handy for checking if everything is set up correctly.</div><br/>

<div className="text">If you can view this page in your browser, it means PHP is working well.</div><br/>

<div className="text">Remember to delete this file after testing, as it might share details about your server. To remove it, just use this command:</div>

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

<div className="text">You can make this page again if you ever need to check your server info in the future.</div><br/>


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

<div className="text">Now that you have set up your LAMP stack, you have various options for what to do next. One important step is to make sure that when people visit your website, their connection is secure. This is done through HTTPS. Follow our simple guide on securing your Apache server with Let's Encrypt to add a free security certificate to your site.</div><br/>

<div className="text">Ready to secure your website? Check out our guide on setting up HTTPS with Let's Encrypt!</div><br/>


<div className="text" style={{ textAlign: 'center' }}><strong>Secure Your Site Now!</strong>: </div>