---
slug: Complete Guide Installing LAMP Stack on Debian 11
title: Complete Guide Installing LAMP Stack on Debian 11
authors: [slorber, yangshun]
tags: [hola, docusaurus]
---

<!-- truncate -->

import CodeBlock from '@site/src/components/CodeBloack';
import debian from '@site/static/img/debian.png';
import debian11 from '@site/static/img/debian11.png';
import todo from '@site/static/img/todo_list.png';

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

<div className="text">A 'LAMP' stack is a group of open-source software that is commonly installed together to allow a server to host dynamic websites and web apps. This term stands for:
Linux: the operating system,
Apache: the web server,
MariaDB: the database where website data is stored,
PHP: the language used to create dynamic content.</div><br/>

<div className="text">While MySQL is often used as the database management system, some Linux distributions, like Debian, use MariaDB as a replacement. In this guide, you'll learn how to install a LAMP stack on a Debian 11 server, using MariaDB as the database management system.</div><br/>


<div className="head">Preparing Your Debian 11 Server</div>

<div className="text">Before we start, make sure you have a Debian 11 server ready. You'll also need a user account with sudo privileges and a basic firewall set up. If you haven't done this yet, you can check our beginner's guide on setting up your Debian 11 server for help.</div><br/>

<div className="head">Step 1 - Apache Installation and Firewall Update</div>
<div className="text">Apache is one of the most popular web servers worldwide. It's well-supported, has a large community, and has been used for hosting websites for a long time, making it a reliable choice.</div><br/>

<div className="text">Let's begin by updating the package manager cache. If this is your first time using 'sudo' in this session, you'll need to enter your password to confirm you have the necessary permissions to manage system packages with 'apt'.</div>

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

<div className="text">Next, let's install Apache. You can do this by running the following command:</div>

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


<div className="text">After running the installation command, you'll be asked to confirm if you want to install Apache. Simply type 'Y' and press ENTER to proceed. Once Apache is installed, we need to make sure our firewall allows web traffic. If you've followed our initial server setup guide and enabled the UFW firewall, you'll need to allow HTTP and HTTPS traffic through it.</div><br/>

<div className="text">On Debian 11, UFW has predefined profiles for applications. You can see the full list of these profiles by running:</div>

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

<div className="text">The WWW profiles you see listed are for controlling the ports that web servers use.</div>


<CodeBlock code={`Output
Available applications:
. . .
  WWW
  WWW Cache
  WWW Full
  WWW Secure
. . .
`} /><br/>

<div className="text">If you check the details of the "WWW Full" profile using the command 'ufw app info', you'll see that it allows traffic to go through ports 80 and 443.</div>

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

<CodeBlock code={`Output
Profile: WWW Full
Title: Web Server (HTTP,HTTPS)
Description: Web Server (HTTP,HTTPS)

Ports:
  80,443/tcp
`} /><br/>

<div className="text">Now, let's enable incoming HTTP and HTTPS traffic for this profile:</div>

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

<div className="text">To confirm that everything is working correctly, open your web browser and visit your server's public IP address.</div>

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

<div className="text">You'll see the default Apache web page for Debian 11, which is there to give you some basic information and to test that Apache is working properly.</div><br/>

<img src={debian} alt="Debain" /> <br/>

<div className="text">If you see this page in your browser, it means your web server is installed correctly and can be accessed through your firewall.</div><br/>

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

<div className="text">Finding your server's public IP address is essential for accessing it from other devices or services. Here are some simple methods to do so: Using Command Line Tools: You can use the command line to find your IP address. One way is to utilize the iproute2 tools. Using Online Services: Alternatively, you can visit a website that displays your public IP address. Simply open your web browser and search for "what is my IP address," and you'll find various websites that provide this information.</div><br/>

<div className="text">Once you have your server's public IP address, you can use it to connect to your server through SSH or access it via a web browser.</div>

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

<div className="text">When you run the command to find your server's IP address, you might see two or three lines of information. Each line represents a different address, but your computer may only use one of them. You can try each one to see which works.</div><br/>

<div className="text">Another way to find your IP address is by using the curl utility to ask an outside server. Here's how to do it:</div>

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

<div className="text">Choose any method you like and use it to find your IP address. Then, enter this IP address into your web browser to check if your server is showing the default Apache page.</div><br/>


<div className="head">Step 2: Setting Up Your Database with MariaDB</div>

<div className="text">Now that your website is live on the web server, you need a database system to store and organize data for your site.<br/><br/>
In Debian 11, the package used to install MySQL server has been replaced by default-mysql-server, which actually installs MariaDB. MariaDB is a community version of MySQL. To put it simply, when you install default-mysql-server, you're getting MariaDB by default. It's the recommended choice for MySQL-compatible databases on Debian-based systems.</div><br/>

<div className="text">For better compatibility in the long run, it's suggested to install MariaDB directly using its actual package, which is called "mariadb-server".</div><br/>

<div className="text">To install MariaDB, simply enter the following command:</div>

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

<div className="text">Once the installation is complete, it's a good idea to run a security script that's included with MariaDB. This script helps to improve the security of your database by removing some insecure default settings and restricting access.To start the interactive security script, run the following command:</div>

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

<div className="text">This script will guide you through a series of questions to improve the security of your MariaDB setup. The first question will ask for the current database root password. It's important to note that this is not the same as the system root password. The database root user is an administrative user with full control over the database system. Since you've just installed MariaDB and haven't set a password yet, simply press ENTER when prompted.</div><br/>

<div className="text">Next, you'll be asked if you want to set a password for the database root user. MariaDB uses a secure authentication method for the root user by default, so you don't need to set a password at this time. Simply type 'N' for "No" and then press ENTER.</div><br/>

<div className="text">After that, you can press 'Y' and then ENTER to accept the default settings for the remaining questions. This will remove any anonymous users and the test database, disable remote root login, and apply these changes immediately so that MariaDB will enforce the new rules you've set.</div><br/>

<div className="text">Once you've completed the security script, you can log in to the MariaDB console.</div>

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

<div className="text">When you run this command, it will connect you to the MariaDB server as the administrative user 'root'. This is implied by using 'sudo' with the command.You should see output similar to the following:</div>

<CodeBlock code={`Output
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 41
Server version: 10.5.15-MariaDB-0+deb11u1 Debian 11
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
`} /><br/>


<div className="text">You may have noticed that you didn't need to enter a password to connect as the root user. This is because the default way MariaDB authenticates the administrative user 'root' is through the system's authentication method, not with a password. While this might seem concerning initially, it actually enhances security. Only system users with sudo privileges can log in as the MariaDB root user, either directly from the console or through an application running with those same privileges. In simple terms, this means you won't be able to use the MariaDB root user to connect from a PHP application, which is a good security measure.</div><br/>

<div className="text">For better security, it's recommended to create separate user accounts with limited privileges for each database, especially if you're hosting multiple databases on your server.<br/>
To exit the MariaDB console, simply type:</div>

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

<div className="text">Now that your MariaDB server is all set up and secure, it's time to add the final part to our website-building process: PHP</div><br/>

<div className="head">Step 3 — Adding PHP to Your Server</div>

<div className="text">Now that you have Apache to show your website and MariaDB to store your data, it's time to add PHP. PHP is like the behind-the-scenes worker of your setup. It takes care of processing code to show dynamic content on your website. It can run scripts, talk to your MariaDB databases to get information and then pass that information to your web server to display on the website.</div><br/>

<div className="text">You'll also need to install some extra stuff to make PHP work smoothly with your MariaDB database and Apache server. One thing is called php-mysql, which helps PHP talk to databases like MariaDB. Another thing is called libapache2-mod-php, which helps Apache handle PHP files. Don't worry too much about the technical details – just run this command to install everything you need:</div>

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

<div className="text">After the installation finishes, you can check which version of PHP you have by using this command:</div>

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


<CodeBlock code={`Output

PHP 7.4.30 (cli) (built: Jul  7 2022 15:51:43) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.30, Copyright (c), by Zend Technologies
`} /><br/>

<div className="text">Now that your LAMP stack is all set up and ready to go, before you try running any PHP scripts to test it, it's a good idea to create a special place on your server where all your website's files and folders will live. This special place is called an Apache Virtual Host.</div><br/>


<div className="head">Step 4 — Setting Up Your Website's Home on the Server</div>

<div className="text">When you're working with the Apache web server, you can create something called virtual hosts. Think of them like separate compartments that hold settings for different websites on the same server. This lets you host multiple websites on one server. In this guide, we'll set up a pretend domain called "your_domain." But when you do this for your own website, make sure to use your actual domain name instead of "your_domain.</div><br/>

<div className="text">By default, Apache shows its content from a folder at /var/www/html and uses the settings in a file called /etc/apache2/sites-available/000-default.conf. Instead of changing the default website settings at /var/www/html, we'll make a new "virtual host" for testing your PHP setup. Virtual hosts let you manage multiple websites on one Apache server. We'll also make a new folder structure inside /var/www for your_domain website. Don't worry, we'll leave /var/www/html as it is, so it will still show the default page if someone tries to access your server without specifying a particular site.</div><br/>

<div className="text">To start, let's create the main folder for your_domain website:</div>

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

<div className="text">Next, let's make sure you have control over the directory by giving it to you, the user who's currently using the system. We'll use a special code ($USER) that stands for your username on the computer.</div>

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

<div className="text">Now, let's create a new file where we'll put some settings for our website. We'll use a program called nano, which lets us edit files from the command line.</div>

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

<div className="text">This will make a new empty file. Now, let's put some basic settings in it for our website. You can replace "your_domain" with your actual domain name.</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">Once you've finished adding the configuration, save and close the file. If you're using nano, you can do this by pressing CTRL + X, then Y, and finally ENTER.</div><br/>

<div className="text">With this VirtualHost setup, you're instructing Apache to display your website, called your_domain, using the directory /var/www/your_domain as the main place for website files. If you want to try Apache without a specific domain name, you can deactivate the ServerName and ServerAlias options by adding a "#" symbol at the start of each line.</div><br/>

<div className="text">Now, let's activate this virtual host using a command called a2ensite:</div>
<CodeBlock code={`sudo a2ensite your_domain`} /><br/>

<div className="text">if you're not using a custom website address (domain name) and want to make sure your own website shows up correctly, you should turn off Apache's default website. To do this:</div>

<div className="text"><ol><li>Open your Apache settings</li><li>Look for a default website that comes with Apache.</li><li>Turn it off or disable it.</li></ol></div>

<div className="text">This helps ensure that your website, instead of the default one, is the one people see when they visit your web server.</div>

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

<div className="text">To check if you've made any mistakes in your configuration file, use the following command: Run this to make sure everything is set up correctly and there are no errors in your settings.</div>

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

<div className="text">Lastly, refresh Apache to apply these updates: This makes sure that any changes you've made to Apache are put into action</div>

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

<div className="text">Now, let's make a simple PHP test to check if PHP is working on your server: You're going to create a small PHP script to make sure everything is set up correctly.</div><br/>


<div className="head">Step 5 — Checking if PHP is Working on Your Website</div>
<div className="text">Now that you've set up a special place to keep all your website stuff, let's make a little test to be sure Apache can handle PHP files.</div><br/>

<div className="text">Start by making a new file called info.php in the special folder you created for your website:</div>

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

<div className="text">The file is empty right now. Let's add some text to it. Copy and paste the following lines into the file. These lines are like a secret code that PHP understands:</div>

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

<div className="text">After adding the text, save and close the file.</div><br/>

<div className="text">Now, let's check if everything is working. Open your web browser and type in your server's address or IP, followed by the script's name, which is info.php in this case:</div>

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

<div className="text">Now, if everything is set up correctly, you should see a simple PHP web page. It's like a default example page that shows PHP is working on your server.</div><br/>

<img src={debian11} alt="Debain" /> <br/>

<div className="text">This page tells you things about your server using PHP. It helps find and fix issues and makes sure your settings are working right.</div><br/>

<div className="text">If you can view this page in your web browser, it means PHP is working just like it should on your server.</div><br/>

<div className="text">After you've looked at the PHP server details on that page, it's a good idea to delete the file you made. It has some private info about your PHP setup and your server. Just use 'rm' to delete it:</div>

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

<div className="text">If you ever need to see that information again, don't worry. You can make this page again whenever you want.</div><br/>

<div className="head">Step 6 — Optional: Verifying Database Connection with PHP</div>

<div className="text">If you're curious about whether PHP can talk to MariaDB (a type of database) and ask it questions, you can do a little test. First, we need to set up a place to test things out, called a 'test database,' and make a special user who can use it. Let's do that first.</div><br/>

<div className="text">Let's create a database called 'example_database' and a user called 'example_user.' You can use different names if you like.</div><br/>

<div className="text">To start, open up the MariaDB console using the root account:</div>

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

<div className="text">To make a new database, just type this command into your MariaDB console:</div>

<CodeBlock code={`CREATE DATABASE example_database;`} /><br/>

<div className="text">Now, let's make a special user and give them permission to do everything in the database you made.</div><br/>

<div className="text">Use this command to make a new user called 'example_user.' We're setting their password as 'password' for now, but you should pick a strong password of your own:</div>

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

<div className="text">After creating the user, you'll want to give them access to the 'example_database' database:</div>

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

<div className="text">This step ensures that 'example_user' has complete control over the 'example_database' and can't mess with any other databases on your server.</div><br/>

<div className="text">Now, let's make sure these changes are saved and ready to use in the current session:</div>

<CodeBlock code={`FLUSH PRIVILEGES;`} /><br/>

<div className="text">After completing those steps, you can exit the MariaDB shell by:</div>

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

<div className="text">Now, let's check if everything is working by logging into the MariaDB console with the new user details you just created:</div>

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

<div className="text">Make sure to use the -p flag when you run this command. It will ask for the password you set when creating the 'example_user' user. After you're logged in, check if you can access the 'example_database' database:</div>

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


<div className="text">This will show you some information on the screen:</div>

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

<div className="text">Now, let's make a test table called 'todo_list.' In the MariaDB console, type in the following and press Enter:</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">Now, let's add some information to our test table. Type the following command into the MariaDB console a few times, each time with different values, to fill up your test table:</div>


<CodeBlock code={`INSERT INTO example_database.todo_list (content) VALUES ("My first important item");`} /><br/>


<div className="text">To make sure your table has the information you added, type this command:</div>

<CodeBlock code={`SELECT * FROM example_database.todo_list;`} /><br/>

<div className="text">This will show you some information on the screen:</div>

<CodeBlock code={`Output
+---------+--------------------------+
| item_id | content                  |
+---------+--------------------------+
|       1 | My first important item  |
|       2 | My second important item |
|       3 | My third important item  |
|       4 | and this one more thing  |
+---------+--------------------------+
4 rows in set (0.000 sec)
`} /><br/>

<div className="text">Once you've checked that your test table has the right information, you can leave the MariaDB console:</div>

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

<div className="text">Now, let's make a PHP script that talks to MariaDB and asks for your data. Open up your custom web folder and create a new PHP file using the text editor you like:</div>


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


<div className="text">This PHP script connects to the MariaDB database and fetches the information from the 'todo_list' table, showing the results in a list. If something goes wrong with connecting to the database, it will let you know by throwing an exception.</div><br/>

<div className="text">Copy and paste the following code into your 'todo_list.php' script. Don't forget to change the 'example_user' and 'password' values to your own:</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">After making changes, save and close the file.</div><br/>

<div className="text">Now, open your web browser and go to your website's address or IP, followed by '/todo_list.php'. This will take you to the page you just created.</div>

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

<div className="text">This webpage will show the information you added to your test table to anyone who visits it:</div><br/>

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

<div className="text">This tells you that your PHP setup is all set to talk and work with your MariaDB server.</div><br/>

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

<div className="text">In this guide, you've set up a solid base for hosting PHP websites and apps. You used Apache for the web server and MariaDB for the database. Now, let's make sure your website is secure by setting up HTTPS. You can do this with Let's Encrypt. Also, if you want to manage dependencies and packages in PHP, check out our guide on How to Install and Use Composer.</div><br/>

<div className="text"><strong>Ready to secure your website and manage dependencies? Follow our guides to learn how!</strong></div>