VPS: Setup LAMP stack - Linux, Apache, MySQL, PHP
This guide was created with the following products:
(Details may vary with products from different providers but the main concepts remain the same)
Introduction
The LAMP stack is a popular selection of open-source software which are setup together to allow for simple dynamic website hosting, with a particular focus on PHP websites and apps. The acronym stands for: Linux as the OS (operating system), Apache as the web server, MySQL as the database and lastly PHP for processing. In this guide, we will cover the process of setting up a LAMP stack on a Linux VPS, with a detailed breakdown and example of setting up a to-do list website.
Preparation
Begin by connecting to your server via SSH. If you don't know how to do this, please have a look at our Initial access (SSH) guide.
In this guide, we will be using Ubuntu as the Linux distribution. The instructions are the same for Debian and should be similar for other distributions, but the syntax of commands for example may vary slightly. Ensure that you have an OS installed and are connected to the server via SSH.
As always, before proceeding with the installation, ensure that all packages are up to date via the following command:
// Ubuntu & Debian
sudo apt update
// CentOS
sudo yum update
// OpenSUSE
sudo zypper up
// Fedora
sudo dnf upgrade --refresh
Installation
The installation can be split up easily into each core LAMP dependency, beginning with the Apache web server, followed by MySQL database and lastly PHP. Throughout the installation, we will setup a test website which is written in PHP and will access the MySQL database. Lastly each web request will be processed and served through the Apache web server.
Setting up Apache
Apache is the web server that will be used to process incoming web requests and serve responses. Install it with the following command.
sudo apt install apache2
Once installed, you should ensure that the appropriate firewall rules are created to ensure that the web server is accessible to the internet. In this example, we will use the UFW Firewall since Apache has a registered application for this.
If you are using a different firewall, ensure that you allow port 80 (HTTP) through the firewall. You can learn more about firewalls in Linux via our Manage Firewall guide.
Ensure that UFW firewall is enabled and also ensure that a rule for SSH is created.
# Create a rule to allow SSH
sudo ufw allow OpenSSH
# Enable UFW Firewall
sudo ufw enable
Ensure that you have a rule setup for SSH if you are using UFW Firewall! If you do not, you will not be able to SSH into the server again if you lose connection to your current session!
Now create the rule to allow Apache and afterwards check to ensure that the rules are present.
# Create a rule to allow Apache
sudo ufw allow in "Apache Full"
# Check the UFW firewall rules
sudo ufw status
You can view which profiles are available by running the ufw app list
command. In the example above, using Apache Full
means that both HTTP (port 80) and HTTPS (port 443) rules are created.
You should see Apache
and Apache (v6)
rules with ALLOW
actions set, which confirms that the firewall is ready. You should also see other rules that you may have previously setup, including the SSH rule.
With the firewall opened up for Apache, you should now ensure that Apache is functional. You can do this by attempting to access your IP address in a browser, as following: http://[your_ipaddress]
If it is functional, you should see a default welcome page. If you cannot, check the status of the service using the following command: systemctl status apache2
Setting up MySQL
Now you will install and setup a MySQL server which will act as your database to persistently store data in a relational manner. Install it with the following command.
sudo apt install mysql-server
After this is finished, it is recommended to run a secure installation script which ensures that your MySQL server instance remains secure. This is optional but highly recommended. You can run this via the sudo mysql_secure_installation
command.
This will take you through an interactive setup. At first, you will be prompted about password validation. We recommend selecting Y
to ensure only secure passwords in the future are allowed and then selecting either MEDIUM
via 1
or STRONG
via 2
.
Next you will be prompted about removing the anonymous
user and disallowing root login remotely. For both we strongly recommend accepting via Y
for security implications. This ensures that the test user is removed and that the master root
user can only be used locally via SSH and not anywhere else, reducing risk.
Finally, you will be prompted about removing the test
database and reloading the privilege tables. Once again we recommend accepting via Y
since the test table is not needed and you need to reload the privilege table for adjustments to take place.
Now check if the MySQL database is running using the following command to attempt to login: sudo mysql -u root
. If successful, you should see a welcome message appear. You can exit it using the quit
command once ready.
Setting up PHP
The final LAMP dependency is PHP and this is quite simple to install. The following command installs PHP alongside a plugin for Apache and MySQL, to allow for Apache to work with PHP and to allow PHP to use MySQL.
sudo apt install php libapache2-mod-php php-mysql
Confirm that the installation was successful by checking the version. If you see a version output, this means that PHP is functioning correctly.
php -v
For advanced use cases, you may require additional PHP extensions to allow for extra functionality. You can view a list of these by running the apt search php- | less
command.
Use the arrow keys to scroll and press Q
once ready to quit. Now to install an extension package, simply use the apt install command as following. You can enter multiple extensions at once, separated by a space to make the installation faster.
sudo apt install [php_extension] [...]
We recommend adjusting the directory index to ensure that index.php
files take precedence over the default .html
. Open the file using the following command.
sudo nano /etc/apache2/mods-enabled/dir.conf
In the nano editor, remove index.php
and move it to the front of the list, as following:
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
Save the file and quit nano by using CTRL + X
, followed by Y
to confirm and lastly ENTER
. Now restart Apache for this to take effect using sudo systemctl restart apache2
.
Creating Test Website
With the installation of each LAMP dependency now complete, we will now create a test website to present how the LAMP stack works together to form a great dynamic website solution. This is completely optional, but it is useful to understand how you can utilise these tools to setup your own websites.
In this example, we will create a small to-do list website via PHP which will fetch and return to-do entries. This will be stored on a MySQL database table and will be served through Apache.
We will also be using a test domain of zapdocs.example.com
throughout, since in a real-world scenario you would likely utilise a domain. You must setup an A
type DNS record for the domain which points at the IP Address of your server. If you require help with this, please browse our Domain Records guide.
You can choose not to use a domain and replace mentions of [your_domain]
with a regular name. You would then access the website via the IP address. However, do note that when creating the virtual host file later on, you should remove the ServerName
parameter.
Setting up Apache
Typically across web servers, all website files and data is stored under the /var/www
directory. By default, Apache usually comes with a html
directory which contains a default page. To ensure that everything is organised especially when hosting many websites on a single Apache instance, we recommend setting up each website in an individual directory or folder.
To do this, you can simply create a new folder in the /var/www/[your_domain]
directory for each website domain. In this example, this will be /var/www/zapdocs.example.com
.
sudo mkdir /var/www/[your_domain]
Now you will create a new Apache virtual host configuration file in the sites-available
directory for this domain and folder.
sudo nano /etc/apache2/sites-available/[your_domain].conf
Use the template below and copy it into the nano editor, replacing [your_domain]
with the domain you are using.
<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>
This new virtual host file handles port 80 (HTTP) requests and checks whether the request matches the ServerName
specified, in this case your domain. It also points that the /var/www/[your_domain]
folder that you created previously should be used to serve files.
Save the file and quit nano by using CTRL + X
, followed by Y
to confirm and lastly ENTER
. We recommend using the sudo apache2ctl configtest
command to ensure that the file doesn't contain any syntax errors.
The final step for Apache configuration is to enable the new virtual host by using a2ensite
.
sudo a2ensite [your_domain]
If you are not using a domain, remove the ServerName
line or uncomment by prefixing it with a #
hashtag. You will also have to disable the default virtual host by using the sudo a2dissite 000-default
command.
Finally restart Apache for the new virthual host to take effect using the following command: sudo systemctl restart apache2
.
Creating Website
Now that you have configured Apache through the new virtual host and document folder, it is time to create the actual website that will be served. At the moment, the folder is empty therefore nothing will be served. We will be creating a small to-do website as previously mentioned for this domain.
Preparing Database
To begin, let's create a new database and table to store each list item. Login to your MySQL server.
sudo mysql -u root
Now let's create a new todowebsite
database and a todoitems
table within it.
# Create database
CREATE DATABASE todowebsite;
# Use the new database
USE todowebsite;
# Create a new items table in the database
CREATE TABLE todoitems (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
is_completed BOOLEAN DEFAULT FALSE,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
With the table ready, let's create a few sample entries for now.
INSERT INTO todoitems (name, is_completed) VALUES ('Create ZAP-Docs Guide', 0);
INSERT INTO todoitems (name, is_completed) VALUES ('Buy a ZAP-Hosting Server', 1);
INSERT INTO todoitems (name, is_completed) VALUES ('Join ZAP-Hosting Discord', 0);
INSERT INTO todoitems (name, is_completed) VALUES ('Have a great day!', 0);
Lastly, let's create a dedicated todo
user which will be used specific for this website.
# Create a dedicated user
# Replace [your_password] with your own password
CREATE USER todo@localhost IDENTIFIED BY '[your_password]';
# Set privilages for the user (copy as one)
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER
ON todowebsite.*
TO todo@localhost;
# Reload privileges
FLUSH PRIVILEGES;
With the database now prepared and the user ready, you can exit the MySQL terminal via the quit
command once ready.
PHP Website Files
The final part of this example is setting up the actual PHP website file for the to-do page. This will be done through a new index.php
file in the /var/www/[your_domain]
directory that you have created earlier. Open the nano editor to create a file there.
sudo nano /var/www/[your_domain]/index.php
Now below we have prepared a simple code snippet that you can place into the nano editor for a basic to-do page which returns the items that are stored in the database. The first PHP section established a MySQL connection to your database.
You must change the [your_password]
field to the password you have set for the todo
user earlier.
The subsequent HTML section contains the main web page which create an unordered list, looping through each of the results.
<?php
// Prepare MySQL Connection
$servername = "localhost";
$username = "todo";
$password = "[your_password]";
$dbname = "todowebsite";
// Create Connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check whether the connection was successful, if not return an error
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Run an SQL query to return entries from the table and set it as the result variable
$sql = "SELECT id, name, is_completed, creation_date FROM todoitems ORDER BY creation_date DESC";
$result = $conn->query($sql);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF--8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do List</title>
</head>
<body>
<h1>Awesome To-Do List :D</h1>
<p>For our awesome ZAP-Hosting guide: <a href="https://zap-hosting.com/guides/docs/vserver-linux-lamp-stack">https://zap-hosting.com/guides/docs/vserver-linux-lamp-stack</a></p>
<ul>
<?php
// Check whether there are any results
if ($result->num_rows > 0) {
// Loop through each item of the returned array from the query
foreach ($result as $entry) {
echo "<li>";
// Display the name and use htmlspecialchars to prevent XSS (cross-site scripting)
echo htmlspecialchars($entry["name"]);
// Display the completion status
if ($entry["is_completed"]) {
echo " <strong>(Completed)</strong>";
} else {
echo " <strong>(Incomplete)</strong>";
}
// Display creation date
echo " - Creation Date: " . htmlspecialchars($entry['creation_date']);
echo "</li>";
}
} else {
// If none are found, return a default message
echo "<li>No to-do items found.</li>";
}
?>
</ul>
</body>
</html>
<?php
// Close database connection
$conn->close();
?>
Once you have copied this into the nano editor, save the file and quit nano by using CTRL + X
, followed by Y
to confirm and lastly ENTER
.
Testing the Website
You have successfully followed along and setup a test to-do website which utilises all of the aspects of the LAMP stack!
You should now be able to access the website via the domain (using http
/port 80) you have defined previously in the virtual host file, with this being zapdocs.example.com
in this example. The end result should look like the following:
Conclusion
Congratulations, you have successfully installed and setup the LAMP stack! As the next step, we highly recommend setting up a domain and SSL certificate to ensure that data is transmitted securely to your websites. Please view our Certbot guide with a focus on the Apache Plugin and follow the interactive setup to quickly and easily setup a certificate for your chosen domain.
For further questions or assistance, please don't hesitate to contact our support team, which is available daily to assist you! 🙂