---
slug: Creating Your Website Installing the LAMP Stack on Ubuntu 20.04
title: Creating Your Website Installing the LAMP Stack on Ubuntu 20.04
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 hello from '@site/static/img/landing_page.png'
import php from '@site/static/img/php7.4.13.jpg'
import todo from '@site/static/img/todo_list.png'

<div className="head">Introduction</div>

<div className="text">In simple terms, a "LAMP" stack is a bundle of open-source software installed together to make a server capable of hosting dynamic websites and web apps built in PHP. "LAMP" stands for Linux (the operating system), Apache (the web server), MySQL (the database), and PHP (the programming language).</div><br/>

<div className="text">In this guide, we'll show you how to set up a LAMP stack on an Ubuntu 20.04 server.</div><br/>


<div className="head">What You Need Before Starting</div>
<div className="text">Before we start, make sure you have an Ubuntu 20.04 server set up. You'll also need a user account with sudo privileges and a basic firewall. If you haven't done this yet, you can follow our guide for setting up your server.</div><br/>

<div className="head">Step 1 —Setting Up Apache and Securing Your Connection</div>

<div className="text">Apache is one of the most popular web servers globally. It's widely used, well-supported, and has been a key part of the internet for a long time. That's why it's a fantastic option for hosting websites.</div><br/>

<div className="text">Let's get started by updating the package manager cache. If it's your first time using sudo in this session, you'll be asked for your password to confirm that you have the necessary privileges to manage system packages with apt.</div>

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

<div className="text">Next, let's put Apache on your computer! Just type this command and hit enter:</div>

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

<div className="text">After you type the command to install Apache, your computer might ask you a question. Just press "Y" on your keyboard and then hit enter.</div><br/>

<div className="text">Once Apache is finished installing, we need to make sure your computer's security settings allow it to work properly. We'll use something called UFW to do this. UFW has different settings for different types of programs and we'll pick the one for Apache.To see all the different settings UFW has, just type this command:</div>

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

<div className="text">You'll see some information on your screen that looks like this:</div>

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

<div className="text">Here's what each of these options means:</div>

<div className="text"><ol><li>Apache: This option allows regular web traffic on port 80, like opening the main door for visitors.</li><li>Apache Full: It allows both regular web traffic (port 80) and secure traffic using TLS/SSL encryption (port 443).</li><li>Apache Secure: This option only opens the special secure door for traffic using TLS/SSL encryption (port 443).</li></ol></div>


<div className="text">For now, it's a good idea to only allow connections through the main door (port 80). Since we just installed Apache and haven't set up a special security certificate yet, it's not ready for secure traffic (HTTPS).</div><br/>

<div className="text">To do this, we'll use the Apache profile:</div>

<CodeBlock code={`sudo ufw allow in "Apache"`} /><br/>
<div className="text">You can make sure everything is working by checking with:</div>

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

<CodeBlock code={`Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                                
Apache                     ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)                    
Apache (v6)                ALLOW       Anywhere (v6) 
`} /><br/>

<div className="text">Now, your firewall is letting traffic through the main door (port 80).
To make sure everything is working, you can quickly check by opening your web browser and visiting your server's public IP address. If you're not sure what your public IP address is, there's a note in the next section that will help you find it.</div>

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

<div className="text">When you visit your server's address in the web browser, you'll see a special page that comes with Ubuntu 20.04 and Apache. This page is just there to give you information and check if everything is set up correctly. It might look something like this:</div><br/>


<img src={ubuntu} alt="Ubuntu Page" /> <br/>

<div className="text">If you can see this page, it means your web server is all set up and working properly. You've successfully installed it, and people can now visit your website through the firewall. Good job!</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 public IP address (the special code to find your server on the internet), there are a couple of easy ways to check. This is the address you use when you want to connect to your server, for example using SSH.</div><br/>

<div className="text">One way is to use a tool called "iproute2." It's like a detective tool for your computer. You can find your IP address by typing this command:</div>

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

<div className="text">When you type that command, your computer will show you two or three lines of information. All of them are correct addresses, but your computer might only be able to use one. You can try each one to see which works.</div><br/>

<div className="text">Another way is to use a tool called "curl." It's like sending a message to a special server and asking, "Hey, what's my IP address?" You can do this by typing a command:</div>

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

<div className="text">No matter how you found your IP address, just copy and paste it into the address bar of your web browser. This way, you can check out the default Apache page and see if everything is working as expected.</div><br/>

<div className="head">Step 2 — Your Database: Installing MySQL</div>

<div className="text">Now that your web server is ready, let's add the database system. This helps store and manage data for your website. MySQL is a popular choice for this, especially when you're using PHP.</div><br/>

<div className="text">Just like before, we'll use the "apt" tool to get and install MySQL. It's a simple command:</div>

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

<div className="text">When your computer asks if you want to install MySQL, just type "Y" and press ENTER.</div><br/>

<div className="text">After the installation, it's a good idea to make things more secure. There's a special tool that comes with MySQL to help with this. It's like a virtual security assistant for your database. To use it, just type a command:</div>

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

<div className="text">This will check if you want to set up something called the VALIDATE PASSWORD PLUGIN.</div>

<div className="note"><strong>Note</strong>:  Deciding to turn on this feature is up to you. If you enable it, MySQL will only accept passwords that meet certain criteria. However, it's okay to leave this validation turned off. Just make sure to always use strong and unique passwords for your database – that's important!</div><br/>

<div className="text">Type "Y" if you want to turn it on, or press any other key if you want to continue without turning it on.</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">If you say "yes," you'll need to choose how strict you want the password rules to be. If you pick level 2 for the strongest rules, keep in mind that your passwords must have numbers, both upper and lower case letters, special characters, or should not be common words. If this sounds a bit confusing or strict, you can choose a lower level for simpler rules.</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 decided to use the password check feature or not, your server will now ask you to choose and confirm a password for the MySQL root user. This is different from the system root. The database root user is like a super admin with full control over the database system.Even though MySQL usually doesn't need a password for the root user by default, it's safer to set a strong password here. We'll discuss why in a moment</div><br/>

<div className="text">If you turn on password validation, you'll see how strong your root password is. Your server will then ask if you want to keep that password. If you're happy with it, just type "Y" for "yes" when prompted.</div>

<CodeBlock code={`Estimated strength of the password: 100 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
`} /><br/>

<div className="text">For the remaining questions, just press "Y" and then press the ENTER key each time. This will remove some unnecessary users and databases, make sure remote logins are secure, and apply these changes to MySQL right away.</div><br/>

<div className="text">Once you're done, let's check if you can log in to the MySQL console. Just type:</div>

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

<div className="text">This command will connect you to the MySQL server as the main admin user, called "root." This is automatically done using special permission ("sudo") when you run the command. You'll see some information displayed on your screen, which should look like this:</div>

<CodeBlock code={`Output
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.19-0ubuntu5 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

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/>

<div className="text">To leave the MySQL console, just type:</div>

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


<div className="text">Even though you set a password during the setup, you might notice that you didn't have to enter it when logging in as the root user. This might seem unusual, but it's actually a security feature. The default way to log in as the main MySQL admin is a bit different – it uses the system's authentication instead of a password. This makes your database server more secure because only users with special permissions (like sudo privileges) can log in as the root MySQL user. In simple terms, you won't be using this root user directly for your website. The password you set is like a backup plan, just in case the default login method changes in the future.</div><br/>

<div className="text">To make things more secure, it's a good idea to create separate user accounts for each database, especially if you're planning to have more than one database on your server. This way, each database has its own special access, and it helps keep everything safer.</div><br/>

<div className="note"><strong>Note : </strong>As of now, the standard library used by PHP for MySQL doesn't work perfectly with the default way MySQL 8 checks passwords. So, when you're setting up users for your PHP applications, you'll need to configure them to use a specific method called "mysql_native_password." We'll show you how to do that later on.</div>

<div className="text">Your MySQL server is all set up and safe. Now, let's move on to installing PHP, which is the last piece needed for the LAMP stack.</div><br/>

<div className="head">Step 3 - Adding PHP to Your Setup</div>

<div className="text">Now that your server can show web pages and manage data, let's bring in PHP. This is what makes your website do cool things by processing code. To make it work smoothly, we'll install the "php" package. Also, we need "php-mysql" to let PHP talk to MySQL, and "libapache2-mod-php" to help Apache handle PHP files. Don't worry about these names; they'll be installed automatically.</div><br/>

<div className="text">Just type this command to get everything set up:</div>

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

<div className="text">After everything is installed, you can check your PHP version by typing the following command:</div>

<CodeBlock code={`php -v`} /><br/>

<CodeBlock code={`Output
PHP 7.4.3 (cli) (built: Jul  5 2021 15:13:35) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies`} /><br/>


<div className="text">Now that your LAMP stack is up and running, it's almost ready for your website. But before you test it with a PHP script, let's make sure everything is organized. We'll set up a special space in Apache called a "Virtual Host" to hold all your website's files and folders. We'll do that in the next step.</div><br/>

<div className="head">Step 4 - Organizing Your Website: Creating a Virtual Host</div>

<div className="text">When you're running a website using the Apache web server, you can create something called virtual hosts. These are like individual compartments that hold all the settings for a specific website. They allow you to host more than one website on a single server. In this guide, we'll set up a pretend domain called your_domain. But remember, you should use your own domain name instead of "your_domain". Let's get started!</div><br/>

<div className="text">Apache on Ubuntu 20.04 comes with a default setup that serves web pages from a directory called /var/www/html. This works fine if you only have one website. However, if you want to host multiple websites, it can get messy. Instead of changing the default setup, we'll create a new directory for each website within the /var/www folder. This way, the /var/www/html directory will still be there to serve pages if no specific website is requested.</div><br/>

<div className="text">To do this for your_domain, follow these steps:</div>

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

<div className="text">Next, we need to give you control over the directory we just created. To do this, we'll use a special code that references your username on the system. This ensures that you have the necessary permissions to manage the files and folders inside.</div>

<CodeBlock code={`sudo chown -R $USER:$USER /var/www/your_domain`} /><br/>

<div className="text">Next, we'll open a new file where we can configure our website settings. We'll do this in a specific directory where Apache keeps these configuration files. We'll use a basic text editor called nano for this task.</div>

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

<div className="text">This will make a new empty file where we can put some basic settings for our website. Copy and paste the following simple configuration into this file.</div>

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

<div className="text">Now, to save and close the file, if you're using the nano editor, press CTRL+X, then Y, and finally ENTER.</div><br/>

<div className="text">With this configuration, Apache knows to use the /var/www/your_domain folder as the place to find the files for your website. If you don't have a domain name yet or just want to test things out, you can ignore the ServerName and ServerAlias options for now.</div><br/>

<div className="text">Once you've saved and closed the file, you can activate the new virtual host by running the command:</div>

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

<div className="text">If you're not using a custom domain name, you may want to turn off the default website that Apache comes with. This is important because otherwise, Apache's default setup will take precedence over your new virtual host.</div><br/>

<div className="text">To do this, you just need to type the following command:</div>

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

<div className="text">To double-check that there are no mistakes in your configuration file, you can run the following command:</div>

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

<div className="text">Finally, to apply these changes and make them active, you just need to reload Apache. You can do this by running the following command:</div>

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

<div className="text">Your new website is up and running, but there's nothing in the web folder yet. To test if everything is working correctly, we'll create a simple web page. Navigate to the /var/www/your_domain directory, and create a new file called index.html. This file will contain the content of your webpage.</div>

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

<div className="text">Inside the index.html file, add the following content:</div>

<CodeBlock code={`<html>
  <head>
    <title>your_domain website</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <p>This is the landing page of <strong>your_domain</strong>.</p>
  </body>
</html>
`} /><br/>

<div className="text">Now, open your web browser and type in the domain name or IP address of your server just like you did before. This will allow you to see if your website is now accessible and displaying the content you added to the index.html file.</div>

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

<div className="text">You should see a page that looks like this:</div><br/>

<img src={hello} alt="landing Page" /> <br/>

<div className="text">If you're seeing this page, it confirms that your Apache virtual host is set up correctly.</div><br/>

<div className="text">You can keep this index.html file as a temporary landing page for your website until you're ready to replace it with an index.php file if you're using PHP. Once you've set up your index.php file, make sure to delete or rename the index.html file from your website's main folder. Otherwise, the index.html file will show up instead of your index.php file when someone visits your website.</div>

<div className="text" style={{ fontSize:'28px' }}>Understanding DirectoryIndex in Apache Web Server</div>

<div className="text">By default, Apache gives priority to a file named index.html over an index.php file. This can be handy for showing maintenance pages on your website. For example, if you need to do some updates on your PHP application, you can create a temporary index.html file with a message for visitors. Since Apache will show index.html first, it becomes the main page during maintenance. After you're done, just rename or delete index.html, and your PHP application will be back as the main page.</div><br/>

<div className="text">If you want to switch this behavior, you'll have to adjust the configuration in a file called dir.conf located in the /etc/apache2/mods-enabled/ directory. This file controls the order in which Apache looks for default files like index.php or index.html when someone visits your website. You can change the order here to prioritize index.php over index.html if you prefer.</div>

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

<div className="text">After you've made the changes to the dir.conf file and saved it, you need to reload Apache to apply these changes. This ensures that Apache follows the new order you've set for default files like index.php or index.html.</div>

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

<div className="text">Next, we'll make a simple PHP script to make sure PHP is working properly on your server. This script will help us confirm that PHP is installed and set up correctly.</div><br/>

<div className="head">Step 5 — Checking PHP Setup: Testing PHP Processing on Your Web Server</div>

<div className="text">Now, we'll make a special file to check if PHP is working on your server. This file will help us see if Apache can correctly handle and process PHP files.</div><br/>

<div className="text">Simply create a new file called info.php inside the folder where you put your website's files.</div>

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

<div className="text">When the file is opened, copy and paste the following text. This text contains code that PHP can understand and execute.</div>

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

<div className="text">Once you've added the code, save and close the file.<br/><br/>
Now, to test if everything is working correctly, open your web browser and type in your server's domain name or IP address, followed by "/info.php" in the address bar. This will allow you to see if the PHP script runs as expected.</div>

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

<div className="text">You should see a page that looks like this:</div><br/>

<img src={php} alt="php Page" /> <br/>

<div className="text">This page shows details about your server as seen by PHP. It's helpful for troubleshooting and making sure your settings are correct.</div><br/>

<div className="text">If you can view this page in your browser, it means PHP is set up correctly on your server.</div><br/>

<div className="text">After you've checked the information on the page, it's a good idea to delete the file you created. This is because it contains sensitive details about your PHP setup and your server. You can remove it using the command "rm":</div>

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

<div className="text">If you ever need to see this information again, you can easily recreate the page. So don't worry about deleting it now. If you need the details in the future, you can just make the file again.</div>

<CodeBlock code={`Step 6 — Checking Database Connection with PHP (Optional)`} /><br/>

<div className="text">If you're interested in seeing if PHP can communicate with MySQL and perform database operations, you can set up a simple test. First, we'll create a test database and a new MySQL user with the right permissions to access it. This will ensure everything is set up properly before proceeding.</div><br/>

<div className="text">As of now, the built-in MySQL PHP library called mysqlnd doesn't work with the default authentication method (caching_sha2_authentication) used in MySQL 8. So, we have to create a new user with a different authentication method (mysql_native_password) to make sure PHP can connect to the MySQL database correctly.</div> <br/>

<div className="text">Let's create a database called "example_database" and a user named "example_user". But if you prefer different names, feel free to choose them.</div><br/>

<div className="text">To start, let's open the MySQL console using the root account.</div>

<CodeBlock code={`sudo mysql`} /><br/>
<div className="text">To make a new database, type the following command into your MySQL console:</div><br/>

<div className="text">CREATE DATABASE example_database;</div><br/>

<div className="text">Now, let's create a new user and give them full access to the database we just made.<br/>
Use the following command to create a new user named "example_user". We'll set their default authentication method to "mysql_native_password". We'll also assign the password "password" to this user. However, for security reasons, it's crucial to replace "password" with a strong, unique password of your choice.</div>

<CodeBlock code={`CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';`} /><br/>

<div className="text">Next, we have to grant permission to the "example_user" over the "example_database" database. This allows the user to perform operations on this database.</div>

<CodeBlock code={`GRANT ALL ON example_database.* TO 'example_user'@'%';`} /><br/>

<div className="text">With this command, the "example_user" will have complete control over the "example_database" database, but they won't be able to make changes to other databases on your server.<br/> <br/> To leave the MySQL shell, simply type:</div><br/>

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

<div className="text">To check if the new user has the correct permissions, you can log in to the MySQL console again, but this time using the credentials of the user you just created.</div>

<CodeBlock code={`mysql -u example_user -p`} /><br/>

<div className="text">In this command, you'll see the "-p" flag, which means MySQL will ask you to enter the password for the "example_user" you created earlier. Once you've logged in to the MySQL console, check if you can access the "example_database" database.</div>

<CodeBlock code={`SHOW DATABASES;`} /><br/>

<div className="text">After running the command, you should see something like this on your screen:</div>

<CodeBlock code={`Output
+--------------------+
| Database           |
+--------------------+
| example_database   |
| information_schema |
+--------------------+
2 rows in set (0.000 sec)
`} /><br/>

<div className="text">Next, we're going to make a test table called "todo_list". Go back to your MySQL console and type in the following command:</div>

<CodeBlock code={`CREATE TABLE example_database.todo_list (
	item_id INT AUTO_INCREMENT,
	content VARCHAR(255),
	PRIMARY KEY(item_id)
);

`} /><br/>

<div className="text">Once you've checked that your test table has the correct data, you can leave the MySQL console by typing:</div>

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

<div className="text">Now, let's make the PHP script that connects to MySQL and retrieves your data. To do this, create a new file in the folder where your website's files are stored. We'll use a simple text editor called nano for this task.</div>

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

<div className="text">Below is a PHP script that connects to your MySQL database, retrieves the content of the todo_list table, and displays the results in a list format. If there's an issue with the database connection, it will show an error message.</div>

<CodeBlock code={`<?php
$user = "example_user";
$password = "password";
$database = "example_database";
$table = "todo_list";

try {
  $db = new PDO("mysql:host=localhost;dbname=$database", $user, $password);
  echo "<h2>TODO</h2><ol>"; 
  foreach($db->query("SELECT content FROM $table") as $row) {
    echo "<li>" . $row['content'] . "</li>";
  }
  echo "</ol>";
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}
`} /><br/>

<div className="text">Once you've finished editing the file, save and close it.</div><br/>

<div className="text">Now, you can view this page in your web browser by entering your website's domain name or public IP address, followed by "/todo_list.php".</div>

<CodeBlock code={`http://your_domain_or_IP/todo_list.php`} /><br/>

<div className="text">When you visit the page in your web browser, you should see something similar to this, displaying the content you added to your test table:</div><br/>

<img src={todo} alt="todo Page" /> <br/>

<div className="text">This indicates that your PHP setup is working correctly and can communicate with your MySQL server.</div><br/>


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

<div className="text">In this guide, you've set up a reliable system for hosting PHP websites and applications using Apache as your web server and MySQL as your database. Now, it's important to make sure your website connections are secure. You can do this by enabling HTTPS, which encrypts data between your website and your visitors' browsers. To do this easily and for free, you can use Let’s Encrypt to get a TLS/SSL certificate.</div><br/>

<div className="text"><strong>Ready to secure your website? Check out our guide on how to set up HTTPS with Let’s Encrypt.</strong></div>